【问题标题】:JPA @ManyToMany with JoinTable Duplicate entry issueJPA @ManyToMany 与 JoinTable 重复条目问题
【发布时间】:2018-09-23 18:02:45
【问题描述】:

我在 Address 和 Group 之间有一个双向 ManyToMany 关系。 我的数据库中保留了以下内容:

  • 3 个地址:addr1、addr2、addr3
  • 1 个名为 group1 的组

当 group1 持有 addr1 时,意味着 Join-Table groups_addresses 持有一个条目,其 id 为 addr1,id 为 group1。

我也在尝试将 addr2 添加到 group1:

AddressGroup group1DataObj = groupsRepository.findById(group1Id);
Address addr2DataObj = addressesRepository.findById(addr2Id);
addr2DataObj.addGroup(group1DataObj);
groupsRepository.save(group1DataObj);

但由于某种原因,我收到了ConstraintViolationException:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '2c355601-02c9-459a-83f4-27720bc5d61f-01b08cbf-bfeb-4c71-969e-135' for key 'PRIMARY'

一开始我错过了CascadeType.PERSIST,在将它添加到双方之后仍然得到相同的异常。 我使用 hibernate 作为 JPA 实现,下面是我的实体,我哪里出错了?

@Entity
@Table(name = "addresses")
public class Address implements Serializable {

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "com.sample.app.UseExistingOrGenerateGenerator")
    private String id;

    @Column(name = "name", nullable = false)
    private String name;

    @ManyToMany(fetch = FetchType.LAZY,
            cascade =
                    {
                            CascadeType.PERSIST,
                            CascadeType.DETACH,
                            CascadeType.REFRESH
                    },
            targetEntity = AddressGroup.class)
    @JoinTable(name = "groups_addresses",
            joinColumns = @JoinColumn(name = "address_id",
                    nullable = false,
                    updatable = false),
            inverseJoinColumns = @JoinColumn(name = "group_id",
                    nullable = false,
                    updatable = false),
            foreignKey = @ForeignKey(ConstraintMode.CONSTRAINT),
            inverseForeignKey = @ForeignKey(ConstraintMode.CONSTRAINT))
    private Set<AddressGroup> groups;


    public void addGroup(AddressGroup group) {
        //avoid circular calls
        if (!groups.contains(group)) {
            groups.add(group);
            //add method to Product : sets 'other side' of association
            group.addAddress(this);
        }
    }

    public void removeGroup(AddressGroup group) {
        //avoid circular calls
        if (groups.contains(group)) {
            groups.remove(group);

            //handle other side of association
            group.removeAddress(this);
        }
    }

    public Address() {
        groups = Sets.newHashSet();
    }


        // Getters & Setters ....
}

================================================ ===================

@Entity
@Table(name = "groups")
public class AddressGroup implements Serializable {

    @Id
    @Column(name = "id", unique = true, nullable = false)
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
    private String id;

    @Column(name = "name", nullable = false)
    private String name;

    @ManyToMany(fetch = FetchType.EAGER,
            cascade =
                    {
                            CascadeType.PERSIST,
                            CascadeType.DETACH,
                            CascadeType.REFRESH
                    },
            targetEntity = Address.class)
    @JoinTable(name = "groups_addresses",
            inverseJoinColumns = @JoinColumn(name = "address_id",
                    nullable = false,
                    updatable = false),
            joinColumns = @JoinColumn(name = "group_id",
                    nullable = false,
                    updatable = false),
            foreignKey = @ForeignKey(ConstraintMode.CONSTRAINT),
            inverseForeignKey = @ForeignKey(ConstraintMode.CONSTRAINT))
    private Set<Address> addresses;

    public void addAddress(Address address) {
        //avoid circular calls
        if (!addresses.contains(address)) {
            addresses.add(address);
            //add method to Product : sets 'other side' of association
            address.addGroup(this);
        }
    }

    public void removeAddress(Address address) {
        //avoid circular calls
        if (addresses.contains(address)) {
            addresses.remove(address);

            //handle other side of association
            address.removeGroup(this);
        }
    }

    public AddressGroup() {
        addresses = Sets.newHashSet();
    }


    // Getters & Setters ....

}

【问题讨论】:

  • 尝试使用addressesRepository.save(addr2DataObj);而不是保存组

标签: hibernate spring-data-jpa jpa-2.0


【解决方案1】:

我在this post 之后更改了Address 类中的注释,它得到了解决。我使用了mappedBy 属性:

@ManyToMany(mappedBy = "addresses", fetch = FetchType.EAGER)
private Set<AddressAliasGroup> groups;

【讨论】:

    猜你喜欢
    • 2012-06-03
    • 2018-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 2014-11-11
    相关资源
    最近更新 更多