描述:本篇博客,主要是对于目前实际web项目开发中,对于数据库操作的一些基本方法的封装,通过这样的方式,可以使得开发更加简单,减少代码量,也便于维护和阅读。其中,主要是讲解了三种不同情况的封装方法,都是自身实际开发过程中,进行积累的,当然,还有很多不足之处,但是基本够项目的基本开发。
一:非框架的DAO层封装
其中包含的知识点:
1:连接池
2:数据源
3:反射
4:数据库元数据对象
5:基本的jdbc知识
封装步骤:
(1)导入dbcp数据源包
(2)编写properties文件,并且命令为dbcpconfig.properties
#连接设置 driverClassName=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/填写要使用的数据库 username=填写自己的mysql账号 password=填写自己的mysql密码 #<!-- 初始化连接 --> initialSize=10 #最大连接数量 maxActive=50 #<!-- 最大空闲连接 --> maxIdle=20 #<!-- 最小空闲连接 --> minIdle=5 #<!-- 超时等待时间以毫秒为单位 6000毫秒/1000等于60秒 --> maxWait=60000 #JDBC驱动建立连接时附带的连接属性属性的格式必须为这样:[属性名=property;] #注意:"user" 与 "password" 两个属性会被明确地传递,因此这里不需要包含他们。 connectionProperties=useUnicode=true;characterEncoding=gbk #指定由连接池所创建的连接的自动提交(auto-commit)状态。 defaultAutoCommit=true #driver default 指定由连接池所创建的连接的只读(read-only)状态。 #如果没有设置该值,则“setReadOnly”方法将不被调用。(某些驱动并不支持只读模式,如:Informix) defaultReadOnly=false #driver default 指定由连接池所创建的连接的事务级别(TransactionIsolation)。 #可用值为下列之一:(详情可见javadoc。)NONE,READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE defaultTransactionIsolation=READ_UNCOMMITTED
(3)编写DBCP工具类
public class DBCPUtils { private static DataSource ds ; static { //将配置文件加载进来 InputStream in = DBCPUtils.class.getClassLoader().getResourceAsStream("dbcpconfig.properties") ; Properties props = new Properties() ; try { props.load(in) ; ds = BasicDataSourceFactory.createDataSource(props) ; } catch (Exception e) { throw new RuntimeException("服务器忙") ; } } //提供获取连接的方法 public static Connection getConnection(){ try { return ds.getConnection() ; } catch (SQLException e) { throw new RuntimeException("服务器忙") ; } } }
(4)编写基本DAO层方法封装
//自定义框架 public class BaseDao{ // 执行添改删语句 public boolean update(String sql, Object... params) { // 拿到连接对象 Connection conn = DBCPUtils.getConnection(); int t = 0; try { // 创建预处理命令对象 PreparedStatement pstmt = conn.prepareStatement(sql); // 对?进行赋值 // 获取ParameterMetaData对象 ParameterMetaData pmd = pstmt.getParameterMetaData(); // 拿到?的个数 int n = pmd.getParameterCount(); if (n > 0) { // sql语句里有?号 if (params == null || params.length != n) { throw new RuntimeException("参数的个数不匹配"); } // 依次给每个?赋值 for (int i = 0; i < n; i++) { pstmt.setObject(i + 1, params[i]); } } t = pstmt.executeUpdate(); } catch (SQLException e) { e.printStackTrace(); } finally { try { conn.close(); // 还回池中了 } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return t > 0 ? true : false; } // 执行查询(返回的结果可能是一个或者多个,或者为null,这个就具体根据返回结果再进行处理即可) public Object queryOne(String sql,Class clazz, Object... params) { // 拿到连接对象 Connection conn = DBCPUtils.getConnection(); try { // 创建预处理命令对象 PreparedStatement pstmt = conn.prepareStatement(sql); // 对?进行赋值 // 获取ParameterMetaData对象 ParameterMetaData pmd = pstmt.getParameterMetaData(); // 拿到?的个数 int n = pmd.getParameterCount(); if (n > 0) { // sql语句里有?号 if (params == null || params.length != n) { throw new RuntimeException("参数的个数不匹配"); } // 依次给每个?赋值 for (int i = 0; i < n; i++) { pstmt.setObject(i + 1, params[i]); } } ResultSet rs = pstmt.executeQuery(); //返回的结果可能是一个或者多个,或者为null return new ResultSetListenerHandlerImpl().handler(rs, clazz) ; } catch (SQLException e) { throw new RuntimeException() ; } finally { try { conn.close(); // 还回池中了 } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
(5)查询返回结果集与实体bean的封装对象ResultSetListenerHandlerImpl
//只适用于结果集有多条记录的情况 //对象的属性名和表中的字段名应当一致 public class ResultSetListenerHandlerImpl{ public Object handler(ResultSet rs, Class clazz) { List<Object> list = new ArrayList<Object>() ; //拿到结果集的元数据对象 try { while(rs.next()){ ResultSetMetaData rsmd = rs.getMetaData() ; //拿到公有多少列 int columnCount = rsmd.getColumnCount() ; //先创建对象 Object obj = clazz.newInstance() ; for (int i = 0; i < columnCount; i++) { //拿到列名 String columnName = rsmd.getColumnName(i+1) ; //拿到对象对应的属性 Field field = clazz.getDeclaredField(columnName) ; //设置私有属性可以访问 field.setAccessible(true) ; //拿到此列对应的值 Object objectValue = rs.getObject(i+1) ; //给属性赋值 field.set(obj, objectValue) ; } list.add(obj) ; } return list ; } catch (Exception e) { throw new RuntimeException() ; } } }
上面这个是返回一个List的情况,如果只想是返回单个对象,那么很简单,稍微处理一下就可以用下面这个类来实现:
//只适用于结果集只有一条记录的情况 //对象的属性名和表中的字段名应当一致 public class ResultSetHandlerImpl { public Object handler(ResultSet rs, Class clazz) { //拿到结果集的元数据对象 try { if(rs.next()){ ResultSetMetaData rsmd = rs.getMetaData() ; //拿到公有多少列 int columnCount = rsmd.getColumnCount() ; //先创建对象 Object obj = clazz.newInstance() ; for (int i = 0; i < columnCount; i++) { //拿到列名 String columnName = rsmd.getColumnName(i+1) ; //拿到对象对应的属性 Field field = clazz.getDeclaredField(columnName) ; //设置私有属性可以访问 field.setAccessible(true) ; //拿到此列对应的值 Object objectValue = rs.getObject(i+1) ; //给属性赋值 field.set(obj, objectValue) ; } return obj ; }else return null ; } catch (Exception e) { throw new RuntimeException() ; } } }
二:Mybatis的DAO层封装
(1)一般先写接口:
public interface DAO { /** * 保存对象 * * @param str * @param obj * @return * @throws Exception */ public Object save(String str, Object obj) throws Exception; /** * 修改对象 * * @param str * @param obj * @return * @throws Exception */ public Object update(String str, Object obj) throws Exception; /** * 删除对象 * * @param str * @param obj * @return * @throws Exception */ public Object delete(String str, Object obj) throws Exception; /** * 查找对象 * * @param str * @param obj * @return * @throws Exception */ public Object findForObject(String str, Object obj) throws Exception; /** * 查找对象 * * @param str * @param obj * @return * @throws Exception */ public Object findForList(String str, Object obj) throws Exception; /** * 查找对象封装成Map * * @param s * @param obj * @return * @throws Exception */ public Object findForMap(String sql, Object obj, String key, String value) throws Exception; }
(2)再写实现层:
@Repository("daoSupport") public class DaoSupport implements DAO { @Resource(name = "sqlSessionTemplate") private SqlSessionTemplate sqlSessionTemplate; /** * 保存对象 * * @param str * @param obj * @return * @throws Exception */ public Object save(String str, Object obj) throws Exception { return sqlSessionTemplate.insert(str, obj); } /** * 批量更新 * * @param str * @param obj * @return * @throws Exception */ public Object batchSave(String str, List objs) throws Exception { return sqlSessionTemplate.insert(str, objs); } /** * 修改对象 * * @param str * @param obj * @return * @throws Exception */ public Object update(String str, Object obj) throws Exception { return sqlSessionTemplate.update(str, obj); } /** * 批量更新 * * @param str * @param obj * @return * @throws Exception */ public void batchUpdate(String str, List objs) throws Exception { SqlSessionFactory sqlSessionFactory = sqlSessionTemplate.getSqlSessionFactory(); // 批量执行器 SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false); try { if (objs != null) { for (int i = 0, size = objs.size(); i < size; i++) { sqlSession.update(str, objs.get(i)); } sqlSession.flushStatements(); sqlSession.commit(); sqlSession.clearCache(); } } finally { sqlSession.close(); } } /** * 批量更新 * * @param str * @param obj * @return * @throws Exception */ public Object batchDelete(String str, List objs) throws Exception { return sqlSessionTemplate.delete(str, objs); } /** * 删除对象 * * @param str * @param obj * @return * @throws Exception */ public Object delete(String str, Object obj) throws Exception { return sqlSessionTemplate.delete(str, obj); } /** * 查找对象 * * @param str * @param obj * @return * @throws Exception */ public Object findForObject(String str, Object obj) throws Exception { return sqlSessionTemplate.selectOne(str, obj); } /** * 查找对象 * * @param str * @param obj * @return * @throws Exception */ public Object findForList(String str, Object obj) throws Exception { return sqlSessionTemplate.selectList(str, obj); } public Object findForMap(String str, Object obj, String key, String value) throws Exception { return sqlSessionTemplate.selectMap(str, obj, key); } }