简体   繁体   English

JPA更新多对多删除记录

[英]JPA update many-to-many deleting records

I have a @ManyToMany relationship between two entities. 我在两个实体之间有一个@ManyToMany关系。 When I perform an update on the owning side, it appears that JPA deletes all the linked records from my database and re-inserts them. 当我在拥有方执行更新时,似乎JPA将从我的数据库中删除所有链接的记录,然后重新插入它们。 For me this is a problem because I have a MySQL trigger that fires before a record is deleted. 对我来说,这是一个问题,因为我有一个MySQL触发器,该触发器在删除记录之前会触发。 Any ideas on how to get around this problem? 关于如何解决此问题的任何想法?

@Entity
public class User {

    @Id
    @Column(name="username")
    private String username;

    ...

    @ManyToMany
    @JoinTable(name="groups", joinColumns=
        @JoinColumn(name="username", referencedColumnName="username"),
            inverseJoinColumns=@JoinColumn(name="groupname",
                    referencedColumnName="type_id"))
    private List<UserType> types;

    ...

}

@Entity
public class UserType {

    @Id
    @Column(name="type_id")
    private String id;

    @ManyToMany(mappedBy="types")
    private List<User> users;

    ...
} 

Use Set instead of List solved the problem. 使用Set代替List解决了该问题。 But I have no idea why it works. 但是我不知道为什么会起作用。

Another solution provided by Hibernate is to split the @ManyToMany association into two bidirectional @OneTo@Many relationships. Hibernate提供的另一个解决方案是将@ManyToMany关联分为两个双向@OneTo@Many关系。 See Hibernate 5.2 documentation for example. 例如,请参见Hibernate 5.2文档

If a bidirectional @OneToMany association performs better when removing or changing the order of child elements, the @ManyToMany relationship cannot benefit from such an optimization because the foreign key side is not in control. 如果在删除或更改子元素的顺序时双向@OneToMany关联的性能更好,则@ManyToMany关系将无法从这种优化中受益,因为外键端不受控制。 To overcome this limitation, the link table must be directly exposed and the @ManyToMany association split into two bidirectional @OneToMany relationships. 为了克服此限制,必须直接公开链接表,并将@ManyToMany关联拆分为两个双向@OneToMany关系。

Its probably related to this question . 它可能与此问题有关 You have to ensure you have an appropriately defined hashCode an equals method in your mapped object so that Eclipselink can determine equality and thus determine that the existing objects map to existing objects in the DB. 您必须确保在映射对象中具有适当定义的hashCode equals方法,以便Eclipselink可以确定相等性,从而确定现有对象映射到DB中的现有对象。 Otherwise it has no choice but to recreate the child objects every time. 否则,它别无选择,只能每次重新创建子对象。

Alternatively, I've read that this kind of join can only support efficient adding and removing of list items if you use an index column, but that's going to be EclipseLink specific, since the JPA annotations don't seem to support such a thing. 另外,我已经读到,如果使用索引列,这种连接只能支持有效地添加和删除列表项,但这将是EclipseLink特定的,因为JPA批注似乎不支持这种东西。 I know there is an equivalent Hibernate annotation, but I don't know what it would be in Eclipselink, if such a thing exists. 我知道有一个等效的Hibernate批注,但是我不知道在Eclipselink中如果存在这样的东西。

Try this one: 试试这个:

1) change declaration to: 1)将声明更改为:

private List<UserType> types = new Vector<UserType>();

2) never call 2)永不致电

user.setTypes(newTypesList)

3) only call 3)只打电话

user.getTypes().add(...);
user.getTypes().remove(...);

看来我的问题是我没有合并实体。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM