使用Spring 3.1,Mojarra,Hibernate
的applicationContext.xml
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
...
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<context:component-scan base-package="mypackage"/>
TestBean.java
@Component
@Scope("session")
public class TestBean {
@Autowired private @Getter @Setter HibernateTemplate hibernateTemplate=null;
public String submit(){
try{
this.test();
}catch (RuntimeException ex) {
FacesUtil.addWarn("Error");
}
return null;
}
@Transactional
public String test() {
Device d1=new Device();
hibernateTemplate.persist(d1);
if(1==1)
throw new RuntimeException("Testing");
Device d2=new Device();
hibernateTemplate.persist(d2);
return null;
}
}
这有效(回滚),但在浏览器中显示异常
<h:commandButton value="Submit" action="#{testBean.test}"/>
尝试显示面部消息,但这会提交d1
<h:commandButton value="Submit" action="#{testBean.submit}"/>
调用其他bean的(DAO)事务方法也行,但是我想在托管bean本身中使用代码。如何在JSF中处理事务?
答案 0 :(得分:1)
将交易方法移至另一个图层,或者如果您因某些原因希望避免使用TransactionTemplate
:
public String test() {
TransactionTemplate txTemplate = new TransactionTemplate(transactionManager);
try {
txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
// your transactional code here;
}
});
} catch (Exception e) {
// handle exception here
}
return null;
}
答案 1 :(得分:0)
更好地采用分层架构服务和DAO层,直接处理托管bean中的事务会违背类的单一责任原则的目的。
Managed Bean灵魂目的应该是导航处理和从视图层到服务层的数据网关,您可以在其中执行主业务逻辑或用例并将数据持久性委托给DAO层。
就涉及到UI的消息而言,您可以从服务层捕获异常并相应地填充所需的消息。
这样事情更易于管理,可维护和可测试。模拟服务层,测试数据持久性的DAO和视图层的受管Bean。
Spring使用代理/ AOP来实现神奇的@Transactional,并且它更好的代码接口,因为它有自己的问题,如果你不编码接口,即直接代理到接口或CGLIB子类注入。在文档中查找代理设置的标记,以便更好地理解代码接口的含义。
注意:HibernateTemplate被认为是一个反模式,并且从Hibernate 4中删除只支持一个指针,因此如果在Hibernate 3上你可以采取相应的行动。
希望这会有所帮助!!!!!