JPA RollbackException持久化事务导致后续有效事务失败?

Mat*_*att 0 java jpa transactions exception

我有一个@Transactional服务在oracle DB中执行持久化操作.如果我运行坚持打破一个唯一的违规,我得到预期的rollbackException:ConstraintException.

问题是任何后续请求(即使没有违反唯一约束)持久化都会引发相同的异常.

似乎JPA没有清除持久化其事务管理器的对象?我甚至关闭?我需要一点解释.

回购:

@Repository
public class UserRepository {

    @PersistenceContext(type=PersistenceContextType.EXTENDED)
    private EntityManager em;

    public User findUserById(long id){
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<User> query = builder.createQuery(User.class);

        Root<User> root = query.from(User.class);

        Predicate whereClause = builder.equal(root.get(User_.userId), id);

        return em.createQuery(query.where(whereClause)).getSingleResult();
    }

    public User findUserByCredentials(String credentials){

        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<User> query = builder.createQuery(User.class);

        Root<User> root = query.from(User.class);

        Predicate whereClause = builder.equal(root.get(User_.credentials), credentials);

        return em.createQuery(query.where(whereClause)).getSingleResult();
    }

    public void registerUser(User user){
         em.persist(user);
    }
}
Run Code Online (Sandbox Code Playgroud)

ServiceImpl:

@Transactional(readOnly=true)
@Service("userService")
public class UserServiceImpl implements UserService {

    @Resource
    private UserRepository userRepository;
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public User findUserById(long id) {
        return userRepository.findUserById(id);
    }

    public User findUserByCredentials(String credentials){
        return userRepository.findUserByCredentials(credentials);
    }

    @Transactional(readOnly=false)
    public void registerUser(User user){
        userRepository.registerUser(user);
    }

}
Run Code Online (Sandbox Code Playgroud)

端点错误抛出:

@PayloadRoot(localPart="RegisterUserRequest", namespace = "http://www.missingwire.com/schemas/User")
public RegisterUserResponseDocument registerUser(RegisterUserRequestDocument requestDoc){


    RegisterUserRequest request = requestDoc.getRegisterUserRequest();
    User user = new User();
    user.setCredentials(request.getCredentials());
    user.setPassword(request.getPassword());
    user.setHonorRating(BigDecimal.valueOf(STARTING_USER_HONOR_RATING));
    user.setAccountActive(true);
    user.setDateCreated(new Date());
    user.setVerified(false);

    UserProfile userProfile = new UserProfile();
    userProfile.setEmailAddress(request.getEmail());
    userProfile.setFirstName(request.getFirstName());
    userProfile.setLastName(request.getLastName());
    userProfile.setDateCreated(new Date());
    userProfile.setUser(user);
    user.setUserProfile(userProfile);

    **userService.registerUser(user);**  //HERE IS THE EXCEPTION THROW

    RegisterUserResponseDocument responseDoc = RegisterUserResponseDocument.Factory.newInstance();
    RegisterUserResponse response = responseDoc.addNewRegisterUserResponse();
    UserType userType = response.addNewUser();
    userType.setAccountActive(user.getAccountActive());
    userType.setCredentials(user.getCredentials());
    userType.setDateCreated(DateConverter.convertDateToXML(user.getDateCreated()));
    userType.setUserId(user.getUserId());
    userType.setVerified(user.getVerified());

    return responseDoc;

}
Run Code Online (Sandbox Code Playgroud)

例外:

org.springframework.orm.jpa.JpaSystemException:提交事务时出错; 嵌套异常是javax.persistence.RollbackException:在org.springframework.orm.jpa.vendor.HandnateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect)的org.springframework.orm.jpa.EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(EntityManagerFactoryUtils.java:311)中提交事务时出错. java:102)org.springframework.work工作中的org.springframework.orm.jpa.ExtendedEntityManagerCreator $ ExtendedEntityManagerSynchronization.convertException(ExtendedEntityManagerCreator.java:501)org.springframework.orm.jpa.ExtendedEntityManagerCreator $ ExtendedEntityManagerSynchronization.afterCommit(ExtendedEntityManagerCreator.java:481) .transaction.support.TransactionSynchronizationUtils.invokeAfterCommit(TransactionSynchronizationUtils.java:133)org.springframework.transaction.support.TransactionSynchronizationUtils.triggerAfterCommit(TransactionSynchronizationUtils.java:121)at org.springframework.transaction.support.AbstractPlatformTransactionManager.triggerA fterCommit(AbstractPlatformTransactionManager.java:953)org.springframework上的org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:796)org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)位于org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java)的org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)中的.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393) :172)在org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)在$ Proxy37.registerUser(来源不明)在com.missingwire.achieve.soa.endpoint.UserEndpoint.registerUser(UserEndpoint.java: 76)在sun.reflect.NativeMethodAccessor的sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)Impl.invoke(NativeMethodAccessorImpl.java:57)在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)在java.lang.reflect.Method.invoke(Method.java:616)在org.springframework.ws.server org.springframework.ws.server.endpoint.adapter.AbstractMethodEndpointAdapter上的org.springframework.ws.server.endpoint.adapter.MarshallingMethodEndpointAdapter.invokeInternal(MarshallingMethodEndpointAdapter.java:140)中的.endpoint.MethodEndpoint.invoke(MethodEndpoint.java:132) .invoke(AbstractMethodEndpointAdapter.java:53)org.springframework.ws.server.MessageDispatcher.dispatch(MessageDispatcher.java:231)org.springframework.ws.server.MessageDispatcher.receive(MessageDispatcher.java:172)at org. springframework.ws.transport.support.WebServiceMessageReceiverObjectSupport.handleConnection(WebServiceMessageReceiverObjectSupport.java:88)at org.springframework.ws.transport.http.WebServiceMessageReceiverHandlerAdapter.handle(WebServiceMessageReceiverHandlerAdapter.java:5 7)在org.springframework.ws.transport.http.MessageDispatcherServlet.doService(MessageDispatcherServlet.java:221)在org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669)在org.springframework.web.servlet .FrameworkServlet.doPost(FrameworkServlet.java:585)位于org.apache的javax.servlet.http.HttpServlet.service(HttpServlet.java:637)的javax.servlet.http.HttpServlet.service(HttpServlet.java:717). catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java: 233)在org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)在org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)在org.apache.catalina.valves.ErrorReportValve .invoke(ErrorReportValve.java:102)在org.apache.catalina.core.StandardEngineValve.在org.apache上的org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)的org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)中调用(StandardEngineValve.java:109) .coyote.http11.Http11Protocol $ Http11ConnectionHandler.process(Http11Protocol.java:602)atg.apache.tomcat.util.net.JIoEndpoint $ Worker.run(JIoEndpoint.java:489)at java.lang.Thread.run(Thread .java:679)引起:javax.persistence.RollbackException:在org.springframework.orm.jpa.ExtendedEntityManagerCreator $ ExtendedEntityManagerSynchronization.afterCommit的org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:93)中提交事务时出错javax.persistence.PersistenceException::(ExtendedEntityManagerCreator.java:478)... 39多个所致org.hibernate.exception.ConstraintViolationException:在org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java无法执行JDBC批处理更新: 1235)在org.hibernate.ejb.AbstractEntityManage org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:81)中的rImpl.convert(AbstractEntityManagerImpl.java:1168)... 40更多引起:org.hibernate.exception.ConstraintViolationException:无法在以下位置执行JDBC批处理更新org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)在org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)在org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)在org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:114)在org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:109)在org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:244 )在org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2395)在org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2858)在org.hibernate.action.EntityInsertAction.execute( EntityInsertAction.java:79)org.hibernate.engine.ActionQueue.execute(ActionQueue.java:267)org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:259)at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:178) )在org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)在org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)在org.hibernate.impl.SessionImpl.flush(在org.hibernate.ejb.TransactionImpl.commit的org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:375)org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)上的SessionImpl.java:1206) (TransactionImpl.java:76)... 40更多引起:java.sql.BatchUpdateException:ORA-00001:违反了唯一约束(ACHIEVE.SYS_C0016488)

at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10070)atracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:213)org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70) )org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)

JB *_*zet 7

您正在为扩展持久性上下文注入实体管理器.这意味着持久化上下文的生命周期与事务的生命周期无关:它会一直保持打开状态,直到您明确地关闭它为止.

由于您遇到RollbackException,持久化上下文处于脏的,不一致的状态,您唯一能做的就是立即关闭它.

如果持久性上下文是事务性上下文,则会自动关闭.但是,由于您使用的是扩展上下文,因此您可以明确地将其关闭.

请务必阅读并理解Spring文档的以下部分:

@PersistenceContext注释具有可选的属性类型,默认为PersistenceContextType.TRANSACTION.此默认值是接收共享EntityManager代理所需的内容.替代方案PersistenceContextType.EXTENDED是一个完全不同的事情:这会产生一个所谓的扩展EntityManager,它不是线程安全的,因此不能在并发访问的组件中使用,例如Spring管理的单例bean.扩展的EntityManagers仅应用于有状态组件,例如驻留在会话中,EntityManager的生命周期不依赖于当前事务,而是完全取决于应用程序.