Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/395.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何对每个请求使用一个事务Spring+Hibernate+Spring Security+JSF_Java_Spring_Hibernate_Jsf 2_Spring Security - Fatal编程技术网

Java 如何对每个请求使用一个事务Spring+Hibernate+Spring Security+JSF

Java 如何对每个请求使用一个事务Spring+Hibernate+Spring Security+JSF,java,spring,hibernate,jsf-2,spring-security,Java,Spring,Hibernate,Jsf 2,Spring Security,我在使用JSF2.1+Hibernate4.1.7+Spring3.2.1+SpringSecurity+SQLServer2012的web应用程序中工作。 一切正常,即积垢操作。但是有些方法需要处理2个或更多的实体,例如更新、添加等 getEntity1Service().merge(); // line 1 getEntity2Service().create(); // line 2 getEntity3Service().delete(); // line 3 如果执行第2行crea

我在使用JSF2.1+Hibernate4.1.7+Spring3.2.1+SpringSecurity+SQLServer2012的web应用程序中工作。 一切正常,即积垢操作。但是有些方法需要处理2个或更多的实体,例如更新、添加等

getEntity1Service().merge();  // line 1
getEntity2Service().create(); // line 2
getEntity3Service().delete(); // line 3
如果执行第2行create entity时发生错误,我需要合并的entity或update、create或PREVIOR DB函数来获得回滚,以便我的DB上的数据保持正确

我将OpenSessionInViewFilter与@Transactional Spring注释结合使用

<filter>
    <filter-name>hibernateFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
    <init-param>
        <param-name>sessionFactoryBeanName</param-name>
        <param-value>SessionFactory</param-value>
    </init-param>
</filter>
    <filter-mapping>
        <filter-name>hibernateFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
我错过了什么?因为当执行第1行时,数据被发送到DB

从我的应用程序日志中提取

执行第1行时

...
23 05 2013 00:04:46,650 DEBUG [http-apr-8080-exec-345] (e.engine.transaction.internal.jdbc.JdbcTransaction:doCommit:113) - committed JDBC Connection
23 05 2013 00:04:46,650 DEBUG [http-apr-8080-exec-345] (e.engine.transaction.internal.jdbc.JdbcTransaction:releaseManagedConnection:126) - re-enabling autocommit
23 05 2013 00:04:46,651 DEBUG [http-apr-8080-exec-345]
...
执行第2行时

(ork.orm.hibernate4.support.OpenSessionInViewFilter:lookupSessionFactory:188) - Using SessionFactory 'SessionFactory' for OpenSessionInViewFilter 23 05 2013 00:05:27,777 DEBUG [http-apr-8080-exec-349]
(ramework.beans.factory.support.AbstractBeanFactory:doGetBean:246) - Returning cached instance of singleton bean 'SessionFactory' 23 05 2013 00:05:27,777 DEBUG [http-apr-8080-exec-349]
(ork.orm.hibernate4.support.OpenSessionInViewFilter:doFilterInternal:141) - Opening Hibernate Session in OpenSessionInViewFilter 23 05 2013 00:05:27,778 DEBUG [http-apr-8080-exec-349]
(org.hibernate.internal.SessionImpl ::312) - Opened session at timestamp: 13692891277
先谢谢你

**感谢您的回复,更新问题:****

这是我的applicationContext.xml:

我也尝试过在服务层接口/服务层类上使用@Transactional,但当控制返回到JSF managedBean时,提交仍然在发生

情景2。 *从服务层删除@Transactional并在JSF托管bean方法上使用它时:*


DB上的更改不再由服务层提交,但问题是,所有流get finished控制返回到客户端,但提交到DB的操作从未发生!请参阅我的第三个问题更新

要获得回滚,您必须确保以下事项:

从第一个代码截取的所有3行必须打包到一个事务中 事务注释必须由Spring拾取,并且必须在运行时应用实际事务。由于存在多个问题,此点可能不起作用。为确保事务已启动,请在第一行上设置制动点并检查stacktrace。您必须在堆栈中看到事务拦截器。 为了确保不遗漏任何内容,最好在任何异常类型的情况下指示您想要回滚。默认情况下,回滚将仅针对RuntimeException及其子类触发 编辑要强制回滚,异常必须跨越事务边界,这意味着:a您根本不使用try/catch;或者,如果使用try/catch,则抛出异常。请参阅我的第二个代码段 @TransactionalrollbackFor=Exception.class 公共无效交易{ GetDaoImplementy1.merge;//第1行 GetDaoImplementity2.create;//第2行 GetDaoImplementity3.delete;//第3行 } 第二个代码段异常:

@TransactionalrollbackFor=Exception.class public void doInTransaction引发异常{ 试一试{ GetDaoImplementy1.merge;//第1行 GetDaoImplementity2.create;//第2行 GetDaoImplementity3.delete;//第3行 }捕获异常{ Logger.getLoggerBeanJSF1.class.getName.logLevel.SEVERE,null,ex; throw ex;//非常重要!!!如果没有此项,异常不会跨越事务边界`doInTransaction`方法,Spring wan也不会为您执行回滚 } }
要获得回滚,您必须确保以下事项:

从第一个代码截取的所有3行必须打包到一个事务中 事务注释必须由Spring拾取,并且必须在运行时应用实际事务。由于存在多个问题,此点可能不起作用。为确保事务已启动,请在第一行上设置制动点并检查stacktrace。您必须在堆栈中看到事务拦截器。 为了确保不遗漏任何内容,最好在任何异常类型的情况下指示您想要回滚。默认情况下,回滚将仅针对RuntimeException及其子类触发 编辑要强制回滚,异常必须跨越事务边界,这意味着:a您根本不使用try/catch;或者,如果使用try/catch,则抛出异常。请参阅我的第二个代码段 @TransactionalrollbackFor=Exception.class 公共无效交易{ GetDaoImplementy1.merge;//第1行 GetDaoImplementity2.create;//第2行 GetDaoImplementity3.delete;//第3行 } 第二个代码段异常:

@TransactionalrollbackFor=Exception.class public void doInTransaction引发异常{ 试一试{ GetDaoImplementy1.merge;//第1行 GetDaoImplementity2.create;//第2行 GetDaoImplementity3.delete;//第3行 }捕获异常{ Logger.getLoggerBeanJSF1.class.getName.logLevel.SEVERE,null,ex; throw ex;//非常重要!!!如果没有此项,异常不会跨越事务边界`doInTransaction`方法,Spring wan也不会为您执行回滚 } }
好的,在看到这一点之后,我猜测问题在于SpringJSF集成。问题可能是因为您使用的是Spring事务管理器。但是您的bean是由JSF@ManagedBean和@ManagedProperty管理和注入的。这可能会导致一些意外的事务行为。 为了解决这个问题,我的建议是将所有bean或至少与事务相关的bean放在一起 er spring控件使用@Component而不是@ManagedBean和@Autowired或@Inject而不是@ManagedProperty。 为了仍然能够通过EL从JSF访问bean,您需要像下面这样将SpringBeanFacesELResolver添加到faces配置中

<application>
    <el-resolver>
            org.springframework.web.jsf.el.SpringBeanFacesELResolver
    </el-resolver>
</application>
以下是一个基本教程,可以逐步进行解释:


即使这不能解决眼前的问题,它仍然是有益的,使项目更加一致,更不容易出错。

好的,在看到这一点后,我猜问题在于Spring JSF集成。问题可能是因为您使用的是Spring事务管理器。但是您的bean是由JSF@ManagedBean和@ManagedProperty管理和注入的。这可能会导致一些意外的事务行为。 为了解决这个问题,我的建议是使用@Component而不是@ManagedBean和@Autowired或@Inject而不是@ManagedProperty将所有bean或至少与事务相关的bean置于spring控制之下。 为了仍然能够通过EL从JSF访问bean,您需要像下面这样将SpringBeanFacesELResolver添加到faces配置中

<application>
    <el-resolver>
            org.springframework.web.jsf.el.SpringBeanFacesELResolver
    </el-resolver>
</application>
以下是一个基本教程,可以逐步进行解释:


即使这不能解决眼前的问题,它仍然是有益的,可以使项目更一致,更不容易出错。

您已经使DAO成为事务性的,因此每个DAO方法都会导致单独的事务,这并不奇怪。DAO方法永远不应该是事务性的。事务属于服务层。

您已经使DAO成为事务性的,因此每个DAO方法都会导致一个单独的事务,这并不奇怪。DAO方法永远不应该是事务性的。事务属于服务层。

好的,谢谢大家抽出时间。解决方案正如@Ryan Stewart所说。总之:

使用服务层 如果需要同时处理多个实体,请在服务层而不是业务逻辑层处理所有实体 在服务层上的方法将控制返回到业务逻辑层方法之后,如果出现问题,则不会将任何内容持久化到DB;但如果没有触发异常,那么所有实体都会被提交。 还有一件事,我添加了一个新的DaoService,它从我的GenericDAOService扩展而来,因此在这个新的服务实现中,我有第2点提到的特定逻辑


再次感谢大家。

好的,谢谢大家抽出时间。解决方案正如@Ryan Stewart所说。总之:

使用服务层 如果需要同时处理多个实体,请在服务层而不是业务逻辑层处理所有实体 在服务层上的方法将控制返回到业务逻辑层方法之后,如果出现问题,则不会将任何内容持久化到DB;但如果没有触发异常,那么所有实体都会被提交。 还有一件事,我添加了一个新的DaoService,它从我的GenericDAOService扩展而来,因此在这个新的服务实现中,我有第2点提到的特定逻辑


再次感谢大家。

您使用什么事务管理器,以及如何配置?还有一个问题是如何设置您的事务。据我所知,问题似乎不在于OpenSessionInViewFilter,而在于事务设置,因为在第1行之后有一个专用的提交。OpenSessionInViewFilter的默认行为是用只读事务包装整个请求,以支持JSP中的延迟加载。它不提交事务,并假设服务层@Transactional方法将处理将数据提交到数据库的操作。合并和创建操作是否在同一个@Transactional方法中发生?如果没有,我认为它们将被视为独立交易。感谢您的回复。我也更新了@Carsten的问题。您使用什么事务管理器,以及如何配置?还有一个问题是如何设置您的事务。据我所知,问题似乎不在于OpenSessionInViewFilter,而在于事务设置,因为在第1行之后有一个专用的提交。OpenSessionInViewFilter的默认行为是用只读事务包装整个请求,以支持JSP中的延迟加载。它不提交事务,并假设服务层@Transactional方法将处理将数据提交到数据库的操作。合并和创建操作是否在同一个@Transactional方法中发生?如果没有,我认为它们将被视为独立交易。感谢您的回复。我也更新了@Carsten的问题。好的,我现在就去试试。谢谢,我会让你知道的。好的,我现在就去试试。谢谢,我会让你知道的。我已经添加了服务层并在上面使用了@Transactional,但是我得到了相同的结果,然后我使用了Transactional
JSF托管bean方法上的spring注释,但现在在DB上没有提交任何内容。请帮忙!请参阅我的第三个问题更新。您最初的抱怨是每次DAO方法返回时tx都会提交。现在您似乎在说您已经成功地将tx边界向上移动到了服务层。这是做这件事的正确地点,但你似乎仍然不满意。我不确定你在找什么。是的,没错,我现在已经实现了服务层。我遇到的问题是相同的,我使用@Transactional on服务层接口/服务层类,当控制返回到JSF managedBean方法时,提交仍在发生。。如果我直接在JSF managedBean方法上使用事务性注释,任何实体都会被提交。1如果您使用的是服务层方法,那么所有事务都应该在服务层中发生。2 Spring将仅管理声明的ApplicationContext中的事务。当您不完全理解Spring的工作原理时,这是一个常见的错误。请参阅,例如,和。我添加了服务层并在其上使用@Transactional,但得到了相同的结果,然后在JSF托管bean方法上使用了Transactional spring注释,但现在在DB上没有提交任何内容。请帮忙!请参阅我的第三个问题更新。您最初的抱怨是每次DAO方法返回时tx都会提交。现在您似乎在说您已经成功地将tx边界向上移动到了服务层。这是做这件事的正确地点,但你似乎仍然不满意。我不确定你在找什么。是的,没错,我现在已经实现了服务层。我遇到的问题是相同的,我使用@Transactional on服务层接口/服务层类,当控制返回到JSF managedBean方法时,提交仍在发生。。如果我直接在JSF managedBean方法上使用事务性注释,任何实体都会被提交。1如果您使用的是服务层方法,那么所有事务都应该在服务层中发生。2 Spring将仅管理声明的ApplicationContext中的事务。当您不完全理解Spring的工作原理时,这是一个常见的错误。请参阅,例如,和。当我在JSF managedBean方法上使用事务性注释时,该方法中更新的任何实体都会在数据库中提交。为什么?请提供帮助。当我在JSF managedBean方法上使用事务性注释时,该方法中更新的任何实体都会在数据库中提交。为什么?请帮忙。
@Transactional(rollbackFor=Exception.class)
public class GenericDAOHibernateImpl <T, PK extends Serializable> implements GenericDAOHibernate<T, PK>, Serializable{

    @Override
    public void mergeEntity(T object) {
        getSessionFactory().getCurrentSession().merge(object);
    }

    @Override
    public void deleteEntity(T object) {
        getSessionFactory().getCurrentSession().delete(object);
    }
}
//Injection to my generic dao:
    @ManagedProperty(value = "#{entity1DAO}")
    GenericDAOHibernate<Entity1,Integer> entity1Service;
    @ManagedProperty(value = "#{entity2DAO}")
    GenericDAOHibernate<Entity2,Integer> entity2Service;
    @ManagedProperty(value = "#{entity3DAO}")
    GenericDAOHibernate<Entity3,Integer> entity3Service;
    //other variables and methods 
    @Transactional(rollbackFor = Exception.class)
    public void onUpdatingRowData(RowEditEvent ree) {
        try{
            getEntity1Service().mergeEntity(ree.getObject());//this get committed on DB
            getEntity2Service().deleteEntity(object2);//this fires an Exception
        } catch (Exception ex) {
            Logger.getLogger(BeanJSF1.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
public interface IGenericDAOHibernate <T, PK extends Serializable>{ ...

public class GenericDAOHibernate <T, PK extends Serializable> implements IGenericDAOHibernate<T, PK>, Serializable{ ...
public interface IGenericDAOHibernateService <T, PK extends Serializable>{ ...

@Transactional(rollbackFor = Exception.class)
public class GenericDAOHibernateImpl <T, PK extends Serializable> implements IGenericDAOHibernateService<T,PK>{
    public IGenericDAOHibernate genericDAOHibernate; ...
<bean id="GenericDAOService" class="com.x.services.generic.GenericDAOHibernateImpl"><property name="genericDAOHibernate" ref="GenericDAOHibernate" /></bean> 
 <bean id="GenericDAOHibernate" class="com.x.dao.generic.GenericDAOHibernate">
     <property name="sessionFactory" ref="SessionFactory" />
 </bean>
@ManagedBean
@ViewScoped
public class BJsfBeanX extends BCommon implements Serializable {
    @ManagedProperty(value = "#{GenericDAOService}")
        IGenericDAOHibernateService genericService; ...


public void onUpdatingDataRow(RowEditEvent ree) throws Exception {
    try{
                getGenericService().updateEntity(entity1); //line1: where updateEntity go throw layers and execute on DAO Layer: getSessionFactory().getCurrentSession().merge(object);
            //this line at DAO class does not execute commit on data base, the commit is executed when the control is back to the managedBean method line1
            getGenericService().updateEntity(entity2);//line2: this throw Exception, but there is nothing to do rollback `cause the entity1 (line 1) has been already committed
     }catch
}
@Transactional(rollbackFor = Exception.class)
    public void onUpdatingDataRow(RowEditEvent ree) throws Exception {
<application>
    <el-resolver>
            org.springframework.web.jsf.el.SpringBeanFacesELResolver
    </el-resolver>
</application>