JDBC之DAO模式、dbutils工具使用、批处理

10. DAO设计模式

10.1 DAO简介

-dao是数据访问对象(Data Access object)的简写。
-是为应用程序的持久层所设计的编程模式。
-持久层指的是数据库与业务层之间的逻辑,即与数据库直接交互的逻辑层,封装了所有对数据库的访问
-目的:将数据访问逻辑和业务逻辑分开。
一个DAO设计模式包含以下内容

1.	定义实体类:
   通过对象关系映射(ORM)将数据库的表结构映射成java类型;表中的每一条记录映射成类的实例。用于数
   据的传
   递。
2.	定义一个接口:
   在此接口中,定义应用程序对此表的所有访问操作,如增,删,改、査,等方法。
3.	定义接口的实现类
   实现接口中的所有抽象方法。
4.	定义一个DAO工厂类型
   用于返回接口实例
   这样,开发人员只需要使用DAO接口即可,具体逻辑就变得透明了,无需了解内部细节
   扩展:项目的包名命名规则
com.qianfeng.jdbcO3.util
com.qianfeng.jdbcO3.entity
com.qianfeng.jdbcO3.test
com.qianfeng.jdbcO3.dao
com.qianfeng.jdbcO3.dao.imp!
com.qianfeng.jdbcO3.service

10.2 DAO的案例示范
10.2.1创建项目,导入相关资源
10.2.2编写工具类DBUtil
10.2.3编写实体类
import java.sql.Date; 
import java.util.Objects; 
/**
\* 以orm关系将数据库中的emp表映射成java中的Emp类型 
\* 表的字段映射成类的属性 
*/ 
public class Emp { 
    private int empno; 
    private String ename; 
    private String job; 
    private int mgr; 
    private Date hiredate; 
    private double salary; 
    private double comm; 
    private int deptno; 
    public Emp(){} 
    public Emp(int empno, String ename, String job, int mgr, Date hiredate, 
               double salary, double comm, int deptno) { 
        this.empno = empno; 
        this.ename = ename; 
        this.job = job; 
        this.mgr = mgr; 
        this.hiredate = hiredate; 
        this.salary = salary; 
        this.comm = comm; 
        this.deptno = deptno; 
    }
    public int getEmpno() { 
        return empno; 
    }
    public void setEmpno(int empno) { 
        this.empno = empno; 
    }
    public String getEname() { 
        return ename; 
    }
    public void setEname(String ename) {
        this.ename = ename; 
    }
    public String getJob() { 
        return job; 
    }
    public void setJob(String job) { 
        this.job = job; 
    }
    public int getMgr() { 
        return mgr; 
    }
    public void setMgr(int mgr) { 
        this.mgr = mgr; 
    }
    public Date getHiredate() { 
        return hiredate; 
    }
    public void setHiredate(Date hiredate) { 
        this.hiredate = hiredate; 
    }
    public double getSalary() { 
        return salary; 
    }
    public void setSalary(double salary) { 
        this.salary = salary; 
    }
    public double getComm() { 
        return comm; 
    }
    public void setComm(double comm) { 
        this.comm = comm; 
    }
    public int getDeptno() { 
        return deptno; 
    }
    public void setDeptno(int deptno) { 
        this.deptno = deptno; 
    }
    @Override 
    public boolean equals(Object o) { 
        if (this == o) return true; 
        if (o == null || getClass() != o.getClass()) return false; 
        Emp emp = (Emp) o;
        return empno == emp.empno && 
            mgr == emp.mgr &&
            Double.compare(emp.salary, salary) == 0 && 
            Double.compare(emp.comm, comm) == 0 && 
            deptno == emp.deptno && 
            Objects.equals(ename, emp.ename) && 
            Objects.equals(job, emp.job) && 
            Objects.equals(hiredate, emp.hiredate); 
    }
    @Override 
    public int hashCode() { 
        return Objects.hash(empno, ename, job, mgr, hiredate, salary, comm, 
                            deptno); 
    }
    @Override 
    public String toString() { 
        return "Emp{" + 
            "empno=" + empno + 
            ", ename='" + ename + '\'' + 
            ", job='" + job + '\'' + 
            ", mgr=" + mgr + 
            ", hiredate=" + hiredate + 
            ", salary=" + salary + 
            ", comm=" + comm + 
            ", deptno=" + deptno + 
            '}'; 
    } 
}
10.2.4 定义接口
import com.qianfeng.jdbc03.entity.Emp; 
import java.util.List; 
/** 
\* 设计针对于实体类Emp和数据库里的emp表设计对数据库操作的接口 
\* 提供相应操作的抽象方法 
*/
public interface EmpDao { 
    /** 
	\* 提供向数据库中插入数据的方法, 
	\* @param e 面向对象思想可以使用实体类的实例 
	*/
    void addEmp(Emp e); 
    /** 
	\* 提供删除数据库内的一条记录方法,通过id进行删除 
	\* @param empno 数据库表中的主键 
	*/
    void deleteById(int empno); 
    /** 
	\* 修改方法。 
	\* @param e 传入前先设置成要修改的数据,然后传入方法中进行update语句赋值 
	*/
    void modifyEmp(Emp e); 
    /**
    \* 通过唯一键查询一条记录 
    \* @param empno 
    \* @return 封装成实体类实例 
    */ 
    Emp findById(int empno); 
    /** 
    \* 查询所有的记录。 
    \* @return 封装成类的实例,并存入集合 
    */
    List<Emp> findAll(); 
    /** 
    \* 分页查询 
    \* @param page 要查询的页数 
    \* @param pageSize 每页显示的条数 
    \* @return 一页的所有记录,封装到集合中 
    */
    List<Emp> findByPage(int page,int pageSize); 
}
10.2.5 编写实现类
public class EmpDaoImpl implements EmpDao { 
    @Override 
    public void addEmp(Emp e) { 
        Connection conn = null; 
        PreparedStatement ps = null; 
        try{
            conn = DBUtil.getConnection(); 
            String sql = "insert into emp values (?,?,?,?,?,?,?,?)"; 
            ps = conn.prepareStatement(sql); 
            ps.setInt(1,e.getEmpno()); 
            ps.setString(2,e.getEname()); 
            ps.setString(3,e.getJob()); 
            ps.setInt(4,e.getMgr()); 
            ps.setDate(5,e.getHiredate()); 
            ps.setDouble(6,e.getSalary()); 
            ps.setDouble(7,e.getComm()); 
            ps.setInt(8,e.getDeptno()); 
            ps.executeUpdate(); 
        }catch (Exception e1){ 
            e1.printStackTrace(); 
        }finally{ 
            DBUtil.closeConnection(conn,ps,null); 
        } 
    }
    @Override 
    public void deleteById(int empno) { 
    }
    @Override 
    public void modifyEmp(Emp e) {
    }
    @Override 
    public Emp findById(int empno) { 
        return null; 
    }
    @Override 
    public List<Emp> findAll() { 
        return null; 
    }
    @Override 
    public List<Emp> findByPage(int page, int pageSize) { 
        Connection conn = null; 
        PreparedStatement ps = null; 
        ResultSet rs = null; 
        List<Emp> emps = new ArrayList<Emp>(); 
        try{
            conn = DBUtil.getConnection(); 
            String sql = "select * from emp order by empno limit ?,?"; 
            ps = conn.prepareStatement(sql); 
            ps.setInt(1,(page-1)*pageSize); 
            ps.setInt(2,pageSize); 
            rs = ps.executeQuery(); 
            Emp e = null; 
            while(rs.next()){ 
                int empno = rs.getInt(1); 
                String ename = rs.getString(2); 
                String job = rs.getString("job"); 
                int mgr = rs.getInt("mgr"); 
                Date hiredate = rs.getDate("hiredate"); 
                double salary = rs.getDouble("sal"); 
                double comm = rs.getDouble("comm"); 
                int deptno = rs.getInt("deptno"); 
                e = new Emp(empno,ename,job,mgr,hiredate,salary,comm,deptno); 
                emps.add(e); 
            } 
        }catch (Exception e1){ 
            e1.printStackTrace(); 
        }finally{ 
            DBUtil.closeConnection(conn,ps,rs); 
        }
        return emps; 
    } 
}
10.2.6 编写DAO工厂类(重点)
public class DaoFactory{ 
    //定义属性EmpDao属性 
    private static EmpDao empdao = new EmpDaoImpl(); 
    //让构造函数为 private,这样该类就不会被实例化 
    private DaoFactory(){} 
    public synchronized static EmpDao getInstance(){ 
        return empdao; 
    } 
}
10.2.7 编写测试类
public class TestDao { 
    @Test 
    public void testAddEmp(){ 
        EmpDao dao = DaoFactory.getInstance(); 
        Emp e = new Emp(9007,"huanghua","manager",7369, 
                        Date.valueOf("2019-1-1"),3000.0,200.0,20); 
        dao.addEmp(e); 
    }
    @Test 
    public void testFindByPage(){ 
        EmpDao dao = DaoFactory.getInstance(); 
        List<Emp> emps = dao.findByPage(3,5); 
        for(Emp e:emps){ 
            System.out.println(e); 
        } 
    }
}

11. dbutils第三方工具类的使用(重点)

11.1 简介
此工具封装了DAO层(持久层)的逻辑。减少了开发周期。
-jar包:commons-dbutils-1.7.jar
-常用API:
1.	QueryRunner类型:可以直接使用连接池技术来操作数据库,进行增删改查
   构造器:
    QueryRunner()
    创建一个连接对象,但连接的数据库需要在之后的操作中写出来
    QueryRunner(DataSource ds)
    返回一个指定数据库连接池得QueryRunner对象
   非静态方法:
    执行query操作
    query(string sql, ResultSetHandler<T> rsh)
    query(string sql, ResultSetHandler<T> rsh,筛选条件)
    执行insert update delete 操作
    update(String sql,Object...params)
2.	通过sqL及其ReusltSetHandler的子类型来获取数据并封装成相应对象
    ResultsetHandler:关于结果集的一个接口。
   其实现类如下:
   MapHander:单行处理器,结果转成Map<String,Object>列名为键。
   MapListHander:多行处理器,结果转成List<Map<String,Object>>一般主键为键,未定义的则第一个字段为键。   
   BeanHandler:单行处理器,将査询到的数据的第一条封装成实体类对象,例: new BeanHandler<>(Employee.class)
   BeanListHandler:多行处理器,将査询到的数据的第一条封装成实体类对象的集合
   ColumnListHander:多行单列处理器,结果转成List<Object>,例: new ColumnListHander("name")
   ScalarHandler:单行单列处理器,把结果集转成Object,一般用于聚类查询,例:select count(*) from emp;
   ArrayListHandler:用于将查询到的记录都封装到Object数组中,并存入到List集合中,例 new ArrayListHandler()
   MapHandler:用于将查询到的第一条记录封装成Map对象,字段名作为键组,字段名作为值组。
   MapListHandler:用于将查询到的每一条记录封装成Map对象,字段名作为键组,字段名作为值组。
11.2代码测试
public class Testdbutils { 
    @Test 
    public void testFindOne() throws SQLException { 
        QueryRunner qr = new QueryRunner(DBUtil.getPool()); 
        Emp emp = qr.query("select * from emp",new BeanHandler<Emp>(Emp.class));
        System.out.println(emp); 
    }
    @Test 
    public void testFindOneParam() throws SQLException { 
        QueryRunner qr = new QueryRunner(DBUtil.getPool()); 
        Emp emp = qr.query("select * from emp where empno =?", 
                           new BeanHandler<Emp>(Emp.class),9007); 
        System.out.println(emp); 
    }
    @Test
    public void testFindAll() throws SQLException { 
        QueryRunner qr = new QueryRunner(DBUtil.getPool()); 
        List<Emp> emp = qr.query("select * from emp", 
                                 new BeanListHandler<Emp>(Emp.class)); 
        System.out.println(emp); 
    } 
}

12. JDBC的批处理

12.1 概念

每一次的sql操作都会占用数据库的资源。如果将N条操作先存储到缓存区中,然后再一次性刷到数据库中,这 就减少了与数据库的交互次数。因此可以提高效率。

12.2 Statement

批处理中不能再出现execute方法

addBatch(String sql):将sql语句添加到缓存中 
executeBatch():将缓存中的sql一次性刷到数据库中
12.3 代码
@Test 
public void testBatch(){ 
    Connection conn = null; 
    Statement stat = null; 
    try{
        conn = DBUtil.getConnection(); 
        stat = conn.createStatement(); 
        int num = 0; 
        while(num<1003){ 
            String sql = "insert into testbatch values (null,'zs"+num+"','f')"; 
            stat.addBatch(sql);//将sql语句添加到缓存中, 
            if(num%50==0){ 
                stat.executeBatch();//缓存中每有50条都刷新一次。 
            }
            num++; 
        }
        stat.executeBatch();//循环结束后,将缓存中剩余的不足50条的全都刷新出去 
    }catch (Exception e){ 
        e.printStackTrace(); 
    }finally { 
        DBUtil.closeConnection(conn,stat,null); 
    } 
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值