我在学校和学生实体之间建立了OneToMany关系。我想做的是,当我保存学校对象时,不要保存或更新学生对象(当然也不要删除它们)。
当我尝试保存如下所示的学校对象时,它也会更新我的学生对象,但我不希望它们被更新,而只能是可联合的。有什么办法吗?
我删除了Cascade,但它仍然无法正常工作。
School school = new School();
school.setStudents(studentList);
repository.save(school);
我的实体;
@OneToMany(fetch = FetchType.EAGER)
@JoinTable(name = "school_student", joinColumns = {@JoinColumn(name = "school_id")},
inverseJoinColumns = {@JoinColumn(name = "student_id")})
private List<Student> students;
编辑:
最佳答案
我认为您的意思是您要管理关联本身-即哪些学生与学校关联-而不是学生详细信息。出于概念和实际原因,恐怕这没有多大意义。
从概念上讲,一对多关系的“拥有”侧始终是“许多”。通过联接表管理关联时,这有点武断(但仍然如此),但是当直接通过实体属性管理关联时,这一点很重要。更新关联需要在拥有方(在本例中为Student
)中管理实体。
实际上,仅从School
一侧管理关联会带来一些困难。例如,如果将新的Student
添加到School
怎么办?在保留关联之前,必须先保留该学生,但是您要避免这种情况的发生。将Student
从一种School
移到另一种School
时,存在类似但较小的问题。
现在,您确实可以避免将持久性操作从Student
层叠到其School
,但是我希望这样做的结果是无法与管理cascade
一起管理它们之间的关联。如果您要这样做,则可以从@OneToMany
批注中省略任何Student
属性,或者显式指定级联类型的空列表。
但是,还请注意,当您对持久性上下文提交更改时,将保存对所有持久性实体的更改。如果要修改School
实体而不将这些更改保存到数据库中,那么最好的选择可能是分离这些实体,或者制作它们的分离副本。
更新:
正如评论中已阐明的那样,基本问题是,当应用程序没有权限更新Student
基表但对连接表具有足够权限时,如何修改Student
和School
实体之间的关系。代表。您不能与持久更改School
一起自动执行此操作,因为Student
不是(也不能是)关系的拥有方。
需要说明的是:JPA尝试将School
实体移动到其他Student
时保存,因为出于其目的,School
和他的特定Student
之间的关联是Student
状态的一部分。如果School
实体已附加到持久性上下文中并且很脏(例如,因为它已分配给其他School
),则在提交对PC的更改时将对其进行更新。这与级联或Student
的状态没有什么特别的关系,只不过您可以通过将School
的状态间接移动到其他students
的EntityManager
列表来修改它们的状态。
由于您使用的是联接表,因此您可以修改对象模型以将每个学生/学校协会独立地表示为一个实体。如果这些协会具有自己的属性,例如注册日期,那将是有道理的,但否则我不建议这样做。
另一种方法是编写 native 查询(通过JPA)。您会在网上找到许多有关该信息的信息,例如https://blogs.oracle.com/JPQL01/entry/native_query_in_java_persistence。但是,这确实带来了一些问题。特别是,它会使Student
的缓存无效,如果不加以处理,可能会导致严重的问题。对您来说也很重要的是,它会产生实体更改而不会触发如果正常执行更新会触发的实体生命周期方法。
关于缓存,解决方案是分离受影响的School
和EntityManager.detach()
(旧的和新的)实体。您可以选择使用EntityManager.clear()
进行选择,也可以使用ojit_code进行选择。之后,您将需要重新查询或合并要继续使用的实体,这可能会引起一些困惑的问题,具体取决于使用它们的方式以及其他代码对它们的假设。
至于生命周期方法,如果您需要确保它们触发,那么您可以选择自己调用它们。
This article提供了有关您可能需要执行的操作的更多详细信息。