Spring事务注释、Hibernate和persist

Spring事务注释、Hibernate和persist,spring,hibernate,Spring,Hibernate,我对Spring@Transactional注释和persist有一个误解。我使用的是Spring3.1,带有JPA和Hibernate。我认为persist意味着将实体添加到持久性上下文中(但在提交或刷新之前不要执行任何查询),而@Transactional注释意味着用事务包装方法 然而,在这个简短的示例中,当执行指针到达persist时,它会失败并出现异常,因为name不能为null(db constraint) 如果我交换setName()和persist(),一切正常。然而,我不明白为什

我对Spring
@Transactional
注释和persist有一个误解。我使用的是Spring3.1,带有JPA和Hibernate。我认为persist意味着将实体添加到持久性上下文中(但在提交或刷新之前不要执行任何查询),而
@Transactional
注释意味着用事务包装方法

然而,在这个简短的示例中,当执行指针到达persist时,它会失败并出现异常,因为name不能为null(db constraint)

如果我交换
setName()
persist()
,一切正常。然而,我不明白为什么另一种方法不行,因为我认为任何查询都会在方法的末尾生成和执行


有人能解释一下吗?

由于事务性注释,它的在方法末尾提交了。但是新记录是在persist上创建的,任何异常都可以抛出


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

persist执行“insert”查询。事务处理注释仅用于启动事务,如果发生异常,则回滚事务。

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

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

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

这是在中的实现


希望这有意义。

有趣,有意义,现在我明白了,事实上我有GenerationType.IDENTITY。谢谢
import javax.persistence.EntityManager;

@PersistenceContext
private EntityManager entityManager;

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