JPA / Hibernate:当连接表具有自己的主键时映射多对多关系

时间:2014-09-02 12:27:42

标签: java sql oracle hibernate jpa

我有三个结构简单的表:

pub [id, name]
days [id, name]
pub_days [id, pub_id, days_id]

出于某种不合理的原因,有人认为 pub_days 表的复合身份(即pub_id + days_id)是不够的,并添加了自己的主键。我现在无法改变它,其他更大的系统依赖于此。 #sigh

我正在尝试使用标准的@ManyToMany JPA注释将其映射到Hibernate(我省略了getter,setters,@ Entitiy注释和其他杂乱):

class Pub {

    @ManyToMany(cascade = {CascadeType.ALL})
    @JoinTable(name = "pub_days",
            joinColumns = {@JoinColumn(name = "pub_id")},
            inverseJoinColumns = {@JoinColumn(name = "days_id")})
    @OrderBy("id")
    private List<Day> pubOpeningDays;
}

class Day {
    @Id Long id;
    String name.
}

当我执行以下代码时:

Day day = repository.find(Day.class, id);
pub.getPubOpeningDays().add(day);
repository.persist(pub);

我收到此错误:

ERROR: ORA-01400: cannot insert NULL into ("PUB"."pub_days"."id")

可悲的是,这很有道理,因为我还没有将ID映射到任何地方。问题是,我甚至不想。我想要生成它,但不确定如何使用@ManyToMany映射克服此问题。有什么想法吗?

2 个答案:

答案 0 :(得分:0)

我只看到两个选择,要么你将映射更改为PubDay列表,因为samwise-gamgee在评论中告诉你,或者你在表pub_days上的insert上添加一个触发器,如果​​它为null则为列id设置一个值(它可能是使用序列)。但这种方法取决于数据库支持的功能。

答案 1 :(得分:0)

你可以做的就像我在评论中提到的那样,你可以创建一个单独的实体CD,它将依次连接两个A和B类,现在A和B之间的关系将是多对多,因此A(很多)许多)CD(多对多)B。现在根据您的要求,无论何时需要获取A或B的实例,您可以做的只是使用适当的参数在DB中触发查询,即id或id为b这将帮助您获得所需的结果。