使用Spring和Java泛型简化数据访问层
1.概述
本文將著重于通過對系統(tǒng)中的所有實(shí)體使用單個通用的數(shù)據(jù)訪問對象來簡化DAO層 ,這將導(dǎo)致優(yōu)雅的數(shù)據(jù)訪問 ,而不會造成不必要的混亂或冗長。
2. Hibernate和JPA DAO
大多數(shù)生產(chǎn)代碼庫都有某種DAO層。 通常,實(shí)現(xiàn)范圍從沒有抽象基類的多個類到某種通用類。 但是,一件事是一致的- 總是多于一件事-最有可能的是,DAO與系統(tǒng)中的實(shí)體之間存在一對一的關(guān)系。
同樣,根據(jù)所涉及泛型的級別,實(shí)際的實(shí)現(xiàn)方式可能從大量重復(fù)的代碼變?yōu)閹缀鯙榭盏拇a,大部分邏輯分組在基本抽象類中。
通常,可以通過使用Java Generics提供的類型安全性, 用單個參數(shù)化DAO替換這些多個實(shí)現(xiàn),這樣就不會損失任何功能。
接下來介紹此概念的兩種實(shí)現(xiàn) ,一種用于Hibernate中心持久性層,另一種針對JPA 。 這些實(shí)現(xiàn)絕不是完整的-僅包括某些數(shù)據(jù)訪問方法,但是可以很容易地使它們變得更徹底。
2.1。 抽象的休眠DAO
public abstract class AbstractHibernateDao< T extends Serializable > {private Class< T > clazz;@AutowiredSessionFactory sessionFactory;public final void setClazz( Class< T > clazzToSet ){this.clazz = clazzToSet;}public T findOne( long id ){return (T) getCurrentSession().get( clazz, id );}public List< T > findAll(){return getCurrentSession().createQuery( "from " + clazz.getName() ).list();}public void create( T entity ){getCurrentSession().persist( entity );}public void update( T entity ){getCurrentSession().merge( entity );}public void delete( T entity ){getCurrentSession().delete( entity );}public void deleteById( long entityId ){T entity = findOne( entityId );delete( entity );}protected final Session getCurrentSession(){return sessionFactory.getCurrentSession();} }DAO直接使用Hibernate API,而不依賴于任何Spring模板(例如HibernateTemplate )。 Hibernate DAO教程介紹了模板的使用以及在DAO中自動裝配的SessionFactory的管理。
2.2。 通用休眠DAO
現(xiàn)在已經(jīng)完成了抽象DAO,我們只需實(shí)現(xiàn)一次即可- 通用DAO實(shí)現(xiàn)將成為唯一需要的實(shí)現(xiàn) :
@Repository @Scope( BeanDefinition.SCOPE_PROTOTYPE ) public class GenericHibernateDao< T extends Serializable >extends AbstractHibernateDao< T > implements IGenericDao< T >{// }首先,請注意,通用實(shí)現(xiàn)本身是參數(shù)化的 -允許客戶根據(jù)具體情況選擇正確的參數(shù)。 這將意味著客戶端將獲得類型安全的所有好處,而無需為每個實(shí)體創(chuàng)建多個工件。
其次,注意這些通用DAO實(shí)現(xiàn)的原型范圍 。 使用此范圍意味著Spring容器將在每次請求DAO時(包括自動裝配時)創(chuàng)建一個新的DAO實(shí)例。 這將允許服務(wù)根據(jù)需要將具有不同參數(shù)的多個DAO用于不同的實(shí)體。
這個作用域如此重要的原因是由于Spring初始化容器中bean的方式。 將通用DAO保留為沒有作用域?qū)⒁馕吨褂媚J(rèn)的singleton作用域 ,這將導(dǎo)致DAO的單個實(shí)例位于容器中。 對于任何一種更復(fù)雜的情況,這顯然都是主要的限制。
IGenericDao只是所有DAO方法的接口,因此我們可以將Spring的實(shí)現(xiàn)注入(或任何需要的)中:
public interface IGenericDao<T extends Serializable> {T findOne(final long id);List<T> findAll();void create(final T entity);T update(final T entity);void delete(final T entity);void deleteById(final long entityId); }2.3。 JPA DAO摘要
public abstract class AbstractJpaDao< T extends Serializable > {private Class< T > clazz;@PersistenceContextEntityManager entityManager;public void setClazz( Class< T > clazzToSet ){this.clazz = clazzToSet;}public T findOne( Long id ){return entityManager.find( clazz, id );}public List< T > findAll(){return entityManager.createQuery( "from " + clazz.getName() ).getResultList();}public void save( T entity ){entityManager.persist( entity );}public void update( T entity ){entityManager.merge( entity );}public void delete( T entity ){entityManager.remove( entity );}public void deleteById( Long entityId ){T entity = getById( entityId );delete( entity );} }與Hibernate DAO實(shí)現(xiàn)類似,此處直接使用Java Persistence API,再次不依賴于現(xiàn)已棄用的 Spring JpaTemplate 。
2.4。 通用JPA DAO
與Hibernate實(shí)現(xiàn)類似,JPA數(shù)據(jù)訪問對象也很簡單:
@Repository @Scope( BeanDefinition.SCOPE_PROTOTYPE ) public class GenericJpaDao< T extends Serializable >extends AbstractJpaDao< T > implements IGenericDao< T >{// }3.注入此DAO
現(xiàn)在,Spring將注入一個DAO 。 此外, 類需要指定:
@Service class FooService implements IFooService{IGenericDao< Foo > dao;@Autowiredpublic void setDao( IGenericDao< Foo > daoToSet ){dao = daoToSet;dao.setClazz( Foo.class );}// ...}Spring 使用setter注入自動裝配新的DAO實(shí)例,以便可以使用Class對象自定義實(shí)現(xiàn)。 在此之后,DAO已完全參數(shù)化,可供服務(wù)使用。
當(dāng)然,還有其他方法可以為DAO指定類-通過反射,甚至以XML。 我偏向于這種簡單的解決方案,因?yàn)榕c使用反射相比,其可讀性和透明度更高。
4。結(jié)論
本文通過提供通用DAO的單個可重用實(shí)現(xiàn),討論了數(shù)據(jù)訪問層的簡化 。 在基于Hibernate和JPA的環(huán)境中都介紹了此實(shí)現(xiàn)。 結(jié)果是簡化了的持久層,沒有不必要的混亂。
有關(guān)使用基于Java的配置和項(xiàng)目的基本Maven pom設(shè)置Spring上下文的分步介紹,請參閱本文 。
翻譯自: https://www.javacodegeeks.com/2011/12/simplifying-data-access-layer-with.html
總結(jié)
以上是生活随笔為你收集整理的使用Spring和Java泛型简化数据访问层的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 招行手机银行买了理财怎么撤回?
- 下一篇: Java EE中的配置管理