- 浏览: 75530 次
- 性别:
- 来自: 西安
文章分类
最新评论
-
zhulin902:
不错
子类一定覆盖父类的同名方法吗? -
剑锋凛冽:
cuisuqiang 写道java解析xml有多种方式,目前j ...
使用java解析XML -
cuisuqiang:
java解析xml有多种方式,目前jdk6已经包含了pull解 ...
使用java解析XML -
cuisuqiang:
基础东西,要经常总结才行
String的equals使用
最近在公司实习过程中,TL提出一个需求,要求在不使用Hibernate的情况下实现一个比较通用的DAO框架,使用JDBCTemplate作为数据库sql语句的执行工具。在参考了CloudStack 3.0.2的相关源代码后,我自己实现了一个简化版的DAO框架。结果后来,TL又说改用Python开发,遗憾地把这些东西留作纪念吧。
简单的类图参见连接http://pan.baidu.com/share/link?shareid=115118&uk=3592520259
环境为MyEclipse8.5+Spring2.5,使用jar为asm-3.3.1、cglib-2.2、mysql-connector
1,编程思想
本质上是将某些通用的API,如最基础的CRUD直接通过泛型类来实现。唯一的比较难处理的就是Update时,哪些属性需要更新,这可以拦截通过CGLIB类库实现对setter方法的拦截并记录被改变的属性。
2,代码
核心类BaseDaoImpl
package DataBaseDemo.daoimpl; import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.sql.DataSource; import net.sf.cglib.proxy.Enhancer; import org.apache.log4j.Logger; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.PreparedStatementCreator; import org.springframework.jdbc.core.PreparedStatementSetter; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.support.GeneratedKeyHolder; import org.springframework.jdbc.support.KeyHolder; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.support.DefaultTransactionDefinition; import DataBaseDemo.interceptor.UpdateFactory; import DataBaseDemo.util.DBUtils; import DataBaseDemo.util.ModelRowMapper; import com.mysql.jdbc.Statement; public class BaseDaoImpl<T> { Logger logger=Logger.getLogger(BaseDaoImpl.class); //POJO类的实际类型 Class<T> entityType; //简单地将POJO类名映射成数据库表名 String table; public static JdbcTemplate jdbcTemplate; public static PlatformTransactionManager transactionManager; public static DefaultTransactionDefinition transactionDef; @SuppressWarnings("unchecked") BaseDaoImpl() { DataSource datasource=DBUtils.configureDatasource(); jdbcTemplate = new JdbcTemplate(datasource); transactionManager=new DataSourceTransactionManager(datasource); transactionDef=new DefaultTransactionDefinition(TransactionDefinition.PROPAGATION_REQUIRED); Type t = getClass().getGenericSuperclass(); // 使用该语法后,BaseDaoImpl无法正常使用,只能通过子类调用它 // 用于获取实际输入的Model类型 if (t instanceof ParameterizedType) { entityType = (Class<T>) ((ParameterizedType) t) .getActualTypeArguments()[0]; } else if (((Class<?>) t).getGenericSuperclass() instanceof ParameterizedType) { entityType = (Class<T>) ((ParameterizedType) ((Class<?>) t) .getGenericSuperclass()).getActualTypeArguments()[0]; } else { entityType = (Class<T>) ((ParameterizedType) ((Class<?>) ((Class<?>) t) .getGenericSuperclass()).getGenericSuperclass()) .getActualTypeArguments()[0]; } this.table = DBUtils.getTable(entityType); } @SuppressWarnings("unchecked") public List<T> queryAll() { String sql = "select * from " + table; List<T> list = jdbcTemplate.query(sql, new ModelRowMapper(entityType)); return list; } /** * 根据ID,查询一条记录并用实体包装 * * @param id * @return */ @SuppressWarnings("unchecked") public T load(int id) { String sql = "select * from " + table + " where id=" + id; List<T> list = jdbcTemplate.query(sql, new ModelRowMapper(entityType)); return list.size() == 0 ? null : list.get(0); } /** * 根据ID,删除指定表里的记录 * * @param id */ public void delete(int id) { String sql = "delete from " + table + " where id=" + id; jdbcTemplate.execute(sql); } /** * 根据ID更新实体数据到数据库 * * @param entity * @param id */ @SuppressWarnings("unchecked") public void update(T entity, int id) { assert Enhancer.isEnhanced(entity.getClass()) : "没有被拦截器监控到更新数据"; StringBuilder sql = new StringBuilder(); sql.append("update " + table + " set "); System.out.println(entity.hashCode()); HashMap<String, Object> map = UpdateFactory.getChanges(entity.hashCode()); List<String> keys = new ArrayList<String>(); List<Object> values = new ArrayList<Object>(); Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); String key = (String) entry.getKey(); Object val = entry.getValue(); keys.add(key); values.add(val); } for (int i = 0; i < keys.size(); i++) { if (i == keys.size() - 1) { sql.append(keys.get(i) + "=? "); } else { sql.append(keys.get(i) + "=?,"); } } sql.append("where id=?"); logger.info("更新语句:"+sql.toString()); values.add(id); jdbcTemplate.update(sql.toString(), setParams(values.toArray())); } /** * 插入实体,并返回数据库自增生成的ID * * @param entity * @return */ @SuppressWarnings("unchecked") public int insert(T entity) { final StringBuilder sql = new StringBuilder(); sql.append("insert into " + table + "("); HashMap<String, Object> map = getChangesForInsert(entity); List<String> columns = new ArrayList<String>(); final List<Object> values = new ArrayList<Object>(); Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry entry = (Map.Entry) iter.next(); String key = (String) entry.getKey(); Object val = entry.getValue(); columns.add(key); values.add(val); } for (int i = 0; i < columns.size(); i++) { if (i == columns.size() - 1) { sql.append(columns.get(i) + ") values("); } else { sql.append(columns.get(i) + ","); } } for (int i = 0; i < values.size(); i++) { if (i == values.size() - 1) { sql.append("?)"); } else { sql.append("?,"); } } logger.info("插入语句:"+sql.toString()); KeyHolder key = new GeneratedKeyHolder(); final String insertSql=sql.toString(); jdbcTemplate.update(new PreparedStatementCreator() { @Override public PreparedStatement createPreparedStatement(Connection con) throws SQLException { // TODO Auto-generated method stub //必须设置Statement.RETURN_GENERATED_KEYS才能进行返回ID PreparedStatement ps = jdbcTemplate.getDataSource() .getConnection().prepareStatement(insertSql,Statement.RETURN_GENERATED_KEYS); for (int i = 0; i < values.size(); i++) { ps.setObject(i + 1, values.get(i)); } return ps; } }, key); return key.getKey().intValue(); } /** * 插入实体并返回被插入的实体 * * @param entity * @return */ public T persist(final T entity) { int id=insert(entity); //直接通过connection进行提交同样无法成功 // transaction.commit(); logger.info("数据库返回的自增ID为:"+id); T persisted=load(id); return persisted; } /** * * @param params * @return */ @SuppressWarnings("unchecked") public List<T> query(SearchCriteria sc){ String where = sc.generateWhereClause(); StringBuilder sb = new StringBuilder("select * from "+sc.getTable()); sb.append(where); logger.info("查询语句"+sb.toString()); logger.info("查询参数"+Arrays.toString(sc.generateParams())); List<T> list = jdbcTemplate.query(sb.toString(), setParams(sc.generateParams()),new ModelRowMapper(entityType)); return list; } /** * 返回DAO对应的数据库表的总记录数 * @return */ public int getTotalCount(){ String sql="select count(*) from "+table; return jdbcTemplate.queryForInt(sql); } /** * 以pagesize大小的页,返回第page页的数据 * @param page * @param pagesize * @return */ @SuppressWarnings("unchecked") public List<T> getPage(int page,int pagesize){ if(page<0||pagesize<0){ throw new IllegalArgumentException("页码或页大小参数不合法"); } String sql="select * from "+table+" limit "+page*pagesize+","+(page+1)*pagesize; return jdbcTemplate.query(sql, new ModelRowMapper<T>(entityType)); } /** * 直接执行sql查询语句,param作为参数数组 * @param sql * @param params * 返回查询到的结果列表 * @return */ @SuppressWarnings("unchecked") public List<T> executeRawSql(String sql,Object[] params){ return jdbcTemplate.query(sql, setParams(params) , new ModelRowMapper<T>(entityType)); } /** * 设置查询用的参数列表 * @param params * @return */ protected PreparedStatementSetter setParams(final Object[] params) { return new PreparedStatementSetter() { @Override public void setValues(PreparedStatement ps) throws SQLException { // TODO Auto-generated method stub for (int i = 0; i < params.length; i++) { ps.setObject(i + 1, params[i]); } } }; } /** * 返回待插入实体上的所有非空属性值及属性名的Map * @param entity * @return */ protected HashMap<String, Object> getChangesForInsert(T entity){ Field[] fields = entityType.getDeclaredFields(); HashMap<String, Object> insertValues = new HashMap<String, Object>(); try { for (Field field : fields) { field.setAccessible(true); //跳过id字段 if("id".equalsIgnoreCase(field.getName())) continue; Object value = field.get(entity); if (value == null) continue; insertValues.put(field.getName(), value); } return insertValues; } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } }
子类Dao实例:UserDaoImpl
package DataBaseDemo.daoimpl; import java.util.List; import DataBaseDemo.dao.UserDao; import DataBaseDemo.model.UserVO; public class UserDaoImpl extends BaseDaoImpl<UserVO> implements UserDao { @Override public UserVO queryUser() { // TODO Auto-generated method stub UserVO user=new UserVO(); return user; } //自定义的高级查询包装 public List<UserVO> listUsers(){ return queryAll(); } }
核心拦截工厂对Model被修改的属性进行记录并通过CGLIB的接口进行拦截
package DataBaseDemo.interceptor; import java.util.HashMap; import net.sf.cglib.proxy.Callback; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.NoOp; /** * 使用UpdateFactory存放对象被改变的属性及其值 * 以对象的hashCode为key,值为被改变的HashMap * @author Administrator * */ public class UpdateFactory { public static HashMap<Integer,HashMap<String,Object>> changes; private static Enhancer enhancer; //以字典的方式记录每个对象的改变属性值 static{ changes=new HashMap<Integer, HashMap<String,Object>>(); } /** * 根据对象的hashCode存储对象被改变的属性值 * @param hash * @param key * @param value */ public static void addChange(Integer hash,String key,Object value){ HashMap<String, Object> orginal=changes.get(hash); if(orginal==null){ orginal=new HashMap<String, Object>(); orginal.put(key, value); }else{ orginal.put(key, value); } changes.put(hash, orginal); } /** * 以对象的hashCode取出对象的所有变更 * @param hash * @return */ public static HashMap<String, Object> getChanges(Integer hash){ return changes.get(hash); } // 通过工厂生成对象,并产生拦截器,拦截set方法生成被改变的值Map /** * 根据对象class生成对应实例,并使它的修改能够被CGLIB拦截 */ public static Object createVO(Class<?> clazz) { enhancer = new Enhancer(); enhancer.setSuperclass(clazz); Callback[] callbacks; callbacks = new Callback[] { NoOp.INSTANCE, new UpdateInterceptor() }; enhancer.setCallbacks(callbacks); enhancer.setCallbackFilter(new SetFilter()); return enhancer.create(); } }package DataBaseDemo.util;
import java.lang.reflect.Field; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; import org.springframework.jdbc.core.RowMapper; import DataBaseDemo.interceptor.UpdateFactory; /** * 使用包cglib和asm来创建对某一对象setters方法的拦截器 * * @author Administrator * */ public class ModelRowMapper<T> implements RowMapper { /** * @param args */ Class<?> clazz; public ModelRowMapper(Class<?> clazz) { this.clazz = clazz; } // RowMapper中直接通过field给字段设值,避免干扰set拦截器的使用 public static Object setValues(HashMap<String, Object> map, Object entity) { Field[] fields = entity.getClass().getDeclaredFields(); try { for (Field field : fields) { Object value = map.get(field.getName()); if (value != null) { field.setAccessible(true); field.set(entity, value); } } } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } return entity; } public void setValues(ResultSet rs, Object entity) { Field[] fields = clazz.getDeclaredFields(); try { for (Field field : fields) { Object value = rs.getObject(field.getName()); field.setAccessible(true); field.set(entity, value); } } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } @SuppressWarnings("unchecked") @Override public T mapRow(ResultSet rs, int rowNum) throws SQLException { //通过更新工厂的静态方法创建类实例,使它被CGLIB监控 T entity = (T) UpdateFactory.createVO(clazz); setValues(rs, entity); return entity; } }
3,缺点
--目前的查询非常简单,需要进行优化
--无法支持事务管理,原因不明,进一步研究中
所有源码参照CloudStack3.0.2的相关代码编写
- DAOProject.rar (38 KB)
- 下载次数: 39
相关推荐
### Oracle + jdbcTemplate + Spring + Java + Flex 实现分页 #### 一、Oracle存储过程分页 在Oracle数据库中,为了实现高效的分页查询,通常会采用存储过程的方式来完成。这种方式能够有效地减少网络传输的数据量...
总结起来,实现Oracle + jdbcTemplate + Spring + Java + Flex的分页查询,主要涉及以下步骤: 1. 在Oracle中创建存储过程,处理分页逻辑和计数。 2. 使用Spring的jdbcTemplate调用存储过程,处理输入输出参数。 3. ...
总的来说,"springmvc+jdbctemplate+mysql(采用注解方式)"的组合为开发中小型项目提供了高效、灵活的基础。通过注解方式,开发者可以快速搭建系统,专注于业务逻辑,而无需过多关注底层配置。这个技术栈的使用能够...
基于java+Spring+SpringMVC+JDBCTemplate+JSP开发的博客论坛系统+源码+开发文档+视频演示,适合毕业设计、课程设计、项目开发。项目源码已经过严格测试,可以放心参考并在此基础上延申使用~ 基于java+Spring+...
本文将深入探讨`JdbcTemplate`通用泛型Dao实现的相关知识点,帮助开发者更好地理解和应用这一技术。 首先,让我们了解什么是`JdbcTemplate`。它是Spring框架的一部分,用于处理SQL操作。`JdbcTemplate`提供了一组...
JdbcTemplate 是 Spring 框架的一部分,提供了一种模板化的 JDBC 操作方式,简化了数据库访问,而 Druid 是阿里巴巴开源的一个高性能、功能丰富的数据库连接池实现。 首先,我们来看一下如何集成 Druid 连接池。在 ...
本系统是基于Maven+JSP+Servlet+JdbcTemplate+Redis+Mysql实现的旅游网站,使用的技术偏多,但是网站内容很简单,容易理解。包含:景点门票,酒店预订,出境游,国内游,港澳游,报团,自由行等功能.登录,注册,后台管理...
在实现通用DAO时,反射通常用于动态调用数据库操作的方法,比如SQL查询。例如,在`UsersDAO.java`中,可能有以下代码: ```java public class UsersDAO extends BaseDao<Users> { @Override public void save...
在IT行业中,数据库操作是应用开发中的重要环节,Spring框架的JdbcTemplate是Java开发者常用的数据库访问工具,它简化了SQL的执行和结果处理。本文将深入探讨如何利用Spring的JdbcTemplate进行MySQL数据库的分页查询...
标题 "springmvc+jdbctemplate+mchange+multidatasource" 涉及到的是一个在Java后端开发中常见的技术组合,主要用于构建基于Spring MVC的多数据源应用,并使用JdbcTemplate进行数据库操作,同时利用mchange(通常指...
在本项目中,我们关注的是如何在 Spring Boot 应用程序中集成 JdbcTemplate 和 Druid 数据源来实现数据库操作。 JdbcTemplate 是 Spring 框架的一部分,提供了一个方便的 API 来执行 SQL 查询和更新,避免了手动...
总的来说,这个"SpringMvc+JdbcTemplate+oracle的小项目实例"是一个很好的学习资源,它涵盖了Web开发的基本流程,包括前后端交互、数据库操作和验证机制。通过这个项目,你可以深入理解这些技术的协同工作方式,为更...
Spring MVC支持动态页面参数,可以配合JdbcTemplate的查询方法实现分页。开发者可以通过设置SQL的LIMIT和OFFSET子句来获取特定范围的数据,然后传递这些数据到视图进行渲染。同时,可以使用Spring提供的Pageable接口...
一套完成的使用Idea开发环境,采用springboot、jdbcTemplate实现的mysql读取webService完成程序。其中,封装了数据读、写、删除的各种操作;访问webservice时,需要使用token认证。 一套很实用、很难得的的基于java...
在IT行业中,构建Web应用程序是常见的任务,而SpringMVC、jdbcTemplate、easyUI和ztree这四个技术组件常被用于构建高效、易用且功能丰富的管理后台。下面将详细介绍这些技术及其在“增删改查”操作中的应用。 首先...
Struts2、Hibernate、Spring、JdbcTemplate以及EXT是Java Web开发中的重要框架和技术,它们各自在应用程序的不同层面发挥着关键作用。将这些技术整合在一起,可以构建出高效、灵活且可维护的Web应用。 1. **Struts2...
本文将探讨如何使用Maven、Spring MVC、JDBCTEMPLATE和日志框架Slf4j实现一个基于MySQL数据库的简单注册功能。首先,我们需要搭建一个开发环境,选用的技术栈包括: 1. **Maven** - 作为项目管理和构建工具,Maven...
【作品名称】:基于 Java+Mysql 实现的图书管理系统( Spring+Spring MVC+JdbcTemplate) 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项...
本文将详细讲解如何利用Spring Boot、Atomikos、JPA(Java Persistence API)以及MySQL来实现JTA(Java Transaction API)分布式事务。 首先,Spring Boot是一个轻量级的框架,它简化了基于Spring的应用程序开发...