使用Spring和Java泛型簡化數據訪問層

1.概述

本文將著重于通過對系統中的所有實體使用單個通用的數據訪問對象來簡化DAO層 ,這將導致優雅的數據訪問 ,而不會造成不必要的混亂或冗長。

2. Hibernate和JPA DAO

大多數生產代碼庫都有某種DAO層。 通常,實現范圍從沒有抽象基類的多個類到某種通用類。 但是,一件事是一致的- 總是多于一件事-最有可能的是,DAO與系統中的實體之間存在一對一的關系。

同樣,根據所涉及泛型的級別,實際的實現方式可能從大量重復的代碼變為幾乎為空的代碼,大部分邏輯分組在基本抽象類中。

通常,可以通過使用Java Generics提供的類型安全性, 用單個參數化DAO替換這些多個實現,這樣就不會損失任何功能。

接下來介紹此概念的兩種實現 ,一種用于Hibernate中心持久性層,另一種針對JPA 。 這些實現絕不是完整的-僅包括某些數據訪問方法,但是可以很容易地使它們變得更徹底。

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

現在已經完成了抽象DAO,我們只需實現一次即可- 通用DAO實現將成為唯一需要的實現

@Repository
@Scope( BeanDefinition.SCOPE_PROTOTYPE )
public class GenericHibernateDao< T extends Serializable >extends AbstractHibernateDao< T > implements IGenericDao< T >{//
}

首先,請注意,通用實現本身參數化的 -允許客戶根據具體情況選擇正確的參數。 這將意味著客戶端將獲得類型安全的所有好處,而無需為每個實體創建多個工件。

其次,注意這些通用DAO實現的原型范圍 。 使用此范圍意味著Spring容器將在每次請求DAO時(包括自動裝配時)創建一個新的DAO實例。 這將允許服務根據需要將具有不同參數的多個DAO用于不同的實體。

這個作用域如此重要的原因是由于Spring初始化容器中bean的方式。 將通用DAO保留為沒有作用域將意味著使用默認的singleton作用域 ,這將導致DAO的單個實例位于容器中。 對于任何一種更復雜的情況,這顯然都是主要的限制。

IGenericDao只是所有DAO方法的接口,因此我們可以將Spring的實現注入(或任何需要的)中:

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實現類似,此處直接使用Java Persistence API,再次不依賴于現已棄用的 Spring JpaTemplate

2.4。 通用JPA DAO

與Hibernate實現類似,JPA數據訪問對象也很簡單:

@Repository
@Scope( BeanDefinition.SCOPE_PROTOTYPE )
public class GenericJpaDao< T extends Serializable >extends AbstractJpaDao< T > implements IGenericDao< T >{//
}

3.注入此DAO

現在,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實例,以便可以使用Class對象自定義實現。 在此之后,DAO已完全參數化,可供服務使用。

當然,還有其他方法可以為DAO指定類-通過反射,甚至以XML。 我偏向于這種簡單的解決方案,因為與使用反射相比,其可讀性和透明度更高。

4。結論

本文通過提供通用DAO的單個可重用實現,討論了數據訪問層簡化 。 在基于Hibernate和JPA的環境中都介紹了此實現。 結果是簡化了的持久層,沒有不必要的混亂。

有關使用基于Java的配置和項目的基本Maven pom設置Spring上下文的分步介紹,請參閱本文 。

參考:在baeldung博客上,使用JCG合作伙伴 Eugen Paraschiv的Spring和Java Generics簡化了DAO 。

翻譯自: https://www.javacodegeeks.com/2011/12/simplifying-data-access-layer-with.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/374136.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/374136.shtml
英文地址,請注明出處:http://en.pswp.cn/news/374136.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

強肝保肝養肝4大食物

“強肝的食物,保肝的食物有哪些,養肝的食物有哪些”如果您對這些食物不了解不明白。那就看看專家為您推薦的四款強肝保肝養肝的食物。荔枝&#xff08;供圖/華蓋&#xff09;一、是荔枝&#xff0c;荔枝可以保肝&#xff0c;對肝有好處根據《本草綱目》記載荔枝有強肝健胰的效果…

如何查看注解實現_該怎么運用注解呢?Java團隊元老有話說

來源 | 異步 15講能學好誕生24年的JAVA嗎&#xff1f;你當然會感到懷疑&#xff0c;眾所周知&#xff0c;在技術向的IT論壇上&#xff0c;“如何在十天之內快速掌握好Java&#xff1f;”這類問題&#xff0c;往往會招來嘲笑。來源于知乎但在當下&#xff0c;5分鐘能看完一部電影…

NXP S32K144開發(一)環境搭建和新建工程

1、首先需要安裝S32 Design Studio for ARM&#xff0c;在NXP官網可以搜索到&#xff0c;這玩意也是基于eclipse的 安裝好后就可以打開了。 2、新建工程 過程可以參考NXP官網&#xff1a; https://www.nxp.com/document/guide/get-started-with-the-s32k144evb:NGS-S32K144E…

首先記錄異常的根本原因

Logback日志庫的0.9.30版本帶來了一個很棒的新功能&#xff1a;從根&#xff08;最內部&#xff09;異常而不是最外部異常開始記錄堆棧跟蹤。 當然&#xff0c;我的興奮與我貢獻了此功能無關。 用塞西爾德米勒&#xff08;Cecil B. de Mille&#xff09; 的話來解釋&#xff1a…

成功醒言

成功醒言 C01 只有敢犯錯誤的人才能成事&#xff1b; 只有不犯同樣錯誤的人才能成大事。 C02 固執≠執著&#xff1b; 幻想≠希望。 固執是無目標的執著&#xff1b; 執著是有目標的固執。 幻想是無法兌現的希望&#xff1b; 希望是有望實現的幻想。 固執地執著幻想&#xf…

Android 中的 Service 全面總結

1、Service的種類 按運行地點分類&#xff1a; 類別區別 優點缺點 應用本地服務&#xff08;Local&#xff09;該服務依附在主進程上&#xff0c; 服務依附在主進程上而不是獨立的進程&#xff0c;這樣在一定程度上節約了資源&#xff0c;另外Local服務因為是在同一進程因此不…

python基礎學習1-三元表達式和lambda表達式

#!/usr/bin/env python # -*- coding:utf-8 -*- 三元運算 if else 的簡寫name "alex" if 11 else "SB" #如果條件成立 賦alex 否則 賦SB print(name)#--------------lambda表達式 f2 lambda a1,a2:a1a2100 #等價 下邊函數定義 def f1(a1,a2): return …

怎么讓存儲過程通用化_怎么做分布式存儲的面試?

cholerae 大神已經做了詳細回答&#xff0c;http://zenlife.tk/interview-for-distributed-storage.md寫于幾年前&#xff0c;內容有點稚嫩&#xff0c;WAL辨識度很高, 其他問題一般.CAP不會再問了&#xff0c;專業的存儲文獻中很少(幾乎不)提及CAP或PACELC, 這個詞用于市場和銷…

Java EE中的配置管理

我嘗試配置管理在云計算中具有很多相關性 爭論 較早。 實際上&#xff0c;我大膽地宣稱配置管理是任何認真嘗試從軟件中節省幾美元的基石。 那么什么是配置管理及其主要目標&#xff1f; 在不使事情變得過于復雜的情況下&#xff0c;我認為接下來的兩個目標與事實相差不遠。 以…

十年總結,一個JAVA人的十年人生路

十年總結-開篇&#xff1a;歇一歇&#xff0c;才能走的更遠經常見壇子里有人問&#xff0c;學習java該如何入手&#xff0c;或者是該學java還是學XX語言。我一直覺得&#xff0c;編程跟語言關系不大&#xff0c;重點是要有解決問題的思路。學習一門語言&#xff0c;其實只是尋求…

(四)Qt實現自定義模型基于QAbstractTableModel (一般)

Qt實現自定義模型基于QAbstractTableModel 兩個例子 例子1代碼 Main.cpp #include <QtGui>#include "currencymodel.h"int main(int argc, char *argv[]) {QApplication app(argc, argv);//數據源QMap<QString, double> currencyMap;currencyMap.insert(…

pt-query-digest使用介紹【轉】

本文來自&#xff1a;http://isadba.com/?p651 一、pt-query-digest參數介紹. pt-query-digest --useranemometer --passwordanemometerpass --review h192.168.11.28,Dslow_query_log,tglobal_query_review \--history h192.168.11.28,Dslow_query_log,tglobal_query_re…

python代碼模板_python 代碼模板

python中的Module是比較重要的概念。常見的情況是&#xff0c;事先寫好一個.py文 件&#xff0c;在另一個文件中需要import時&#xff0c;將事先寫好的.py文件拷貝 到當前目錄&#xff0c;或者是在sys.path中增加事先寫好的.py文件所在的目錄&#xff0c;然后import。這樣的做法…

Java并發教程–重入鎖

Java的synced關鍵字是一個很棒的工具–它使我們能夠以一種簡單可靠的方式來同步對關鍵部分的訪問&#xff0c;而且也不難理解。 但是有時我們需要對同步進行更多控制。 我們要么需要分別控制訪問類型&#xff08;讀取和寫入&#xff09;&#xff0c;要么使用起來很麻煩&#xf…

找出互聯網類似以下圖的實例

轉載于:https://www.cnblogs.com/sghcjy/p/4978851.html

python比較運算符重載_python運算符重載

1、打印操作會首先嘗試__str__和str內置函數&#xff0c;他通常返回一個用戶友好顯示。__repr__用于所有其他環境&#xff0c;用于交互式模式下提示回應以及repr函數&#xff0c;如果沒有使用__str__&#xff0c;則會使用print和str。它通常返回一個編碼字符串&#xff0c;可以…

使用Spring MVC開發Restful Web服務

REST簡介 摘自Wikipedia&#xff1a; REST風格的體系結構由客戶端和服務器組成。 客戶端向服務器發起請求&#xff1b; 服務器處理請求并返回適當的響應。 請求和響應圍繞資源表示的傳遞而構建。 資源本質上可以是可以解決的任何連貫且有意義的概念。 正如您所閱讀的&#xff0…

深入Java核心 Java內存分配原理精講

深入Java核心 Java內存分配原理精講 Java內存分配與管理是Java的核心技術之一&#xff0c;之前我們曾介紹過Java的內存管理與內存泄露以及Java垃圾回收方面的知識&#xff0c;今天我們再次深入Java核心&#xff0c;詳細介紹一下Java在內存分配方面的知識。一般Java在內存分配時…

iOS正則表達式(親測,持續更新)

先來說說判斷方法,書寫不簡介但是好理解: -(BOOL)isRealNmaeString:(NSString *)str{NSString *pattern "填寫正則表達式";NSPredicate *pred [NSPredicate predicateWithFormat:"SELF MATCHES %", pattern];BOOL isMatch [pred evaluateWithObject:str…

python新建一個文件夾需要重新安裝模塊嗎_解決pycharm每次新建項目都要重新安裝一些第三方庫的問題...

目前有三個解決辦法&#xff0c;也是親測有用的&#xff1a;第一個方法&#xff1a;因為之前有通過pycharm的project interpreter里的號添加過一些庫&#xff0c;但添加的庫只是指定的項目用的&#xff0c;如果想要用&#xff0c;就必須用之前的項目的python解釋器&#xff0c;…