Spring Boot Sprint Data JPA -将子实体与具有共享主键的父实体一起保存

thtygnil  于 2022-11-29  发布在  Spring
关注(0)|答案(1)|浏览(154)

我有两个表'STUDENT'(pk -自动生成的学生标识)和'Address'。address_id是Address表的pk,它必须与学生标识具有相同的值。
实体:

@Entity
@Table(name = "student")
Public class Student{

    @Id
    @GeneratedValue
    @Column(name = "STUDENT_ID",updatable = false,insertable = false)
    private long Id;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name="STUDENT_ID")
    private Address address;

.....
//getters setters
}

@Entity
@Table(name = "address")
Public class Address{

    @Id
    @Column(name = "ADDRSS_ID",updatable = false,insertable = false)
    private long Id;

    @OneToOne
    private Student student;

.....
//getters setters
}


service 

public class Service {

 @Autowired StudentRepository repo;

 public void saveStudent(Student s){

 repo.save(s)
}

}

我面临的问题是因为级联。所有JPA尝试保存子实体,即父实体Student之前的Address,但ADDRESS_ID具有NOT NULL约束,并且我遇到约束违规异常。如何一次性保存这两个实体。请帮助。提前感谢

e5njpo68

e5njpo681#

你问的
如何一次保存实体和关联实体。
让我们把“一次完成”翻译成一个事务,有很多方法可以实现这一点,所有这些方法都在于这样一个事实:对于持久化实体,在提交整个事务之前的适当时间点进行刷新。

解决方案

一种做法是根据JPA规范采用一种具有可延迟约束的后缓存机制,先持久化StudentAddress实体,通过刷新从数据库中获取生成器的id,然后在它们之间建立适当的绑定和关联,最后提交事务。
为了演示它,从会话抽象开始,即EntityManager,它代表一级缓存,您可以通过EntityManagerFactory示例化它,它实际上代表二级缓存。

EntityManager entityManager = entityManagerFactory.createEntityManager()
entityManager.getTransaction().begin();
entityManager.persist(Not_associated_entities);
...
flush();
...
entityManager.merge(associated_entities);
...
entityManager.getTransaction().commit();
entityManager.close();

另外专门针对PK和FK列最常建立索引,因此共享PK可以将索引占用空间减少一半,这是可取的,因为您希望将所有索引存储到内存中以加快索引扫描,您可能会在此article中进行OneToOne关联优化。

注意事项

总是close所有手动示例化的entityManager。

相关问题