分享
 
 
 

在Spring中配置Hibernate事务(图)

王朝other·作者佚名  2008-05-31
窄屏简体版  字體: |||超大  

这篇文章主要探讨怎么用SPRing来装配组件及其事务治理。在J2EE工程里连接到一个简单的数据库并不是什么难题,但是假如要综合组装企业类的组件就变得复杂了。一个简单的组件有一个或多个数据库支撑,所以,我们说到整合两个或多个的组件时,我们希望能够维持跨组件的许多数据库的运作的原子性。

J2EE提供了这些组件的容器,可以保证处理的原子性和独立性。在没有J2EE的情况下我们可以用Spring。Spring基于IoC模式(即反转模式),不仅可以配置组件服务,还可以配置相应的方法。为了更好的实现本文的目的,我们使用Hibernate来做相应的后台开发。

装配组件事务

假设在组件库里,我们已经有一个审核组件(audit component),里面有可以被客户端调用的方法。接着,当我们想要构建一个处理订单的体系,我们发现设计需要的OrderListManager组件服务同样需要审核组件服务。OrderListManager创建和治理订单,每一个服务都含有自己的事务属性。当这时调用审核组件,就可以把OrderListManager的处理内容传给它。也许将来新的业务服务(business service)同样需要审核组件,那这时它调用的事务内容已经不一样了。在网络上的结果就是,虽然审核的功能保持不变,但是可以和别的事件功能组合在一起,用这些方法属性来提供不同的运行时的处理参数。

在图1中有两个分开的调用流程。在流程1里,假如客户端含有一个TX内容,OrderListManager 要由一个新的TX开始或者参与其中,取决于客户端在不在TX里以及OrderListManager方法指定的TX属性。这在它调用AuditManager方法的时候仍然适用。

图1. 装配组件事务

EJB体系通过装配者声明正确的事务属性来获得这种适应性。我们不是在探讨是否声明事务治理,因为这会使运行时的事务参数代码发生改变。几乎所有的J2EE工程提供了分布的事务治理来配合提交协议例如X/Open XA specification。

现在的问题是我们能不能不用EJB来获得相同的功能?Spring是其中一种解决方案。来看一下Spring如何处理这样的问题:

用Spring来治理事务

我们将看到的是一个轻量级的事务机制,实际上,它可以治理组件层的事务集成。Spring就是如此。它的优点是我们可以不用捆绑在J2EE的服务例如JNDI数据库。最棒的是假如我们想把这个事务机制与已经存在的J2EE框架组合在一起,没有任何问题,就似乎我们找到了杠杆中完美的支撑点一样。

Spring的另一个机制是使用了AOP框架。这个框架使用了一个可以使用AOP的Spring bean factory。在Spring特定的配置文件applicationContext.xml里通过特定的组件层的事件来指定。

<beans<!-- other code goes here... --

<bean id="orderListManager"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"<property name="transactionManager"

<ref local="transactionManager1"/</property<property name="target"

<ref local="orderListManagerTarget"/</property<property name="transactionAttributes"

<props<prop key="getAllOrderList"PROPAGATION_REQUIRED</prop

<prop key="getOrderList"PROPAGATION_REQUIRED</prop<prop key="createOrderList"PROPAGATION_REQUIRED</prop

<prop key="addLineItem" PROPAGATION_REQUIRED, -com.example.exception.FacadeException</prop<prop key="getAllLineItems"PROPAGATION_REQUIRED,readOnly</prop

<prop key="queryNumberOfLineItems"PROPAGATION_REQUIRED,readOnly</prop

</props</property</bean</beans

一旦我们在服务层指定了事务属性,它们就被一个继续org.springframework.transaction.PlatformTransactionManager 接口的类截获. 这个接口如下:

public interface PlatformTransactionManager{TransactionStatus getTransaction(TransactionDefinition definition);

void commit(TransactionStatus status);

void rollback(TransactionStatus status);}

Hibernate事务治理

一旦我们决定了使用Hibernate作为ORM工具,我们下一步要做的就是用Hibernate特定的事务治理实例来配置。

<beans<!-- other code goes here... --<bean id="transactionManager1"class="org.springframework.orm.hibernate.HibernateTransactionManager"

<property name="sessionFactory"

<ref local="sessionFactory1"/

</property</bean</beans

我们来看看什么是“装配组件事务”,你也许注重到了那个OrderListManager 特有的TX属性,那个服务层的组件。我们的工程的主要的东西在表2的BDOM里:

图 2. 业务领域对象模型 (BDOM)

为了用实例说明,我们来列出工程里的非功能需求(NFR):

---事务在数据库appfuse1里保存。

---审核时要登入到另一个数据库appfuse2里,出于安全的考虑,数据库有防火墙保护。

---事务组件可以重用。

---所有访问事件必须经过在事务服务层的审核。

出于以上的考虑,我们决定了OrderListManager 服务将委托任何审核记录来调用已有的AuditManager 组件.这产生了表3这样更细致的结构:

图 3. 组件服务结构设计

值得注重的是,由于我们的NFR,我们要映射OrderListManager相关的事物到appfuse1 数据库里去,而审核相关的到appfuse2。这样,任何审核的时候 OrderListManager 组件都会调用AuditManager 组件。我们认为OrderListManager 组件里的所有方法都要执行, 因为我们通过服务来创建次序和具体项目。那么AuditManager 组件里的服务呢? 因为它做的是审核的动作,我们关心的是为系统里所有的事务记录审核情况。这样的需求是,“即使事务事件失败了,我们也要记录登录的审核情况”。AuditManager 组件同样要有自己的事件,因为它同样与自己的数据库有关联。如下所示:

<beans<!—其他代码在这里--<bean id="auditManager"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"<property name="transactionManager"<ref local="transactionManager2"/</property

<property name="target"<ref local="auditManagerTarget"/</property

<property name="transactionAttributes"

<props

<prop key="log"

PROPAGATION_REQUIRES_NEW

</prop

</props

</property</bean</beans

我们现在把注重力放到这两个事务createOrderList 和 addLineItem中来,作为我们的试验。同时注重我们并没有要求最好的设计——你可能注重到了 addLineItem 方法抛出了 FacadeException, 而 createOrderList 没有。在产品设计中,你也许希望每一个方法都处理异常。

public class OrderListManagerImpl

implements OrderListManager{private AuditManager auditManager;public Long createOrderList (OrderList orderList){

Long orderId = orderListDAO.createOrderList(orderList);

auditManager.log(new AuditObject

(ORDER + orderId, CREATE));

return orderId;}public void addLineItem (Long orderId, LineItem lineItem)

throws FacadeException{

Long lineItemId = orderListDAO.

addLineItem(orderId, lineItem);

auditManager.log(new AuditObject

(LINE_ITEM + lineItemId, CREATE));

int numberOfLineItems = orderListDAO.

queryNumberOfLineItems(orderId);

if(numberOfLineItems 2){

log("Added LineItem " + lineItemId +

" to Order " + orderId + ";

But rolling back *** !");

throw new FacadeException("Make a new

Order for this line item");

}

else{

log("Added LineItem " + lineItemId +

" to Order " + orderId + ".");

}}//其他代码在这里}

要创建一个这个试验的异常,我们已经介绍了其他事务规则规定一个特定的次序不能在同一行里包含两个项目。我们应该注重到createOrderList 和 addLineItem调用了auditManager.log() 方法。你应该也注重到了上面方法中的事务属性。

<bean id="orderListManager"

class="org.springframework.transaction.

interceptor.TransactionProxyFactoryBean"

<pro

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有