2011-02-24 62 views
9

有没有任何方法可以在约束违反异常被抛出后继续使用线程绑定的hibernate会话?我给一个简单的例子在这里:ConstraintViolationException后Hibernate会话失效

Parent other=service.load(33); // loads a new parent 
    try { 
     Parent p=new Parent(); 
     p.setName("A name"); 
     service.save(p); // a @Transactional spring service class, throws ConstraintViolationException - name should be at least 15 characters long 
    } catch (ConstraintViolationException e){ 
     // i would like to handle validation errors and proceed normally 
     // but the session is allready closed here 
    } 
    System.out.println("Children: " + other.getChildren()); // lazy initialization exception, even when using opensessioninview 

从现在开始Hibernate的Session是完全无用的,甚至是只读喜欢用OpenSessionInView模式鉴于渲染延迟集合操作。

回答

12

Session的文档指出如果会话引发异常,则必须回滚事务并丢弃会话。发生异常后,会话的内部状态可能与数据库不一致。。由于这些问题,我记得有人在工作时警告我不要使用session-per-request/OpenSessionInView-模式。

+0

这可能是正确的答案,但多么令人不满!在使用JPA(Hibernate 3)和Spring的应用程序中,我注意到当我们在合并之后显式刷新实体管理器时抛出了'ConstraintViolationException异常,但如果我们移除了flush,则抛出了一个更通用的Spring'TransactionSystemException',其中包含嵌套的'RollbackException',它又包含根'ConstraintViolationException'。但是,在捕获'TransactionSystemException'后,实体管理器(hibernate会话)仍然可用。没有更多的懒惰初始化错误! – 2013-10-18 22:34:12

+1

@Brice:考虑到文档明确指出在引发异常之后不使用Session,找到一个解决方法仍然使用它并不会降低危险性。它可能适用于某些情况而不适用于其他情况,导致不确定的行为。但是,如果它对你没有任何问题,那么好!尽管如此,个人而言,我宁愿不使用任何这样的“噱头”,而是首先解决交易中的问题(例如,在这个问题中,例如,以某种其他方式验证输入,而不是对数据库进行验证)。 – esaj 2013-10-19 11:57:41

+0

我同意。更清楚的是,这个问题与bean验证(JSR 303)异常('javax.validation.ConstraintViolationException'而不是数据库约束异常)有关,导致会话/实体管理器抛出一个异常使其本身无用。在pre-persist/pre-update/pre-remove验证失败后,仍然可以将会话用于只读查询将会很好。在这种情况下,在数据库级别上没有任何事情会使会话变得危险(据我所知),这仅仅是使某个实体无效的业务规则。 – 2013-10-21 20:24:43

5

使用StatelessSession而不是Session。这是一个窍门。

使用StatelessSession,您可以在任何异常之后继续执行,因为它可能在SQL中(甚至在一个事务中 - 没有提交/回滚由休眠完成)。这对批量更新/插入或检查是否违反唯一约束是理想的。

但请注意,与普通会话相比,StatelessSession有许多限制。请参阅Hibernate文档/ Javadocs。

+0

适合我! (到目前为止) – displayname 2015-05-29 14:54:36

+0

谢谢。工作。我只需要插入,它的工作。 – Bhaskara 2015-09-08 07:06:46

相关问题