Hibernate中的三元(和n-ary)关系

时间:2010-04-10 12:24:37

标签: java hibernate database-design orm jpa

问1)我们如何使用Hibernate建模三元关系?例如,我们如何使用Hibernate(或JPA)模拟呈现here的三元关系?

注意:我知道JPA 2添加了一些使用地图构建三元关系的结构。但是,这个问题假定JPA 1或Hibernate 3.3.x并且我不喜欢使用地图对此进行建模。

ER Model http://db.grussell.org/co22001%20notes_files/image043.gif


ER Model with ternary relationships replaced http://db.grussell.org/co22001%20notes_files/image045.gif

理想情况下,我更喜欢我的模型:

class SaleAssistant {
Long id;
//...
}

class Customer {
Long id;
//...
}

class Product {
Long id;
//...
}

class Sale {
SalesAssistant soldBy;
Customer buyer;
Product product;
//...
}

Q 1.1)

我们如何对这种变化进行建模,其中每个Sale项目可能包含许多产品?

class SaleAssistant {
Long id;
//...
}

class Customer {
Long id;
//...
}

class Product {
Long id;
//...
}

class Sale {
SalesAssistant soldBy;
Customer buyer;
Set<Product> products;
//...
}

问2)一般来说,我们如何用Hibernate建模n-ary,n&gt; = 3关系?

提前致谢。

2 个答案:

答案 0 :(得分:11)

  

Q1。我们如何使用Hibernate建模三元关系?例如,我们如何使用Hibernate(或JPA)对这里呈现的三元关系进行建模? (...)

我会改造与中间实体类的关联(这是Hibernate的推荐方法)。适用于您的示例:

@Entity
public class Sale {
    @Embeddable
    public static class Pk implements Serializable {
        @Column(nullable = false, updatable = false)
        private Long soldById;

        @Column(nullable = false, updatable = false)
        private Long buyerId;

        @Column(nullable = false, updatable = false)
        private Long productId;

        public Pk() {}

        public Pk(Long soldById, Long buyerId, Long productId) { ... }

        // getters, setters, equals, hashCode
    }

    @EmbeddedId
    private Pk pk;

    @ManyToOne
    @JoinColumn(name = "SOLDBYID", insertable = false, updatable = false)
    private SaleAssistant soldBy;
    @ManyToOne
    @JoinColumn(name = "BUYERID", insertable = false, updatable = false)
    private Customer buyer;
    @ManyToOne
    @JoinColumn(name = "PRODUCTID", insertable = false, updatable = false)
    private Product product;

    // getters, setters, equals, hashCode
}
  

Q1.1。我们如何对这种变化进行建模,其中每个Sale项目可能包含许多产品?

我不会在这里使用复合主键,并为Sale实体引入PK。

  

Q2。一般来说,我们如何模拟n-ary,n&gt; = 3与Hibernate的关系?

我认为我对Q1的回答。涵盖了这个。如果没有,请澄清。


更新:回复OP的评论

  

(...)pk的字段未填充,因此我无法在数据库中保存Sale项目。我应该在Sale类中使用这样的setter吗? public void setBuyer(Customer cust){this.buyer = cust; this.pk.buyerId = cust.getId(); }

您需要创建一个新的Pk(我从原始答案中删除了构造函数以获得简洁性)并将其设置在Sale项上。我会做这样的事情:

Sale sale = new Sale();
Pk pk = new Pk(saleAssistant.getId(), customer.getId(), product.getId());
sale.setPk(pk);
sale.setSoldBy(saleAssistant);
sale.setBuyer(customer);
sale.setProduct(product);
...

然后坚持sale

  

另外,在JoinColumn注释中,哪个列是“name”字段引用?目标关系'pks或销售表自己的列名?

对于复合Pk属性的列(即销售表自己的列名),我们希望它们获得PK 和FK 约束。

答案 1 :(得分:0)

您是否正在为Customer,Product和SalesAssistant使用数据库生成的主键?这可能会导致问题,因为看起来您正在尝试使用实际的数据库身份,而不是让Hibernate在实际持久性期间解析对象引用。

上面的嵌入式PK对我个人来说很奇怪,但我没有机会尝试一下。看起来这些列是重叠的,互相破坏。

我认为只需拥有ManyToOne引用即可。

此外,打开SQL语句调试并查看发送给数据库的内容。