我正在使用EclipseLink 2.5.1(和Hibernate 4.3.5最终版)。给定MySQL中的下表。
产品及其颜色之间存在多对多关系。
产品可以具有多种颜色,而颜色又可以与多种产品相关联。这些表在数据库中表示了这种关系。
prod_colour
表在其相关父表prod_id
和colour_id
中分别具有两个参考列product
和colour
。
很明显,实体类Product
具有颜色列表-java.util.List<Colour>
,其命名为colourList
。
实体类Colour
具有产品列表-java.util.List<Product>
,名称为productList
。
[Colour
实体中的关系:
public class Colour implements Serializable {
@JoinTable(name = "prod_colour", joinColumns = {
@JoinColumn(name = "colour_id", referencedColumnName = "prod_id")}, inverseJoinColumns = {
@JoinColumn(name = "prod_id", referencedColumnName = "colour_id")})
@ManyToMany(mappedBy = "colourList", fetch = FetchType.LAZY)
private List<Product> productList; //Getter and setter.
//---Utility methods---
//Add rows to the prod_colour table.
public void addToProduct(Product product) {
this.getProductList().add(product);
product.getColourList().add(this);
}
//Delete rows from the prod_colour table.
public void removeFromProduct(Product product) {
this.getProductList().remove(product);
product.getColourList().remove(this);
}
}
Product
实体中的关系:
public class Product implements Serializable {
@JoinTable(name = "prod_colour", joinColumns = {
@JoinColumn(name = "prod_id", referencedColumnName = "prod_id")}, inverseJoinColumns = {
@JoinColumn(name = "colour_id", referencedColumnName = "colour_id")})
@ManyToMany(fetch = FetchType.LAZY)
private List<Colour> colourList; //Getter and setter.
}
从关联的EJB中,插入操作如下执行。
@Override
@SuppressWarnings("unchecked")
public boolean insert(List<Colour> colours, Product product)
{
int i=0;
Long prodId=product.getProdId();
for(Colour colour:colours)
{
Product p = entityManager.getReference(Product.class, prodId);
colour.addToProduct(p);
if(++i%49==0)
{
entityManager.flush();
}
entityManager.merge(colour);
entityManager.merge(p);
}
return true;
}
一切正常。
[当尝试重复的行(与相同的Colour
实体关联的相同Product
实体]时,它们也被插入到我不希望发生的prod_colour
表中。
我是否需要执行一些额外的条件检查以避免重复插入,或者EclipseLink / Hibernate具有某种机制来防止重复插入?
这也让我感到惊讶。我一直在想,它使连接表中的引用列作为复合主键,但事实并非如此。如果要具有唯一记录,请尝试使用Set
而不是List
或使用复合主键(color_id,product_id)创建自己的ManyToMany关系表。我没有更好的主意。
您可以在JoinTable上指定一个uniqueConstraints,如下所示:
@JoinTable(name = "prod_colour", joinColumns = {
@JoinColumn(name = "prod_id", referencedColumnName = "prod_id")}, inverseJoinColumns = {
@JoinColumn(name = "colour_id", referencedColumnName = "colour_id")}, uniqueConstraints = @UniqueConstraint(columnNames = {
"colour_id", "prod_id" }))
这将防止直接对表并通过您的应用程序代码执行直接sql时条目的重复。