手把手教你如何自定义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);
}
}