Spring Transactional注释,Hibernate和persist

时间:2012-10-05 15:55:39

标签: spring hibernate

我对Spring @Transactional注释产生了误解并持续存在。我正在使用Spring 3.1,JPA和Hibernate。我认为persist意味着,将实体添加到持久化上下文(但是在commit或flush之前不执行任何查询),并且@Transactional注释意味着,用事务包装方法。

但是,在这个简短的例子中,当执行指针到达时,它会因异常而失败,因为name不能为null(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(),一切正常。但是,我不明白为什么反过来没有,因为我认为任何查询都将在方法结束时构建和执行。

有人可以解释一下吗?

3 个答案:

答案 0 :(得分:4)

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

如果id生成基于自动增量(GenerationType.IDENTITY),则需要向db发出insert语句以获取并分配密钥。当id生成基于序列/表时,则由JPA实现管理的id池管理和分配id,在这种情况下,不需要直接插入。

将对象传递给persist()并进行管理后,对其进行的任何更改都必须将持久字段刷新到事务处理中的数据库。在您的情况下,如果id生成为Identity,则必须在插入后执行更新。如果id生成是其他方法,那么单个insert语句就足够了。如果事务被回滚,则根本不应该将SQL发送到数据库。

这是Batoo JPA中的实施。

希望这是有道理的。

答案 1 :(得分:2)

由于事务性注释,

在方法结束时已提交。但是新记录是在持久化的情况下创建的,并且可以抛出任何异常。

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

答案 2 :(得分:0)

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