数据层开发
数据层中重点进行数据库的CRUD操作,在操作过程中,数据层只关心是否存在有Connection对象,至于这个对象谁给的,不关心。
1.定义数据层接口标准
由于业务层要调用数据层的相关操作,所以必须在数据层中定义好与之前业务分析处给出的要求一致的操作。但定义数据层标准的时候也需要考虑以下情况:
数据更新操作:主要包含INSERT, UPDATE,DELETE
方法名称建议以:doXxx()形式命名,例如:doCreate(), doUpdate(), doRemove();
数据查询操作:分为两种情况:
数据查询:以findXxx()形式命名,例如:findAll(),findById()
数据的统计操作:以getXxx()形式命名,例如:getAllCount()
同时数据层的简写为dao,所以数据层的标准就需要定义在xxx.dao包中,同时考虑到 接口与类的区别,接口前使用字母“ I ”作为标记,本次进行emp表操作,那么就 IEmpDAO
范例:定义IEmpDAO接口
大部分情况下每一张实体表一定会对应有一个DAO接口标准。有多少张表就有多少个DAO接口,就有多少个简单java类,但是不包含关系表
package xxx.dao; import java.util.List; import java.util.Set; import xxx.vo.Emp; /* * 定义数据表的数据层操作标准 * */ public interface IEmpDAO { /* * 数据增加的操作,执行的是INSERT语句 * vo 包含了要增加的数据信息 * return 如果数据增加成功 返回true 否则返回false * Exception 如果数据库没有连接,则出现NullPointerException,如果SQL语句错误抛出SQLException */ public boolean doCreate(Emp vo) throws Exception; /* * 数据修改操作,执行UPDATE语句,本次的修改会根据ID将所有的数据进行变更 * vo 包含了要修改数据的信息 * return 如果数据修改成功 返回true 否则返回false * Exception 如果数据库没有连接,则出现NullPointerException,如果SQL语句错误抛出SQLException */ public boolean doUpdate(Emp vo) throws Exception; /* * 数据删除操作,需在执行前根据删除的编号,拼凑出SQL语句 * ids 所有要删除的编号数据 * return 如果数据删除成功 返回true 否则返回false * Exception 如果数据库没有连接,则出现NullPointerException,如果SQL语句错误抛出SQLException */ public boolean doRemove(Set<Integer>ids) throws Exception; /* * 根据雇员编号查询出表一行的完整信息,并且将返回结果填充到VO类对象中 * id 要查询的数据编号 * return 如果查询到则将内容以vo对象的形式返回,如果查到没有数据返回null * Exception 如果数据库没有连接,则出现NullPointerException,如果SQL语句错误抛出SQLException */ public Emp findById(Integer id) throws Exception; /* * 查询数据表中的全部数据,每行数据通过vo类包装,而后通过List保存多个返回结果 * return 全部的查询数据行,如果没有数据返回,集合长度为0(size() = 0)。 * Exception 如果数据库没有连接,则出现NullPointerException,如果SQL语句错误抛出SQLException */ public List<Emp> findAll() throws Exception; /* * 分页进行数据表的模糊查询操作,每行数据通过vo类包装,而后通过List保存多个返回结果 * column 要模糊查询的数据列 * keyWord 要进行查询的关键字 * currentPage 当前所在页 * lineSize 每页显示的数据行数 * return 全部的查询数据行,如果没有数据返回,集合长度为0(size() = 0)。 * Exception 如果数据库没有连接,则出现NullPointerException,如果SQL语句错误抛出SQLException */ public List<Emp> findAllSplit(String columun,String keyWord,Integer currentPage, Integer lineSize) throws Exception; /* * 使用COUNT()函数统计数据表中符合查询要求的数据量 * column 要模糊查询的数据列 * keyWord 要进行查询的关键字 * return 返回COUNT()的统计结果,如果没有数据满足,则返回内容为0 * Exception 如果数据库没有连接,则出现NullPointerException,如果SQL语句错误抛出SQLException */ public Integer getAllCount(String columun,String keyWord) throws Exception; }
如果要定义数据层的实现类,那么最关键的问题:如何取得数据库连接对象
通过业务层操作DatabaseConnection对象,每一个数据层执行的时候传入Connection接口对象
使用业务层统一负责数据库的打开与关闭,而数据层的子类之中只需要关注与存在有Connection的接口对象即可
考虑到数据层的实现子类上必须要有Connection接口对象后才可以操作,那么就可以定义有参构造方法接收Connection的接口对象。
数据层的实现子类可以保存在xxx.dao.impl子包上,加上impl代表子类
范例:定义EmpDAOImpl子类
package xxx.dao.impl; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import xxx.dao.IEmpDAO; import xxx.vo.Emp; /* * 要想操作数据层子类,那么一定要在构造方法中传入Connection接口对象 */ public class EmpDAOImpl implements IEmpDAO { private Connection conn; //数据库连接对象 private PreparedStatement pstmt; //数据库操作对象 /* * 实例化数据层子类对象,同时传入一个数据库连接对象 * conn Connection连接对象,如果为null表示数据库没有打开 */ public EmpDAOImpl(Connection conn) { this.conn = conn; } @Override public boolean doCreate(Emp vo) throws Exception { String sql = "INSERT INTO emp(empno,ename,job,hiredate,sal,comm) VALUES (?,?,?,?,?,?)"; this.pstmt = this.conn.prepareStatement(sql); this.pstmt.setInt(1, vo.getEmpno()); this.pstmt.setString(2, vo.getEname()); this.pstmt.setString(3, vo.getJob()); this.pstmt.setDate(4, new java.sql.Date(vo.getHiredate().getTime())); this.pstmt.setDouble(5, vo.getSal()); this.pstmt.setDouble(6, vo.getComm()); return this.pstmt.executeUpdate() > 0; } @Override public boolean doUpdate(Emp vo) throws Exception { String sql = "UPDATE emp SET ename = ?,job = ?,hiredate = ?,sal = ?,comm = ? WHERE empno = ?"; this.pstmt = this.conn.prepareStatement(sql); this.pstmt.setString(1, vo.getEname()); this.pstmt.setString(2, vo.getJob()); this.pstmt.setDate(3, new java.sql.Date(vo.getHiredate().getTime())); this.pstmt.setDouble(4, vo.getSal()); this.pstmt.setDouble(5, vo.getComm()); this.pstmt.setInt(6, vo.getEmpno()); return this.pstmt.executeUpdate() > 0; } @Override public boolean doRemove(Set<Integer> ids) throws Exception { StringBuffer sql = new StringBuffer(); sql.append("DELETE FROM emp WHERE empno IN ("); Iterator<Integer> iter = ids.iterator(); while(iter.hasNext()) { sql.append(iter.next()).append(","); } sql.delete(sql.length() - 1, sql.length());//删除最后的逗号, sql.append(")"); this.pstmt = this.conn.prepareStatement(sql.toString()); return this.pstmt.executeUpdate() == ids.size(); //true是删除成功了 } @Override public Emp findById(Integer id) throws Exception { //根据ID查询 Emp vo = null; String sql = "SELECT empno,ename,job,hiredate,sal,comm FROM emp WHERE empno=?"; this.pstmt = this.conn.prepareStatement(sql); this.pstmt.setInt(1, id); ResultSet rs = this.pstmt.executeQuery(); if(rs.next()) { vo = new Emp(); vo.setEmpno(rs.getInt(1)); vo.setEname(rs.getString(2)); vo.setJob(rs.getString(3)); vo.setHiredate(rs.getDate(4)); vo.setSal(rs.getDouble(5)); vo.setComm(rs.getDouble(6)); } return vo; } @Override public List<Emp> findAll() throws Exception { //查询全部 List<Emp> all = new ArrayList<Emp>(); String sql = "SELECT empno,ename,job,hiredate,sal,comm FROM emp "; this.pstmt = this.conn.prepareStatement(sql); ResultSet rs = this.pstmt.executeQuery(); while(rs.next()) { Emp vo = new Emp(); vo = new Emp(); vo.setEmpno(rs.getInt(1)); vo.setEname(rs.getString(2)); vo.setJob(rs.getString(3)); vo.setHiredate(rs.getDate(4)); vo.setSal(rs.getDouble(5)); vo.setComm(rs.getDouble(6)); all.add(vo); } return all; } @Override public List<Emp> findAllSplit(String columun, String keyWord, Integer currentPage, Integer lineSize) throws Exception { List<Emp> all = new ArrayList<Emp>(); String sql = "SELECT * FROM (SELECT empno,ename,job,hiredate,sal,comm,ROWNUM rn FROM emp WHERE "+columun+" LIKE ? AND ROWNUM <= ?) temp WHERE temp.rn > ? "; this.pstmt = this.conn.prepareStatement(sql); this.pstmt.setString(1, "%" + keyWord + "%"); this.pstmt.setInt(2, currentPage * lineSize); this.pstmt.setInt(3, (currentPage - 1) * lineSize); ResultSet rs = this.pstmt.executeQuery(); while(rs.next()) { Emp vo = new Emp(); vo = new Emp(); vo.setEmpno(rs.getInt(1)); vo.setEname(rs.getString(2)); vo.setJob(rs.getString(3)); vo.setHiredate(rs.getDate(4)); vo.setSal(rs.getDouble(5)); vo.setComm(rs.getDouble(6)); all.add(vo); } return all; } @Override public Integer getAllCount(String columun, String keyWord) throws Exception { String sql = "SELECT COUNT(*) FROM emp WHERE " + columun + " LIKE ? "; this.pstmt = this.conn.prepareStatement(sql); this.pstmt.setString(1, "%" + keyWord + "%"); ResultSet rs = this.pstmt.executeQuery(); if(rs.next()) { return rs.getInt(1); } return null; } }
在整个实现过程中,DAO层的每一个方法都描述的是一个具体的操作。
定义工厂类
数据层最终是要交给业务层使用的,那么业务层不关心你的数据是怎么搞的,也不关心你有神马子类,这样就一定需要有一个工厂类提供实例化对象的获取支持。工厂类可以定义在factory子包中。
范例:定义DAOFactory程序类
package xxx.factory; import java.sql.Connection; import xxx.dao.IEmpDAO; import xxx.dao.impl.EmpDAOImpl; public class DAOFactory { public static IEmpDAO getIEmpDAOInstance(Connection conn) { return new EmpDAOImpl(conn); } }