如何防止使用JPA保存子对象? [英] How to prevent saving child object with JPA?

查看:126
本文介绍了如何防止使用JPA保存子对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在学校和学生实体之间建立了OneToMany关系.我想做的就是保存学校对象时不要保存或更新学生对象(当然也不要删除它们)

I got OneToMany relationship between school and student entities. What I want to do is when I save a school object don't save or update students object.(and of course don't delete them)

当我尝试像下面那样保存学校对象时,它也会更新我的学生对象,但我不希望它们被更新,而只能是可联合的.有什么办法吗?

When I try to save school object like below it also updates my student objects but I don't want them to be updated but only jointable. Is there any way?

我删除了Cascade,但它仍然无法正常工作.

I removed Cascade but its still not working.

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;

  • 当我尝试保存/更新/删除School对象时,请勿保存/更新/删除Student对象.认为我在学生表上没有任何插入/更新/删除权限.

推荐答案

当我尝试像下面那样保存学校对象时,它也会更新我的学生对象,但我不希望它们被更新,而只能是可联合的.有什么办法吗?

When I try to save school object like below it also updates my student objects but I don't want them to be updated but only jointable. Is there any way?

我认为您的意思是您要管理关联本身(即,哪些学生与学校关联),而不是学生详细信息.出于概念和实际原因,恐怕这没有多大意义.

I think you mean that you want the association itself to be managed -- i.e. which students are associated with the school -- but not the student details. This does not make much sense, I'm afraid, for both conceptual and practical reasons.

从概念上讲,一对多关系的拥有"侧始终是许多".通过联接表管理关联时,这有点武断(但仍然如此),但是当直接通过实体属性管理关联时,这一点很重要.更新关联需要在拥有方(在这种情况下为您的Student s)中管理实体.

Conceptually, the "owning" side of a one-to-many relationship is always the "many". This is a bit arbitrary (but nevertheless still true) when you manage the association via a join table, but it is important when the association is managed directly via entity attributes. Updating the association requires managing the entities on the owning side, which in this case is your Students.

实际上,仅从School一方管理关联会带来一些困难.例如,如果将 new Student添加到School,该怎么办?在保留关联之前,必须先保留该学生,但是您要避免这种情况的发生.将Student从一个School移到另一个时,存在类似但较小的问题.

As a practical matter, managing the association from the School side only would raise some difficulties. For example, what if a new Student is added to a School? That student needs to be persisted before the association can be persisted, but you want to avoid that happening. There is a similar, but lesser, problem when you move a Student from one School to a different one.

现在,您确实可以避免从School到其Student的级联持久性操作,但是我希望这样做的结果是无法同时管理它们之间的关联并管理School .如果您要这样做,则可以从@OneToMany批注中省略任何cascade属性,或者显式指定级联类型的空列表.

Now, you can indeed avoid cascading persistence operations from Schools to their Students, but I would expect the result of doing so to be failure to manage the association between them in conjunction with managing Schools. If that's what you want to do, then you would omit any cascade attribute from the @OneToMany annotation, or else explicitly specify an empty list of cascade types.

但是,请注意,当您对持久性上下文提交更改时,会保存对 all 持久性实体的更改.如果要修改Student实体而不将这些更改保存到数据库中,那么最好的选择可能是 detach 那些实体,或者制作它们的分离副本.

Note also, however, that changes to all persistent entities are saved when you commit changes to your persistence context. If you want to modify Student entities without having those changes be saved to the database, then your best alternative is probably to detach those entities, or else to make detached copies of them.

更新:

正如注释中已阐明的那样,基本问题是,当应用程序没有权限更新Student的基表但具有足够的权限时,如何修改SchoolStudent实体之间的关系在表示关系的联接表上.您不能自动结合持久保存对School的更改来执行此操作,因为School不是(也不能是)该关系的拥有方.

As has been clarified in comments, the essential problem is how to modify the relationship between School and Student entities when the application does not have permission to update the base table of Student, but does have sufficient permissions on the join table by which the relationship is represented. You cannot do this automatically in conjunction with persisting changes to Schools, because School is not -- and cannot be -- the owning side of the relationship.

澄清一下:当您将Student实体移动到不同的School时,JPA试图保存它们,因为出于其目的,Student与他的特定School之间的关联是状态的一部分. Student.如果Student实体附加到持久性上下文并且是脏的(例如,因为它已分配给其他School),则在提交对PC的更改时将对其进行更新.这与级联或School的状态无关,除了可以通过将Student的状态间接移动到不同的Schoolstudents列表中来修改它们.

To clarify: JPA is attempting to save your Student entities when you move them to different Schools because for its purposes, the association between a Student and his particular School is part of the state of the Student. If the Student entity is attached to the persistence context and is dirty (e.g. because it was assigned to a different School), then it will be updated when changes to the PC are committed. This has nothing in particular to do with cascading or with the state of the School, except that you modify the states of your Students indirectly by moving them to different Schools' students lists.

由于使用的是联接表,因此可以修改对象模型以将每个学生/学校协会独立地表示为一个实体.如果这些协会具有自己的属性(例如注册日期),那将是有道理的,但否则我不建议这样做.

Since you are using a join table, you could modify your object model to represent each student / school association as an entity in its own right. That would make sense if those associations had attributes of their own, such as enrollment dates, but otherwise I wouldn't recommend it.

另一种方法是编写本机查询(通过JPA);您会在网上找到很多有关该信息的信息,例如 https://blogs.oracle. com/JPQL01/entry/native_query_in_java_persistence .但是,这确实带来了一些问题.特别是,它会使EntityManager的缓存无效,如果不加以处理,可能会导致严重的问题.对于您来说可能很重要的一点是,它会产生实体更改而不会触发如果正常执行更新会触发的实体生命周期方法.

The alternative is to write native queries (via JPA); you'll find lots of information about that around the net, such as https://blogs.oracle.com/JPQL01/entry/native_query_in_java_persistence. This does introduce some problems, however. In particular, it invalidates the EntityManager's cache, which can produce serious problems if not dealt with. It may also be significant to you that it produces entity changes without triggering the entity lifecycle methods that would fire if you performed the update normally.

关于缓存,解决方案是分离受影响的StudentSchool(旧的和新的)实体.您可以使用EntityManager.detach()有选择地执行此操作,或者使用EntityManager.clear()进行整批操作.之后,您将需要重新查询或合并要继续使用的实体,这可能会引起一些混乱的问题,具体取决于使用它们的方式以及其他代码对它们的假设.

With respect to the cache, the solution is to detach the affected Student and School (both old and new) entities. You can do that selectively with EntityManager.detach(), or en masse with EntityManager.clear(). Afterward, you'll need to re-query or merge the entities you want to continue using, and that could make for some messy problems, depending on how pervasively they are used and on what assumptions other code makes about them.

关于生命周期方法,如果您需要确保它们触发,那么您可以选择自己调用它们.

As for the lifecycle methods, if you need to ensure they fire, then you have the alternative of invoking them yourself.

本文提供了一些内容有关您可能需要做什么的更多详细信息.

This article provides a few more details on what you might need to do.

这篇关于如何防止使用JPA保存子对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆