JPA @ManyToMany 与 JoinTable 重复输入问题
JPA @ManyToMany with JoinTable Duplicate entry issue
我在 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 ....
}
我在 class Address
中更改了 this post 之后的注释,它已解决。我使用了 mappedBy
属性:
@ManyToMany(mappedBy = "addresses", fetch = FetchType.EAGER)
private Set<AddressAliasGroup> groups;
我在 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 ....
}
我在 class Address
中更改了 this post 之后的注释,它已解决。我使用了 mappedBy
属性:
@ManyToMany(mappedBy = "addresses", fetch = FetchType.EAGER)
private Set<AddressAliasGroup> groups;