【问题标题】:Spring4 + and Hibernate 4 TransactionsSpring4 + 和 Hibernate 4 事务
【发布时间】:2014-08-27 14:03:04
【问题描述】:

使用 spring 4.0.6.RELEASE、Hibernate 4.3.6.Final 和 hsqldb 2.3.2。我的集成测试如下所示;

 @Test(expected = DataIntegrityViolationException.class)
public final void testDuplicateItems() {
    final ServerEntity serverEntity1 = new ServerEntity("DuplicateItem");

    opService.save(serverEntity1);
    opService.save(serverEntity1);
}

这按预期工作。但是,当我运行我的独立 java 组件时,我可以保存第一项,第二项是重复的,但我无法捕获异常。这是日志文件

 WARN org.hibernate.engine.jdbc.spi.SqlExceptionHelper: SQL Error: -104, SQLState: 23505
2014-08-27 14:52:06,843  ERROR org.hibernate.engine.jdbc.spi.SqlExceptionHelper: integrity constraint violation: unique constraint or index violation; UK_NFU7LXMMDFVIR1WD08662085N table: SERVERENTITY
[WARNING] 
java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:293)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [UK_NFU7LXMMDFVIR1WD08662085N]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
    at org.springframework.orm.hibernate4.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:161)
    at org.springframework.orm.hibernate4.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:681)
    at org.springframework.orm.hibernate4.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:563)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:757)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:726)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:478)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:272)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    at com.sun.proxy.$Proxy38.execute(Unknown Source)
    at com.opserver.simpleapp.MainApp.start(MainApp.java:60)
    at com.opserver.simpleapp.MainApp.main(MainApp.java:37)
    ... 6 more

服务和 dao 实现在类级别都有 @Transactional。我有一个调用服务类的组件类,这个组件类不是事务性的!组件类打印响应,这里是否需要刷新会话?

需要弄清楚为什么dao中的save方法没有抛出异常,我实际上可以看到它正在创建一个id然后回滚。

J

我的组件类很基础;

boolean isValid = opServerService.loadXMLFile("Server.xml");

    try{

    if (isValid) {
        System.out.println("Entity has been added");
    } else {
        System.out.println("Entity has not been added");
    }
    }catch (Exception ex){
        System.out.println("that was a focked up");
    }

问题是“实体已添加”被打印到控制台,然后我在控制台中看到上述错误。

DAO 看起来像这样

@Override
    @Transactional
    public final void save(final ServerEntity serverEntity) throws DataIntegrityViolationException {
        LOGGER.debug(">>start(serverEntity=" + serverEntity + ")");
        Preconditions.checkNotNull(serverEntity);
        this.getCurrentSession().save(serverEntity);
    }

在类级别使用@Transactional 的服务方法,如下所示

@Override
    public final void save(ServerEntity serverEntity) {
        opServerDao.save(serverEntity);
    }

组件看起来像这样

@Component
public class AddCommand implements Command {

    @Autowired
    OpService opService;

    public AddServerCommand() {
        super();
    }

    @Override
    public void execute(String[] options) {

        try{
         boolean isValid = opService.save("Server.xml");
        if (isValid) {
            System.out.println("Entity has been added");
        } else {
            System.out.println("Entity has not been added");
        }
        }catch (Exception ex){
            System.out.println("Exception found");
        }
    }

}

【问题讨论】:

    标签: spring hibernate hsqldb transactional


    【解决方案1】:

    您应该在调用该服务的组件中捕获您的异常。

    【讨论】:

    • 更新了问题,添加了Exception来验证抛出了什么样的异常,但是loadXML没有抛出异常。
    • 你在哪里调用组件中的服务方法?你能把代码贴出来吗?
    • 所以你没有在 AddCommand 中调用 opService.save,如果你觉得在服务层不需要@transactional,那么删除它并在服务层捕获异常。您应该捕获事务边界之外的异常。
    • 这里是调用顺序。组件类(非事务性)调用 -> opService(OpServiceImplementation 在类级别是事务性的)调用 -> 调用 DAO 类(在类级别是事务性的)。在我的组件类中,我可以看到 isValid 返回为 true,因此打印了 msg。然后出现错误!是否需要刷新会话才能提前抛出提交异常?
    • 你的组件看起来不正确,你怎么能传递一个字符串来保存?请发布正确的代码,看看可以做些什么来解决这个问题。
    【解决方案2】:

    找到了解决方案,但 applicationContext.xml 中缺少该解决方案。包裹在 opService 周围的 try/catch 现在会捕获异常。需要实现我自己的自定义异常处理程序,但现在至少我知道组件类正在处理服务类抛出的异常。

    感谢您的帮助。

    J

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-01-27
      • 2015-09-07
      • 2015-01-15
      • 2011-06-13
      • 2014-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多