手把手教你如何自定义DAO框架(重量级干货)(yet)

https://mp.weixin.qq.com/s?__biz=MzI4Njc5NjM1NQ==&mid=2247484864&idx=2&sn=9721e840eab2b929e9523d82c45a1bb6&chksm=ebd63aecdca1b3fa998f27a185630f7e6b40564cf7cacec8e32818184fcf1d2e23d33757beee&mpshare=1&scene=1&srcid=0206Vt8xydSjEPcErB4rA2az&key=7a4fd26cfac6ce0520c3b75a31a96df31d4be437a8f3317af06cfc9c97b79ac5fbf1bdc6bd5d03aed3ab70644e57d1140efc6bdc63ad85edd4508daea3e8e113732c605adb68dc975c22022d8f989caf&ascene=0&uin=MTA2NzUxMDAyNQ%3D%3D&devicetype=iMac+MacBookAir6%2C2+OSX+OSX+10.10.5+build(14F2511)&version=11020012&lang=zh_CN&pass_ticket=EVZTeGFk8lco7QnbdQu1aVcnN2PUGDc58FC5tG6YJ74SpwFYT%2BA%2BC4MKrc8qeCV1



描述:本篇博客,主要是对于目前实际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);  
   }  
}



原文地址:https://www.cnblogs.com/silyvin/p/9106620.html