2012-10-05 161 views
3

我对春节@Transactional注解和坚持的误解。我正在使用Spring 3.1,使用JPA和Hibernate。我认为persist意味着,将实体添加到持久性上下文中(但不要执行任何查询,直到提交或刷新),并且注释的含义是用事务包装该方法。春季交易注释,休眠和坚持

但是,在这个简短的例子中,当执行指针到达时,由于名称不能为空(db约束),所以它会失败并产生异常。

import javax.persistence.EntityManager; 

@PersistenceContext 
private EntityManager entityManager; 

@Transactional 
public void test() { 
    Brand brand = new Brand(); 
    entityManager.persist(brand); 
    brand.setName("test"); 
} 

如果我换setName()persist(),一切正常。然而,我不明白为什么其他解决方法不会这样,因为我认为任何查询都会在方法结束时生成并执行。

有人能解释一下吗?

回答

4

在JPA中,一旦对象传递给persist(),它就变成了“托管”,作为托管JPA实现的一部分,必须为该持久对象生成一个id。

如果id生成基于自动增量(GenerationType.IDENTITY),则需要向db发出insert语句来获取和分配键。当id生成基于sequence/table时,id由JPA Implementation管理标识池管理和分配,在这种情况下,不需要直接插入。

让一个对象传递给persist()并成为托管对象,对其进行的任何更改都必须将持久字段刷新到事务处理中的数据库。在你的情况下,如果身份证号是身份,则必须在更新后执行插入操作。如果id生成是其他方法,那么只需一个插入语句即可。如果事务回滚,则根本不应该将SQL发送到数据库。

这是在Batoo JPA中的实现。

希望这是有道理的。

+0

有趣,有道理,现在我明白了,实际上我有GenerationType.IDENTITY。谢谢 – stivlo

2

它的承诺由于事务性注释的方法结束。但是新记录是持续创建的,并且可以抛出任何异常。

在方法结束之前,它仍然可以回滚;我通常使用回滚来注释异常。

0

坚持执行“插入”查询。事务注释仅用于启动事务,如果发生异常,则回滚事务。