【发布时间】:2021-03-13 09:46:59
【问题描述】:
我想知道 Spring Data JPA 的实际行为记录在哪里,因为它恰好是 与使用实体管理器的常规 JPA 中所期望的不同。我有兴趣找到 关于 Spring JPA 中实体生命周期的文档。
例如,假设我们有三个实体,Message、Author 和 Label。一封邮件可以有多个标签,但只有一个作者。
所以消息基本上是:
@Entity
public class Message implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;
@ManyToMany
private Set<Label> labels = new HashSet<>();
@ManyToOne
private Author author;
...
}
链接是单向的。
考虑服务中的以下代码:
Author a = new Author("auteur A");
a = authorRepository.save(a);
Message msg = new Message("un message", "texte du message", a);
msg = messageRepository.save(msg);
for (int i=0; i < 10; i++) {
Label lab = new Label("label"+i);
lab = labelRepository.save(lab);
labelRepository.flush();
msg.addLabel(lab);
}
messageRepository.save(msg);
如果我省略最后一行 (messageRepository.save(msg)),则会创建标签,但它们并没有真正添加到消息中。考虑到底层技术是 JPA,我觉得这出乎意料:
等效代码 带有实体管理器的标准 JPA 将是:
EntityManagerFactory emf = Persistence.createEntityManagerFactory("demo1PU");
EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();
Author a = new Author("auteur A");
em.persist(a);
Message msg = new Message("un message", "texte du message", a);
em.persist(msg);
for (int i=0; i < 10; i++) {
Label lab = new Label("label"+i);
em.persist(lab);
msg.addLabel(lab);
}
transaction.commit();
em.close();
emf.close();
在基于 entitymanager 的代码中,您不需要保存消息两次:因为您仍然处于相同状态 事务,消息是一个托管实体,并且在事务处于活动状态时对此对象所做的所有更改也会对数据库条目进行。
显然,Spring 管理的实体与常规 EntityManager 操作的实体有些不同。但是某处是否有一些明确的文档? spring-data-jpa-reference.pdf 文件没有多大帮助。
【问题讨论】:
-
您是否在
@Transactional方法中执行您的服务代码? -
是的,当然。
-
打开 SQL
spring.jpa.hibnerate.show-sql=true作为开始了解发生了什么。但除此之外,谁拥有 Message-Label 关系,你为什么要脸红?显示您的标签实体代码。 -
附带说明,如果您想了解存储库方法的工作原理,请查看
SimpleJpaRepository -
@Lesiak 所以,这就是问题所在。用 PostConstruct 注释的方法不能是事务性的。
标签: jpa spring-data-jpa entitymanager