JDBC之对Dao层的封装

一、封装的目的和原因

  • 简化Dao层对数据库的操作,希望像可以像数据库中的操作一样,只根据不同的sql语句和sql语句中的参数来达到操作数据库的目的

二、封装增删改查的分析

  • 根据增删改查四种执行语句提取出相同部分进行封装,因为增删改的sql语句在数据库中执行时都只返回影响的行数,且statement对象中的executeUpdate方法可执行增删改三种sql语句,故可以将这三种方法封装成一个方法,返回影响的行数。
  • 将查询方法单独进行封装,返回查询数据的集合。因为不知道具体要查询的数据对应的实体类的属性个数和数据类型,故无法进行数据封装,需要用到泛型来让调用者告知类型,用到接口回调来让调用者实现接口,告知实体类的属性个数和属性类型

三、DaoUtil工具类

1、工具类的实现

public class DaoUtils<T> {
    //对增删改进行封装
    //insert into emp value (?,?,?,?,?,?,?,?)
    public int commonsUpdate(String sql,Object... args){
        //1、获取数据库连接对象Connection
        Connection conn = JDBCUtil.getConn();
        //2、获取数据库操作对象
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(sql);
            //2.1、设置占位符的值
            if(args != null){
                for (int i = 0; i < args.length; i++) {
                    ps.setObject(i+1,args[i]);
                }
            }
            //3、执行SQl语句
            int count = ps.executeUpdate();
            //4、处理结果
            return count;
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            //5、关闭资源
            JDBCUtil.closeAll(conn,ps,null);
        }
        return 0;
    }

    //对查询进行封装
    public List<T> commonsQuery(String sql,RowMapper<T> rowMapper, Object... args){
        //1、获取数据库连接对象Connection
        Connection conn = JDBCUtil.getConn();
        //2、获取数据库操作对象
        PreparedStatement ps = null;
        try {
            ps = conn.prepareStatement(sql);
            //2.1设置占位符的值
            if(args != null){
                for (int i = 0; i < args.length; i++) {
                    //这里是重点,因为不知道要传递参数类型故用Object
                    ps.setObject(i+1,args[i]);
                }
            }
            //3、执行SQL语句返回结果
            ResultSet rs = ps.executeQuery();
            //定义一个List集合,保存获取到一行数据
            List<T> list = new ArrayList<>();
            //思路:要将rs中的内容映射到 T这个类
            while(rs.next()){
                T t = rowMapper.getRow(rs);
                list.add(t);
            }
            return list;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}

2、接口回调

public interface RowMapper<T> {
    //将rs指向的这行数据映射到实体类中
    public T getRow(ResultSet rs);
}

3、 接口实现

class EmpRowMapper implements  RowMapper<Emp>{
    @Override
    public Emp getRow(ResultSet rs) {
        try {
            int empno = rs.getInt("empno");
            String ename = rs.getString("ename");
            String job = rs.getString("job");
            int mgr = rs.getInt("mgr");
            Date hiredate = rs.getDate("hiredate");
            double sal = rs.getDouble("sal");
            double comm = rs.getDouble("comm");
            int deptno = rs.getInt("deptno");
            Emp emp = new Emp(empno, ename, job, mgr, hiredate, sal, comm, deptno);
            return emp;
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}

4、DaoUtils工具类使用

public class EmpDaoImpl implements EmpDao {
    DaoUtils<Emp> daoUtils = new DaoUtils();
    @Override
    public int insertEmp(Emp emp) {
        String sql = "insert into emp values (?,?,?,?,?,?,?,?)";
        Object[] args = {emp.getEmpno(),emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno()};
        return daoUtils.commonsUpdate(sql,args);
    }

    @Override
    public int updateEmp(Emp emp) {
        String sql = "update emp set ename = ?,job = ?,mgr = ?,hiredate = ?,sal = ? ,comm = ?,deptno = ? where empno = ?";
        Object[] args = {emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno(),emp.getEmpno()};
        return daoUtils.commonsUpdate(sql,args);
    }

    @Override
    public int deleteEmp(int empno) {
        String sql = "delete from emp where empno =?";
        Object[] args = {empno};
        return daoUtils.commonsUpdate(sql,args);
    }

    @Override
    public Emp selectOne(int empno) {
        String sql = "select * from emp where empno = ?";
        Object[] args = {empno};
        List<Emp> empList = daoUtils.commonsQuery(sql,new EmpRowMapper(), args);
        if(empList.size() > 0 ){
            return empList.get(0);
        }
        return null;
    }
    @Override
    public List<Emp> selectAll() {
        String sql = "select * from emp";
        return daoUtils.commonsQuery(sql,new EmpRowMapper());
    }
}

四、连接池

1、出现数据库连接池的原因

  • 数据库连接是一种关键的、有限的、昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。对数据库连接的管理能显著影响到整个应用程序的伸缩性和健壮性,影响到程序的性能指标。数据库连接池正是针对这个问题提出来的。

2、什么是数据源(DataSource)

  • JDBC2.0 提供了javax.sql.DataSource接口,它负责建立与数据库的连接,当在应用程序中访问数据库时不必编写连接数据库的代码,直接引用DataSource获取数据库的连接对象即可。用于获取操作数据Connection对象。

3、Druid连接池

  • 连接池的作用:在程序初始化时,预先创建指定数量的数据库连接对象存储在池中。当需要连接数据库时,从连接池中取出现有连接;使用完毕后,也不会进行关闭,而是放回池中,实现复用,节省资源。
  • 使用Druid连接池的步骤:
    • a、创建 db.properties 配置文件。
    • b、引入druid的jar 文件。
db.properties
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql:///java2006?useSSL=false
username=root
password=123456
#初始化连接   (初始化连接池的,里面默认就已经存在了10个Connection连接)
initialSize=10
#最大连接数量  (当初始的10个连接不够的时候,最大会创建到50个)
maxActive=50
#最小空闲连接  (当连接池中的连接,没有被使用,就会减少到5个)
minIdle=5
#超时等待时间  (当连接数超过最大连接数,会等待5秒,如果5秒后还没有空闲连接,就会抛出异常)
maxWait=5000

4、升级之后的JDBC工具类(加入连接池)

public class JDBCUtil {
    //定义一个Druid连接池
    private static DataSource ds;

    static {
        //通过Properties读取配置文件
        Properties pro = new Properties();
        InputStream in = JDBCUtil.class.getClassLoader().getResourceAsStream("db.properties");
        try {
            pro.load(in);
            ds = DruidDataSourceFactory.createDataSource(pro);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //连接池一般是DBUtils的QueryRunner使用
    public static DataSource getDataSource(){
        return  ds;
    }
    public static Connection getConn(){
        try {
            return ds.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
    public static void closeAll(Connection conn, Statement stat, ResultSet rs){
        try {
            if(rs!=null){
                rs.close();
            }
            if(stat != null){
                stat.close();
            }
            if(conn!=null){
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

DBUtils工具类

1、DBUtils简介

DbUtils是Java编程中数据库操作实用小工具,小巧、简单、实用

  • 对于数据表的查询操作,可以把结果转换为List、Array、Set等集合。便于操作。
  • 对于数据表的DML操作,也变得很简单(只需要写SQL语句)。

2、DbUtils核心API

ResultSetHandler接口:转换类型接口(结果集处理类)

  • BeanHandler类:实现类,把一条记录转换成对象
  • BeanListHandler类:实现类,把多条记录转换成List集合。
  • ScalarHandler类:实现类,适合获取一行一列的数据。
  • MapHandler类: 实现类,把一条记录转换成Map集合
  • MapListHandler类:实现类,把多条记录转换成List集合。

QueryRunner:执行sql语句的类

  • 增、删、改:update();
  • 查询:query();
/*
 * QueryRunner数据查询操作:
 * 	调用QueryRunner类方法query(Connection con, String sql, ResultSetHandler r, Object...params)
 * 	ResultSetHandler r 结果集的处理方式,传递ResultSetHandler接口实现类
 * 	Object...params SQL语句中的?占位符
 * 
 * 	注意:query方法返回值,返回的是T 泛型,具体返回值类型,跟随结果集处理方式变化
 */
/*
 * 结果集其中一种处理方法,BeanListHandler
 * 结果集每一行数据,封装JavaBean对象
 * 多个JavaBena对象,存储到List集合
 */
public static void beanListHandler() throws SQLException{
	QueryRunner qr = new QueryRunner();
	String sql = "SELECT * FROM sort";
	//调用方法query,传递结果集处理实现类BeanListHandler
	List<Sort> list = qr.query(con, sql, new BeanListHandler<Sort>(Sort.class));
	for(Sort s : list) {
		System.out.println(s);
	}
}

3、 DbUtils的使用步骤

导入jar包

  • mysql连接驱动jar包
  • 导入druid 的jar包
  • database.properties配置文件
  • 导入commons-dbutils的jar包

4、DBUtils使用

public class EmpDaoImpl implements EmpDao {

    @Override
    public int insertEmp(Emp emp) {
        //1、创建QueryRunner对象
        QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
        //2、调用update方法
        String sql = "insert into emp values(?,?,?,?,?,?,?,?)";
        Object[] args = {emp.getEmpno(),emp.getEname(),emp.getJob(),emp.getMgr(),emp.getHiredate(),emp.getSal(),emp.getComm(),emp.getDeptno()};
        try {
            return qr.update(sql,args);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }

    @Override
    public Emp selectOne(int empno) {
        //1、创建QueryRunner对象
        QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
        String sql = "select * from emp where empno = ?";
        Object[] args = {empno};
        //2、调用query方法
        try {
            return qr.query(sql,new BeanHandler<Emp>(Emp.class),args);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<Emp> selectAll() {
        //1、创建QueryRunner对象
        QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
        String sql = "select * from emp";
        //2、调用query方法
        try {
            return  qr.query(sql,new BeanListHandler<Emp>(Emp.class));
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public int selectCount() {
        //1、创建QueryRunner对象
        QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
        String sql = "select count(*) from emp";
        //2、调用query方法
        try {
            return qr.query(sql, new ScalarHandler<Long>()).intValue();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 0;
    }
}

将查询出来的数据封装成一个Map集合,一般用于多表联查时,有多张表的数据不能封装到一个实体类,需要装入Map的集合再一个个取出,进行封装

public class StudentDaoImpl implements StudentDao {
    @Override
    public Map<String, Object> selectOne(int id) {
        //1、获取QueryRunner对象
        QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
        String sql = "select * from tb_student where id = ?";
        Object[] args = {id};
        try {
            return qr.query(sql,new MapHandler(),args);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<Map<String, Object>> selectAll() {
        //1、获取QueryRunner对象
        QueryRunner qr = new QueryRunner(JDBCUtil.getDataSource());
        String sql = "select * from tb_student";
        try {
            return qr.query(sql,new MapListHandler());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值