我在@ManyToMany关系中有2个实体:Networks和SiteCodes。
网络:
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "network_id")
public int getNetworkId() {
return this.networkId;
}
public void setNetworkId(int networkId) {
this.networkId = networkId;
}
@ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
@JoinTable(name = "site_code_map",
joinColumns = { @JoinColumn(name = "network_id") },
inverseJoinColumns = { @JoinColumn(name = "site_code_id") })
public Set<SiteCodes> getSiteCodes() {
return siteCodes;
}
public void setSiteCodes(Set<SiteCodes> siteCodes) {
this.siteCodes = siteCodes;
}
SiteCodes:
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name = "site_code_id")
public Integer getSiteCodeId() {
return this.siteCodeId;
}
public void setSiteCodeId(Integer siteCodeId) {
this.siteCodeId = siteCodeId;
}
@Column(name = "site_code", nullable = false)
@NotNull
@NaturalId
public String getSiteCode() {
return siteCode;
}
@ManyToMany(mappedBy="siteCodes",cascade = CascadeType.MERGE)
public Set<Networks> getNetworks() {
return networks;
}
public void setNetworks(Set<Networks> networks) {
this.networks = networks;
}
我的主要课程:
session.beginTransaction();
Networks nw1 = new Networks(345);
Networks nw2 = new Networks(789);
SiteCodes sc1 = new SiteCodes("0123");
SiteCodes sc2 = new SiteCodes("0001");
SiteCodes sc3 = new SiteCodes("0ABC");
// The real code would do this inside a loop, ie create a new network, figure out
// the site codes and assign them.
session.beginTransaction();
Networks nw1 = new Networks(345);
nw1.getSiteCodes().add(sc1);
nw1.getSiteCodes().add(sc2);
session.merge(nw1);
session.getTransaction().commit();
session.beginTransaction();
Networks nw2 = new Networks(789);
nw2.getSiteCodes().add(sc3);
nw2.getSiteCodes().add(sc2);
session.merge(nw2);
session.getTransaction().commit();
结果是重复输入错误:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '0001' for key 'site_code'
我玩过CascadeType以及我能想到的任何其他东西。我已经搜索了关于这个主题的现有问题,但还没有找到解决这个问题的方法。偶尔在我尝试过的变体中,我收到了“对象引用未保存的瞬态实例”错误。
答案 0 :(得分:0)
非常基本! (希望这将有助于其他新手学到一些基本的东西)
问题是第二次使用站点代码时,它只是一个包含重复信息的SiteCode对象。 Hibernate尝试插入是作为新记录。
为使更新正确发生,SiteCode需要成为托管对象,即需要从数据库加载。
用这个替换第二个交易,问题就消失了:
session.beginTransaction();
SiteCodes sc4 = (SiteCodes) session.bySimpleNaturalId(SiteCodes.class).load(sc2.getSiteCode());
Networks nw2 = new Networks(789);
nw2.getSiteCodes().add(sc3);
nw2.getSiteCodes().add(sc4); // Same as sc2
session.merge(nw2);
session.getTransaction().commit();
感谢我的同事指出了这一点。