亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Spring 與 Hibernate 的延遲加載和 Dao 模式

系統 1879 0
Hibernate 與延遲加載:

Hibernate 對象關系映射提供延遲的與非延遲的對象初始化。非延遲加載在讀取一個對象的時候會將與這個對象所有相關的其他對象一起讀取出來。這有時會導致成百的(如果不是成千的話) select 語句在讀取對象的時候執行。這個問題有時出現在使用雙向關系的時候,經常會導致整個數據庫都在初始化的階段被讀出來了。當然,你可以不厭其煩地檢查每一個對象與其他對象的關系,并把那些最昂貴的刪除,但是到最后,我們可能會因此失去了本想在 ORM 工具中獲得的便利。


一個明顯的解決方法是使用 Hibernate 提供的延遲加載機制。這種初始化策略只在一個對象調用它的一對多或多對多關系時才將關系對象讀取出來。這個過程對開發者來說是透明的,而且只進行了很少的數據庫操作請求,因此會得到比較明顯的性能提升。這項技術的一個缺陷是延遲加載技術要求一個 Hibernate 會話要在對象使用的時候一直開著。這會成為通過使用 DAO 模式將持久層抽象出來時的一個主要問題。為了將持久化機制完全地抽象出來,所有的數據庫邏輯,包括打開或關閉會話,都不能在應用層出現。最常見的是,一些實現了簡單接口的 DAO 實現類將數據庫邏輯完全封裝起來了。一種快速但是笨拙的解決方法是放棄 DAO 模式,將數據庫連接邏輯加到應用層中來。這可能對一些小的應用程序有效,但是在大的系統中,這是一個嚴重的設計缺陷,妨礙了系統的可擴展性。

Web 層進行延遲加載

幸運的是, Spring 框架為 Hibernate 延遲加載與 DAO 模式的整合提供了一種方便的解決方法。對那些不熟悉 Spring Hibernate 集成使用的人,我不會在這里討論過多的細節,但是我建議你去了解 Hibernate Spring 集成的數據訪問。以一個 Web 應用為例, Spring 提供了 OpenSessionInViewFilter OpenSessionInViewInterceptor 。我們可以隨意選擇一個類來實現相同的功能。兩種方法唯一的不同就在于 interceptor Spring 容器中運行并被配置在 web 應用的上下文中,而 Filter Spring 之前運行并被配置在 web.xml 中。不管用哪個,他們都在請求將當前會話與當前(數據庫)線程綁定時打開 Hibernate 會話。一旦已綁定到線程,這個打開了的 Hibernate 會話可以在 DAO 實現類中透明地使用。這個會話會為延遲加載數據庫中值對象的視圖保持打開狀態。一旦這個邏輯視圖完成了, Hibernate 會話會在 Filter doFilter 方法或者 Interceptor postHandle 方法中被關閉。下面是每個組件的配置示例:


Interceptor的配置:

<beans>
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="interceptors">
<list>
<ref bean="openSessionInViewInterceptor"/>
</list>
</property>
<property name="mappings">
...
</bean>
...
<bean name="openSessionInViewInterceptor"
class="org.springframework.orm.hibernate.support.OpenSessionInViewInterceptor">
<property name="sessionFactory"><ref bean="sessionFactory"/></property>
</bean>
</beans>
Filter的配置

<web-app>
...
<filter>
<filter-name>hibernateFilter</filter-name>
<filter-class>
org.springframework.orm.hibernate.support.OpenSessionInViewFilter
</filter-class>
</filter>
...
<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>*.
spring
</url-pattern>
</filter-mapping>
...
</web-app>

實現 Hibernate Dao 接口來使用打開的會話是很容易的。事實上,如果你已經使用了 Spring 框架來實現你的 Hibernate Dao, 很可能你不需要改變任何東西。方便的 HibernateTemplate 公用組件使訪問數據庫變成小菜一碟,而 DAO 接口只有通過這個組件才可以訪問到數據庫。下面是一個示例的 DAO


Example DAO

public class HibernateProductDAO extends HibernateDaoSupport implements ProductDAO {

public Product getProduct(Integer productId) {
return (Product)getHibernateTemplate().load(Product.class, productId);
}

public Integer saveProduct(Product product) {
return (Integer) getHibernateTemplate().save(product);
}

public void updateProduct(Product product) {
getHibernateTemplate().update(product);
}
}

在業務邏輯層中使用延遲加載

即使在視圖外面, Spring 框架也通過使用 AOP interceptor HibernateInterceptor 來使得延遲加載變得很容易實現。這個 Hibernate interceptor 透明地將調用配置在 Spring 應用程序上下文中的業務對象中方法的請求攔截下來,在調用方法之前打開一個 Hibernate 會話,然后在方法執行完之后將會話關閉。讓我們來看一個簡單的例子,假設我們有一個接口 BussinessObject


public interface BusinessObject {
public void doSomethingThatInvolvesDaos();
}
The class BusinessObjectImpl implements BusinessObject:


public class BusinessObjectImpl implements BusinessObject {
public void doSomethingThatInvolvesDaos() {
// lots of logic that calls
// DAO classes Which access
// data objects lazily
}
}
通過在 Spring 應用程序上下文中的一些配置,我們可以讓將調用 BusinessObject 的方法攔截下來,再令它的方法支持延遲加載。看看下面的一個程序片段:


<beans>
<bean id="hibernateInterceptor" class="org.springframework.orm.hibernate.HibernateInterceptor">
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<bean id="businessObjectTarget" class="com.acompany.BusinessObjectImpl">
<property name="someDAO"><ref bean="someDAO"/></property>
</bean>
<bean id="businessObject" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target"><ref bean="businessObjectTarget"/></property>
<property name="proxyInterfaces">
<value>com.acompany.BusinessObject</value>
</property>
<property name="interceptorNames">
<list>
<value>hibernateInterceptor</value>
</list>
</property>
</bean>
</beans>
businessObject 被調用的時候, HibernateInterceptor 打開一個 Hibernate 會話,并將調用請求傳遞給 BusinessObjectImpl 對象。當 BusinessObjectImpl 執行完成后, HibernateInterceptor 透明地關閉了會話。應用層的代碼不用了解任何持久層邏輯,還是實現了延遲加載。


在單元測試中測試延遲加載

最后,我們需要用 J-Unit 來測試我們的延遲加載程序。我們可以輕易地通過重寫 TestCase 類中的 setUp tearDown 方法來實現這個要求。我比較喜歡用這個方便的抽象類類作為所有我的測試類的基類。


public abstract class MyLazyTestCase extends TestCase {

private SessionFactory sessionFactory;
private Session session;

public void setUp() throws Exception {
super.setUp();
SessionFactory sessionFactory = (SessionFactory) getBean("sessionFactory");
session = SessionFactoryUtils.getSession(sessionFactory, true);
Session s = sessionFactory.openSession();
TransactionSynchronizationManager.bindResource(sessionFactory, new SessionHolder(s));

}

protected Object getBean(String beanName) {
//Code to get objects from
Spring application context
}

public void tearDown() throws Exception {
super.tearDown();
SessionHolder holder = (SessionHolder) TransactionSynchronizationManager.getResource(sessionFactory);
Session s = holder.getSession();
s.flush();
TransactionSynchronizationManager.unbindResource(sessionFactory);
SessionFactoryUtils.closeSessionIfNecessary(s, sessionFactory);
}
}

由于要求在項目中使用泛型的DAO,所以上網Google了一下,找到了IBM的一篇文章。文章講得不錯,但是有些地方不清楚,如果完全按照那篇文章可能還會遇到一些困難。所以寫了這篇文章,解釋如何在項目中加入泛型的DAO實現。

首先是總的類關系的UML圖:

然后是在配置文件中的關系圖:

其中,IStaffDao是我們自己定義的接口,這個接口類似:

public interface IStaffDAO extends GenericDao < Staff,Integer > {

public ListlistAll();

public StaffgetByLogonAndId(Stringlogon,Integerid);

// more

}


GenericDao<T , PK extends Serilizable> 是泛型的 Dao 接口:

/***/ /**
*2006-11-22
*范型DAO接口
*
@author ZouAng
*Contact<ahref="mailto:richardeee@gmail.com">ZouAng</a>
*/

public interface GenericDao < T,PK extends Serializable > {

/***/ /**
*保存一個對象到數據庫
*
@param newInstance需要保存的對象
*
@return
*/

PKcreate(TnewInstance);
/***/ /**
*從數據庫讀取一個對象
*
@param id主鍵
*
@return
*/

Tread(PKid);

/***/ /**
*更新一個對象
*
@param transientObject被更新的對象
*/

void update(TtransientObject);

/***/ /**
*刪除一個對象
*
@param transientObject被刪除的對象
*/

void delete(TtransientObject);
}

GenericDaoHibernateImpl GenericDao 接口的泛型實現 :


/***/ /**
*2006-11-22
*范型DAO實現
*
@author ZouAng
*Contact<ahref="mailto:richardeee@gmail.com">ZouAng</a>
*/

public class GenericDaoHibernateImpl < T,PK extends Serializable >
extends HibernateDaoSupport
implements GenericDao < T,PK > ,FinderExecutor {

private Class < T > type;
private FinderNamingStrategynamingStrategy = new SimpleFinderNamingStrategy(); // Default.Canoverrideinconfig
private FinderArgumentTypeFactoryargumentTypeFactory = new SimpleFinderArgumentTypeFactory(); // Default.Canoverrideinconfig

public GenericDaoHibernateImpl(Class < T > type) {
this .type = type;
}


/**/ /* (non-Javadoc)
*@seecom.gdnfha.atcs.common.service.dao.GenericDao#create(java.lang.Object)
*/

public PKcreate(TnewInstance) {
return (PK)getHibernateTemplate().save(newInstance);
}


/**/ /* (non-Javadoc)
*@seecom.gdnfha.atcs.common.service.dao.GenericDao#delete(java.lang.Object)
*/

public void delete(TtransientObject) {
getHibernateTemplate().delete(transientObject);
}


/**/ /* (non-Javadoc)
*@seecom.gdnfha.atcs.common.service.dao.GenericDao#read(java.io.Serializable)
*/

public Tread(PKid) {
return (T)getHibernateTemplate().get(type,id);
}


/**/ /* (non-Javadoc)
*@seecom.gdnfha.atcs.common.service.dao.GenericDao#update(java.lang.Object)
*/

public void update(TtransientObject) {
getHibernateTemplate().update(transientObject);
}


public List < T > executeFinder(Methodmethod, final Object[]queryArgs)
{
final QuerynamedQuery = prepareQuery(method,queryArgs);
return (List < T > )namedQuery.list();
}


public Iterator < T > iterateFinder(Methodmethod, final Object[]queryArgs)
{
final QuerynamedQuery = prepareQuery(method,queryArgs);
return (Iterator < T > )namedQuery.iterate();
}


private QueryprepareQuery(Methodmethod,Object[]queryArgs)
{
final StringqueryName = getNamingStrategy().queryNameFromMethod(type,method);
final QuerynamedQuery = getSession().getNamedQuery(queryName);
String[]namedParameters
= namedQuery.getNamedParameters();
if (namedParameters.length == 0 )
{
setPositionalParams(queryArgs,namedQuery);
}
else {
setNamedParams(namedParameters,queryArgs,namedQuery);
}

return namedQuery;
}


private void setPositionalParams(Object[]queryArgs,QuerynamedQuery)
{
// Setparameter.UsecustomHibernateTypeifnecessary
if (queryArgs != null )
{
for ( int i = 0 ;i < queryArgs.length;i ++ )
{
Objectarg
= queryArgs[i];
TypeargType
= getArgumentTypeFactory().getArgumentType(arg);
if (argType != null )
{
namedQuery.setParameter(i,arg,argType);
}

else
{
namedQuery.setParameter(i,arg);
}

}

}

}


private void setNamedParams(String[]namedParameters,Object[]queryArgs,QuerynamedQuery)
{
// Setparameter.UsecustomHibernateTypeifnecessary
if (queryArgs != null )
{
for ( int i = 0 ;i < queryArgs.length;i ++ )
{
Objectarg
= queryArgs[i];
TypeargType
= getArgumentTypeFactory().getArgumentType(arg);
if (argType != null )
{
namedQuery.setParameter(namedParameters[i],arg,argType);
}

else
{
if (arg instanceof Collection) {
namedQuery.setParameterList(namedParameters[i],(Collection)arg);
}

else
color:
分享到:
評論

Spring 與 Hibernate 的延遲加載和 Dao 模式


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产乱子伦一区二区三区 | 国产大学生一级毛片绿象 | 久久中文字幕2021精品 | 国产伦乱 | 国产成人aa免费视频 | 成人爽a毛片在线视频 | 久久亚洲精品专区蓝色区 | 伊人狼人综合网 | 午夜免费体验区 | 日本a在线观看 | 午夜成人在线视频 | 一区二区三区成人 | 国产成人麻豆精品video | 久久精品综合 | 久久精品视屏 | 在线欧美一级毛片免费观看 | 久久日韩精品 | 久久国产热这里只有精品 | 青青草一区二区免费精品 | 久久精品视频久久 | 色偷偷要色偷偷网站视频在线 | 亚洲国产美女精品久久 | 中文在线视频 | 伊人精品综合 | a v在线男人的天堂观看免费 | 国产综合色在线视频区色吧图片 | 亚洲成年网站 | 天天操夜夜拍 | 国产不卡视频 | 国产精品99久久久久久夜夜嗨 | 国产69精品久久久久999三级 | 国产区精品福利在线观看精品 | 久久综合九色综合97_ 久久久 | 又粗又大的机巴好爽视频视频 | 奇米最新视频 | 操美女的穴 | 日日舔| 91成人影院未满十八勿入 | 日本在线毛片视频免费看 | 欧美高清在线精品一区 | 九九九九在线精品免费视频 |