Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用CascadeType.MERGE与Spring数据存储库的正确方法是什么?_Java_Spring_Jpa_Spring Boot_Spring Data - Fatal编程技术网

Java 使用CascadeType.MERGE与Spring数据存储库的正确方法是什么?

Java 使用CascadeType.MERGE与Spring数据存储库的正确方法是什么?,java,spring,jpa,spring-boot,spring-data,Java,Spring,Jpa,Spring Boot,Spring Data,在提交保存entity2和entity3实例的事务时,每个实例都保存对Entity1(Entity1)实例的引用,导致数据库中出现Entity1的两条记录(因为保存每个实例时都会保存引用) 如果我有两个Spring数据存储库-Entity2Repository和Entity3Repository,我执行以下操作将导致数据库中包含实体1的两个实例: Entity1 entity1 = new Entity1(); entity1.name = "Name1"; entity1.value = "V

在提交保存
entity2
entity3
实例的事务时,每个实例都保存对Entity1(Entity1)实例的引用,导致数据库中出现Entity1的两条记录(因为保存每个实例时都会保存引用)

如果我有两个Spring数据存储库-
Entity2Repository
Entity3Repository
,我执行以下操作将导致数据库中包含实体1的两个实例:

Entity1 entity1 = new Entity1();
entity1.name = "Name1";
entity1.value = "Value1";

Entity2 entity2 = new Entity2();
entity2.name = "Name2";
entity2.value = "Value2";
entity2.setEntity1(entity1);

Entity3 entity3 = new Entity3();
entity3.name = "Name3";
entity3.value = "Value3";
entity3.setEntity1(entity1);

Entity2Repository.save(entity2);
Entity3Repository.save(entity3);
简短回答 它将正常工作(只生成一条
entity1
记录)

长话短说 示例代码执行的实际结果取决于测试方法上是否存在注释

Entity2Repository.save(entity2);
Entity3Repository.save(entity3);
这些调用将调用方法,该方法本身就是@Transactional

@Transactional
public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}
没有@Transactional

将有两个事务-每个
save()
调用一个事务

  • entity1
    entity2
    entity3
    现在是瞬态的
  • 调用了Entity2Repository.save(entity2)
  • 事务被打开,会话被创建
    • persist()
      作为新实体为
      entity2
      调用
    • persist()
      被级联到
      entity1
    • entity1
      entity2
      持久的现在,它们连接到 本届会议
  • 事务已提交,会话已关闭
  • entity1
    entity2
    现在已分离
  • 调用了Entity3Repository.save(entity3)
  • 事务被打开,会话被创建
    • persist()
      作为新实体为
      entity3
      调用
    • persist()
      被级联到
      entity1
    • org.springframework.dao.InvalidDataAccessApiUsageException:抛出传递给persist的分离实体
  • 事务回滚,会话关闭
entity1
entity2
条目保存在数据库中

带有@Transactional

默认情况下@Transactional传播是-只有一个事务

  • entity1
    entity2
    entity3
    现在是瞬态的
  • 事务被打开,会话被创建
    • 调用了Entity2Repository.save(entity2)
    • persist()
      作为新实体为
      entity2
      调用
    • persist()
      被级联到
      entity1
    • entity1
      entity2
      持久的现在,它们已附加到当前会话
    • 调用了Entity3Repository.save(entity3)
    • persist()
      作为新实体为
      entity3
      调用
    • persist()
      级联到一级缓存中找到的托管实体
      entity1
    • entity3
      持久的现在,它已附加到当前会话
  • 事务已提交,会话已关闭
entity1
entity2
entity3
条目保存在数据库中

public boolean isNew() {
    return null == getId();
}