0

我在 @ManyToMany 关系中有 2 个实体:网络和站点代码。

网络:

@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;
}

站点代码:

@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 和我能想到的任何其他东西。我已经搜索了有关此主题的现有问题,但尚未找到解决此问题的方法。有时,在我尝试过的变体中,我收到了“对象引用未保存的瞬态实例”错误。

4

1 回答 1

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();

感谢我的同事指出了这一点。

于 2013-01-25T15:35:56.020 回答