JPA的泛型DAO设计及使用
- 使用如Hibernate或者JPA作为持久化的解决方案时,设计一个泛型的DAO抽象父类可以方便各个实体的通用CRUD操作。由于此时大部分实体DAO的CRUD操作基本一样,采用泛型设计解决这个问题,带来了简洁代码的好处。
- 问题的关键在于我们需要在代码中获取抽象DAO父类(BaseEntityDAOImpl<T>)中的泛型信息。
- 由于Java的泛型是基于泛型擦除实现的,因此无法直接获取如果直接获取,在Java中,如果子类继承一个泛型的父类,会保存父类中泛型的信息,因此可以采用如下方法获取泛型信息。
public abstract class BaseEntityDAOImpl<T> {
protected Class<T> entityClass;
public BaseEntityDAOImpl() {
// 由于Java 方法的动态绑定getClass()调用的是子类方法
// getGenericSuperclass()返回直接父类的Type类型,并保存了泛型参数的实际类型信息。
Type genType = getClass().getGenericSuperclass();
Type[] params = ((ParameterizedType)genType).getActualTypeArguments();
// 获取实际的泛型参数的类型信息。
entityClass = (Class<T>) params[0];
} } - 在获取了泛型参数实际类型之后,以下使用JPA的EntityManager来对通用CRUD操作实现,如下:
public class BaseEntityDAOImpl<T> {
protected Class<T> entityClass;
//@PersistenceContext注解后,entityManager由Spring负责注入
@PersistenceContext
protected EntityManager entityManager;
public BaseEntityDAOImpl() {
Type genType = getClass().getGenericSuperclass();
Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
entityClass = (Class<T>) params[0];
}
public EntityManager getEntityManager(){
return entityManager;
}
public void setEntityManager(EntityManager entityManager){
this.entityManager=entityManager;
}
public void add(T t){
entityManager.persist(t);
}
public void update(T t){
entityManager.merge(t);
}
public T getById(long id){
return entityManager.find(entityClass, id);
}
public void deleteById(long id){
T t=getById(id);
if(t!=null){
entityManager.remove(t);
}
}
public void delete(T t){
entityManager.remove(t);
}
public List<T> getListByPage(int offset,int maxResult){
return (List<T>)getEntityManager().createQuery("from "+entityClass.getSimpleName()).setFirstResult(offset).setMaxResults(maxResult).getResultList();
}
public List<T> getAll(){
return (List<T>)getEntityManager().createQuery("from "+entityClass.getSimpleName()).getResultList();
}
}
- 使用客户Customer和订单Order两个实体的作为例子,我们可以通过继承泛型的DAO抽象父类来实现实体DAO接口的CRUD,而DAOImpl中没有相关的代码,类图如下:

- Spring 和JPA集成如下,事务的配置使用注解实现:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="cn.cjtblog.jpatest"/>
<context:property-placeholder location="classpath:jdbc.properties" />
<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="${jdbc.driverClassName}" />
<property name="url"
value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- 对注解Jpa EntityManager的@PersistenceContext,进行注入 -->
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="packagesToScan" value="cn.cjtblog.jpatest" />
<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
<property name="jpaDialect" ref="jpaDialect" />
<property name="persistenceProvider" ref="persistenceProvider" />
<property name="jpaProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property> </bean>
<bean id="persistenceProvider" class="org.hibernate.jpa.HibernatePersistenceProvider" />
<bean id="jpaVendorAdapter"
class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL" />
<property name="showSql" value="true" />
</bean>
<bean id="jpaDialect" class="org.springframework.orm.jpa.vendor.HibernateJpaDialect" /> <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
<property name="jpaDialect" ref="jpaDialect" />
</bean>
</beans>
- 结论 对于使用Hibernate和JPA这样的ORM框架来说,通用的CRUD操作,应该都有这么一个泛型的DAO抽象父类。这样可以省去很多相同功能的代码。
- Maven测试项目的地址如下:https://github.com/jintaocai/testcode/tree/master/jpatest
JPA的泛型DAO设计及使用的更多相关文章
- 泛型DAO与泛型Service
泛型Dao与Service 看了几个帖子,泛型Dao与Service的主要目的就是要减少重复代码.具体的说明如下: 1. 定义一个BaseDao接口,此接口包含了一些通用的DAO操作,例如:增加.删除 ...
- 一个好用的hibernate泛型dao
以前从springside2.0上搞下来的很好用的,基本实现dao零编码只要配置xml文件就行了. 先看图: 一共4层,com.demonstration.hibernate.basedao是我加的用 ...
- SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装
SpringJdbc持久层封装,Spring jdbcTemplate封装,springJdbc泛型Dao,Spring baseDao封装 >>>>>>>& ...
- 泛型DAO
最近正在学习泛型DAO,通过网上查阅资料,汇总并自己整理了一下.提前需要学习的知识java反射.泛型 用到的反射如下: Class<T>类 是java.lang包下,Class类的实例表示 ...
- 《项目架构那点儿事》——Hibernate泛型Dao,让持久层简洁起来
[前言]hibernate作为持久层ORM技术,它对JDBC进行非常轻量级对象封装,使得我们可以随心所欲的使用面向对象的思想来操作数据 库.同时,作为后台开发的支撑,的确扮演了一个举足轻重的角色,那么 ...
- 自己动手写泛型dao
在经过一系列的问题得到解决之后,泛型dao终于写出来了.泛型dao相比于以前写的dao最大的好处就是,大大提高了代码的复用性,以往我们要对数据库中表中的数据进行操作的时候,每张表都需要写一个dao来操 ...
- 浅谈Java——泛型DAO
首先解释一下为什么要学习泛型DAO.平时在写DAO的时候是一个接口对应一个实现类,实现类里面要写很多的操作数据库的方法.当我们有很多的javaben的时候我们会写很多的接口和实现类,并且里面的代码都是 ...
- Hibernate也须要呵护——Hibernate的泛型DAO
众所周之.面向对象的基础是抽象.也能够说,抽象促使编程在不断发展. 对于数据库的訪问,以前写过HqlHelper.EFHelper.编写Spring+Hibernate框架下的应用.也相同离不了编写一 ...
- 泛型DAO模型设计
aaarticlea/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgMCAgMDAwMEAwMEBQgFBQQEBQoHBwYIDAoMDAsKC
随机推荐
- 图的强连通&双连通
http://www.cnblogs.com/wenruo/p/4989425.html 强连通 强连通是指一个有向图中任意两点v1.v2间存在v1到v2的路径及v2到v1的路径. dfs遍历一个图, ...
- hdoj 1406 完数
完数 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submissi ...
- Fast特征检测
一.Fast算法 1.基本原理 Fast特征点检测feature2D原理是在圆周上按顺时针方向从1到16的顺序对圆周像素点进行编号.如果在圆周上有N个连续的像素的亮度都比圆心像素的亮度Ip加上阈值t还 ...
- android 控件花屏问题
发现自己的手机上某个界面出现了花屏,某些控件背景被拉伸过多遮住了其他控件,很难看.这种现象高概率出现,分析了下发现:一旦发生这种现象,必然 会打印下面这种log,google了下,这种log应该是硬件 ...
- HTTP POST发消息
业务需求:模拟TANX给DSP发消息,protobuf数据已弄好. 代码: def PostDataToDSP(self,url,postdata): headers = { #taobao文档规定 ...
- 用WebCollector爬取站点的图片
用WebCollector爬取整站图片,仅仅须要遍历整站页面.然后将URL为.jpg.gif的页面(文件)保存到本地就可以. 比如我们爬取一个美食站点,获取里面全部的图片: import cn.edu ...
- Delphi 根据快捷方式路径取源文件地址
unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, ...
- 关于NSRunLoop和NSTimer的深入理解
一.什么是NSRunLoop NSRunLoop是消息机制的处理模式 NSRunLoop的作用在于有事情做的时候使的当前NSRunLoop的线程工作,没有事情做让当前NSRunLoop的线程休眠 NS ...
- 玩转Android之数据库框架greenDAO3.0使用指南
用过ActiveAndroid.玩过ORMLite,穿过千山万水,最终还是发现greenDAO好用,ActiveAndroid我之前有一篇文章介绍过 玩转Android之数据库框架ActiveAndr ...
- Java strictfp关键字
保证浮点运算的结果不受平台的影响,在任何平台上,使用统一的标准进行浮点运算,提高程序的可移植性(毕竟结果更可控,更精确),相应的,以降低性能为代价 Strictfp ensures that you ...