生活随笔
收集整理的這篇文章主要介紹了
JPA的泛型DAO设计及使用
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
- 使用如Hibernate或者JPA作為持久化的解決方案時,設(shè)計一個泛型的DAO抽象父類可以方便各個實體的通用CRUD操作。由于此時大部分實體DAO的CRUD操作基本一樣,采用泛型設(shè)計解決這個問題,帶來了簡潔代碼的好處。
- 問題的關(guān)鍵在于我們需要在代碼中獲取抽象DAO父類(BaseEntityDAOImpl<T>)中的泛型信息。
- 由于Java的泛型是基于泛型擦除實現(xiàn)的,因此無法直接獲取如果直接獲取,在Java中,如果子類繼承一個泛型的父類,會保存父類中泛型的信息,因此可以采用如下方法獲取泛型信息。 public abstract class BaseEntityDAOImpl<T> { protected Class<T> entityClass;
public BaseEntityDAOImpl() {
// 由于Java 方法的動態(tài)綁定getClass()調(diào)用的是子類方法
// getGenericSuperclass()返回直接父類的Type類型,并保存了泛型參數(shù)的實際類型信息。
Type genType = getClass().getGenericSuperclass();
Type[] params = ((ParameterizedType)genType).getActualTypeArguments();
// 獲取實際的泛型參數(shù)的類型信息。
entityClass = (Class<T>) params[0];
}
} - 在獲取了泛型參數(shù)實際類型之后,以下使用JPA的EntityManager來對通用CRUD操作實現(xiàn),如下:
public class BaseEntityDAOImpl<T>
{protected Class<T>
entityClass;//@PersistenceContext注解后,entityManager由Spring負責注入
@PersistenceContextprotected 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抽象父類來實現(xiàn)實體DAO接口的CRUD,而DAOImpl中沒有相關(guān)的代碼,類圖如下:
- Spring 和JPA集成如下,事務(wù)的配置使用注解實現(xiàn):
<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsdhttp://www.springframework.org/schema/contexthttp://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> ?
- 結(jié)論 對于使用Hibernate和JPA這樣的ORM框架來說,通用的CRUD操作,應(yīng)該都有這么一個泛型的DAO抽象父類。這樣可以省去很多相同功能的代碼。
- Maven測試項目的地址如下:https://github.com/jintaocai/testcode/tree/master/jpatest
轉(zhuǎn)載于:https://www.cnblogs.com/NotOnlyAnAnswer/p/5262868.html
總結(jié)
以上是生活随笔為你收集整理的JPA的泛型DAO设计及使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。