javaWeb实战教程4-jdbc连接数据库和junit单元测试

来源:互联网 发布:软考网络规划师论文 编辑:程序博客网 时间:2024/05/21 04:26

javaWeb实战教程


2.5 junit单元测试

我们在平时做代码时,每完成一个方法都需要先测试再提交,在java中比较常用的一个测试方法就是使用junit。

首先在项目中加入junit的jar包:junit-4.7.jar;将jar包复制到WEB-INF/lib目录下。

新建一个包专门存放测试类:cn.funsoftware.Lesson.test,再新建一个类:Lesson6JunitTest

我们可以写一个公有方法,并在方法前加上注释@Test来把这个方法变成一个测试方法,如:

@Testpublic void test1(){    System.out.println("测试方法1运行啦");}@Testpublic void test2(){    System.out.println("测试方法2运行啦");}

在方法上右击run as-junit test。

junit还提供了@Before@After两个注解,使在运行测试方法前,会先运行@Before标记的方法,运行完测试方法后会运行@After标记的方法,且同时运行多个测试方法时,@Before@After都会随每个方法执行多次。

@Beforepublic void before(){    System.out.println("@Before");}@Testpublic void test1(){    System.out.println("测试方法1运行啦");}@Testpublic void test2(){    System.out.println("测试方法2运行啦");}@Afterpublic void after(){    System.out.println("@After");}

junit还提供了@BeforeClass@AfterClass两个注解,被注解标记的方法必须是静态static的,这两个方法分别会在所有测试方法运行前运行和所有方法运行完成后运行:

@BeforeClasspublic static void beforeClass(){    System.out.println("@BeforeClass");}@Beforepublic void before(){    System.out.println("@Before");}@Testpublic void test1(){    System.out.println("测试方法1运行啦");}@Testpublic void test2(){    System.out.println("测试方法2运行啦");}@Afterpublic void after(){    System.out.println("@After");}@AfterClasspublic static void afterClass(){    System.out.println("@AfterClass");}

在类上右击Run As-junit test,得到结果:

@BeforeClass@Before测试方法1运行啦@After@Before测试方法2运行啦@After@AfterClass

通过结果我们能看出@AfterClass@After@BeforeClass@Before的区别。


2.6 jdbc连接数据库

在java中,连接数据库通常是jdbc组件,我们先把jdbc的jar包加入到项目中:mysql-connector-java-5.1.42-bin.jar

使用jdbc连接数据库通常情况下分为以下几个步骤:

  • 加载jdbc驱动:Class.forName("com.mysql.jdbc.Driver");
  • 打开链接:DriverManager.getConnection(数据库地址,用户名,密码);
  • 执行查询:PreparedStatement;
  • 展开结果集:ResultSet;
  • 关闭连接:close;

先在数据库里新建一张表:

CREATE TABLE `type` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `name` varchar(255) DEFAULT NULL,  `type` int(11) NOT NULL,  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;

再在项目中新建一个javaBean来存数据,新建包cn.funsoftware.Lesson.bean,新建类Type.java:

package cn.funsoftware.Lesson.bean;public class Type {    private int id;    private String name;    private int type;    public int getId() {return id;}    public void setId(int id) {this.id = id;}    public String getName() {return name;}    public void setName(String name) {this.name = name;}    public int getType() {return type;}    public void setType(int type) {this.type = type;}}

我们习惯把操作数据库的内容都写到一个叫做XXXDao的类里,新建一个TypeDao.java:

package cn.funsoftware.Lesson.dao;import cn.funsoftware.Lesson.bean.Type;public class TypeDao {    public int add(String name,int type){    }    public void del(int id){    }    public void update(int id,String name,int type){    }    public Type getById(int id){    }}

使用jdbc插入数据:

public int add(String name,int type){    Connection connection = null;    PreparedStatement preparedStatement = null;    ResultSet resultSet = null;    try {        Class.forName("com.mysql.jdbc.Driver");        connection = DriverManager.getConnection(        "jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=true",         "root","000000");        preparedStatement = connection.prepareStatement        ("insert into type (name,type)values(?,?)",                Statement.RETURN_GENERATED_KEYS);        preparedStatement.setString(1, name);        preparedStatement.setInt(2, type);        preparedStatement.execute();        resultSet = preparedStatement.getGeneratedKeys();        if (resultSet.next()) {            System.out.println("插入数据id是" + resultSet.getInt(1));            return resultSet.getInt(1);        }    } catch (Exception e) {        e.printStackTrace();    } finally {        if (resultSet != null)            try {                resultSet.close();            } catch (SQLException e) {                e.printStackTrace();            }        if (preparedStatement != null)            try {                preparedStatement.close();            } catch (SQLException e) {                e.printStackTrace();            }        if (connection != null)            try {                connection.close();            } catch (SQLException e) {                e.printStackTrace();            }    }    return 0;}

我们要保证无论数据库操作是否成功,ResultSet、PreparedStatement、Connection都必须得到关闭,所以在程序代码外嵌套:

    try {        //代码块    }catch (Exception e) {        e.printStackTrace();    } finally {        if (resultSet != null)            try {                resultSet.close();            } catch (SQLException e) {                e.printStackTrace();            }        if (preparedStatement != null)            try {                preparedStatement.close();            } catch (SQLException e) {                e.printStackTrace();            }        if (connection != null)            try {                connection.close();            } catch (SQLException e) {                e.printStackTrace();            }    }

删除操作:

preparedStatement = connection.prepareStatement("delete from type where id=?");preparedStatement.setInt(1, id);preparedStatement.executeUpdate();

更新操作:

preparedStatement = connection.prepareStatement("update type set name=?,type=? where id=?");preparedStatement.setString(1, name);preparedStatement.setInt(2, type);preparedStatement.setInt(3, id);preparedStatement.executeUpdate();

查询操作:

preparedStatement = connection.prepareStatement("select * from type where id=?");preparedStatement.setInt(1, id);resultSet =preparedStatement.executeQuery();if (resultSet.next()) {    Type type=new Type();    type.setId(resultSet.getInt("id"));    type.setName(resultSet.getString("name"));    type.setType(resultSet.getInt("type"));    return type;}

我们来写一个Lesson7Jdbc.java测试一下TypeDao:

public class Lesson7Jdbc {    @Test    public void test() {        TypeDao typeDao=new TypeDao();//      typeDao.add("测试1", 1);//      typeDao.del(6);//      typeDao.update(7, "测试2", 2);        Type type=typeDao.getById(7);        System.out.println(type.getName());    }}

我们现在写好了一个TypeDao.java来操作数据库,但查看代码发现大量的重复代码;java讲究封装,如果重复代码很多,代表程序优化不足,我们可以将部分代码封装,来简化TypeDao.java,也让我们操作数据库更方便。

dao内每个方法都有:

Class.forName("com.mysql.jdbc.Driver");connection = DriverManager.getConnection(        "jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=true", "root",        "000000");

我们可以把加载驱动和打开connection写成一个工具类,在cn.funsoftware.Lesson.utils内新建类DBUtil.java,将两行代码写进去:

public class DBUtil {    static {        try {            Class.forName("com.mysql.jdbc.Driver");        } catch (ClassNotFoundException e) {            e.printStackTrace();        }    }    public static Connection getcConnection() {        try {            return DriverManager.getConnection(                    "jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=true", "root",                    "000000");        } catch (SQLException e) {            throw new RuntimeException(e);        }    }}

其中static{//代码}叫静态代码块,JVM加载类时会执行静态代码块。

这样我们优化下TypeDao.java里的代码:

public int add(String name,int type){    Connection connection = null;    PreparedStatement preparedStatement = null;    ResultSet resultSet = null;    try {        connection = DBUtil.getcConnection();        preparedStatement = connection.prepareStatement("insert into type (name,type)values(?,?)",                Statement.RETURN_GENERATED_KEYS);        preparedStatement.setString(1, name);        preparedStatement.setInt(2, type);        preparedStatement.execute();        resultSet = preparedStatement.getGeneratedKeys();        if (resultSet.next()) {            System.out.println("插入数据id是" + resultSet.getInt(1));            return resultSet.getInt(1);        }    } catch (Exception e) {        e.printStackTrace();    } finally {        if (resultSet != null)            try {                resultSet.close();            } catch (SQLException e) {                e.printStackTrace();            }        if (preparedStatement != null)            try {                preparedStatement.close();            } catch (SQLException e) {                e.printStackTrace();            }        if (connection != null)            try {                connection.close();            } catch (SQLException e) {                e.printStackTrace();            }    }    return 0;}

优化不大,我们再引入一个第三方jar包commons-dbutils-1.6.jar


2.7 commons-dbutils操作数据库

DbUtils是一个为简化JDBC操作的小类库,它的核心代码是QueryRunner和ResultSetHandler,通过使用这两个类可以大幅简化dao内的代码。

2.7.1 closeQuietly

commons-dbutils里提供close()方法,我们刚刚的dao代码里要关闭ResultSet、PreparedStatement、Connection之前,都必须判断是否为NULL,也必须要try{}catch{},使用commons-dbutils就能简单关闭ResultSet、PreparedStatement、Connection:

DbUtils.closeQuietly(resultSet);DbUtils.closeQuietly(preparedStatement);DbUtils.closeQuietly(connection);

2.7.2 QueryRunner做增删改查

commons-dbutils提供了QueryRunner类来简化数据库操作,原本复杂的插入操作可以简化成一句话:

return new QueryRunner().insert(connection, "insert into type (name,type)values(?,?)", new ScalarHandler<Long>(),name,type).intValue();

删除操作:

new QueryRunner().update(connection, "delete from type where id=?",id);

更新操作:

new QueryRunner().update(connection,     "update type set name=?,type=? where id=?",name,type,id);

查询操作:

return new QueryRunner().query(connection,     "select * from type where id=?",     new BeanHandler<>(Type.class),id);

2.7.8 ResultSetHandler将查询数据注入到javaBean里

commons-dbutils还提供了一个ResultSetHandler,可以很方便的将数据库查询出来的数据注入到javaBean中,省去了从resultSet里不停get、set的操作。

  • 查询单个javaBean:BeanHandler;
  • 查询一组javaBean:BeanListHandler;
  • 查询单个字段:ScalarHandler;

查询一组javabean的代码如下:

public List<Type> getList(){    Connection connection = null;    try {        connection = DBUtil.getcConnection();        return new QueryRunner().query(connection, "select * from type", newBeanListHandler<>(Type.class));    } catch (Exception e) {        e.printStackTrace();    } finally {        DbUtils.closeQuietly(connection);    }    return null;}

这样我们改造一下TypeDao.java:

package cn.funsoftware.Lesson.dao;import java.sql.Connection;import java.util.List;import org.apache.commons.dbutils.DbUtils;import org.apache.commons.dbutils.QueryRunner;import org.apache.commons.dbutils.handlers.BeanHandler;import org.apache.commons.dbutils.handlers.BeanListHandler;import org.apache.commons.dbutils.handlers.ScalarHandler;import cn.funsoftware.Lesson.bean.Type;import cn.funsoftware.Lesson.utils.DBUtil;public class TypeDao2 {    public int add(String name, int type) {        Connection connection = null;        try {            connection = DBUtil.getcConnection();            return new QueryRunner().insert(connection, "insert into type (name,type)values(?,?)",                    new ScalarHandler<Long>(), name, type).intValue();        } catch (Exception e) {            e.printStackTrace();        } finally {            DbUtils.closeQuietly(connection);        }        return 0;    }    public void del(int id) {        Connection connection = null;        try {            connection = DBUtil.getcConnection();            new QueryRunner().update(connection, "delete from type where id=?", id);        } catch (Exception e) {            e.printStackTrace();        } finally {            DbUtils.closeQuietly(connection);        }    }    public void update(int id, String name, int type) {        Connection connection = null;        try {            connection = DBUtil.getcConnection();            new QueryRunner().update(connection, "update type set name=?,type=? where id=?", name, type, id);        } catch (Exception e) {            e.printStackTrace();        } finally {            DbUtils.closeQuietly(connection);        }    }    public Type getById(int id) {        Connection connection = null;        try {            connection = DBUtil.getcConnection();            return new QueryRunner().query(connection, "select * from type where id=?", new BeanHandler<>(Type.class),                    id);        } catch (Exception e) {            e.printStackTrace();        } finally {            DbUtils.closeQuietly(connection);        }        return null;    }    public List<Type> getList(){        Connection connection = null;        try {            connection = DBUtil.getcConnection();            return new QueryRunner().query(connection, "select * from type", new BeanListHandler<>(Type.class));        } catch (Exception e) {            e.printStackTrace();        } finally {            DbUtils.closeQuietly(connection);        }        return null;    }}

和之前的TypeDao对比一下,是不是节省很多操作?

原创粉丝点击