Hibernate / JPA注释中的多列连接

我有两个实体,我想通过多个列加入。 这些列由两个实体共享的@Embeddable对象共享。 在下面的示例中, Foo只能有一个BarBar可以有多个Foo (其中AnEmbeddableObjectBar的唯一键)。 这是一个例子:

 @Entity @Table(name = "foo") public class Foo { @Id @Column(name = "id") @GeneratedValue(generator = "seqGen") @SequenceGenerator(name = "seqGen", sequenceName = "FOO_ID_SEQ", allocationSize = 1) private Long id; @Embedded private AnEmbeddableObject anEmbeddableObject; @ManyToOne(targetEntity = Bar.class, fetch = FetchType.LAZY) @JoinColumns( { @JoinColumn(name = "column_1", referencedColumnName = "column_1"), @JoinColumn(name = "column_2", referencedColumnName = "column_2"), @JoinColumn(name = "column_3", referencedColumnName = "column_3"), @JoinColumn(name = "column_4", referencedColumnName = "column_4") }) private Bar bar; // ... rest of class } 

和Bar类:

 @Entity @Table(name = "bar") public class Bar { @Id @Column(name = "id") @GeneratedValue(generator = "seqGen") @SequenceGenerator(name = "seqGen", sequenceName = "BAR_ID_SEQ", allocationSize = 1) private Long id; @Embedded private AnEmbeddableObject anEmbeddableObject; // ... rest of class } 

最后是AnEmbeddedObject类:

 @Embeddable public class AnEmbeddedObject { @Column(name = "column_1") private Long column1; @Column(name = "column_2") private Long column2; @Column(name = "column_3") private Long column3; @Column(name = "column_4") private Long column4; // ... rest of class } 

显然,模式很难规范化,这是一个限制, AnEmbeddedObject的字段在每个表中重复。

我遇到的问题是,当我尝试启动Hibernate时收到此错误:

 org.hibernate.AnnotationException: referencedColumnNames(column_1, column_2, column_3, column_4) of Foo.bar referencing Bar not mapped to a single property 

我试过标记JoinColumns不可插入和可更新,但没有运气。 有没有办法用Hibernate / JPA注释表达这个?

这对我有用。 在我的情况下,2个表foo和boo必须基于3个不同的列加入。请注意在我的情况下,在boo中3个常用列不是主键

即,基于3个不同列的一对一映射

 @Entity @Table(name = "foo") public class foo implements Serializable { @Column(name="foocol1") private String foocol1; //add getter setter @Column(name="foocol2") private String foocol2; //add getter setter @Column(name="foocol3") private String foocol3; //add getter setter private Boo boo; private int id; @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "brsitem_id", updatable = false) public int getId() { return this.id; } public void setId(int id) { this.id = id; } @OneToOne @JoinColumns( { @JoinColumn(updatable=false,insertable=false, name="foocol1", referencedColumnName="boocol1"), @JoinColumn(updatable=false,insertable=false, name="foocol2", referencedColumnName="boocol2"), @JoinColumn(updatable=false,insertable=false, name="foocol3", referencedColumnName="boocol3") } ) public Boo getBoo() { return boo; } public void setBoo(Boo boo) { this.boo = boo; } } @Entity @Table(name = "boo") public class Boo implements Serializable { private int id; @Column(name="boocol1") private String boocol1; //add getter setter @Column(name="boocol2") private String boocol2; //add getter setter @Column(name="boocol3") private String boocol3; //add getter setter @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "item_id", updatable = false) public int getId() { return id; } public void setId(int id) { this.id = id; } } 

如果这不起作用我就没有​​想法了。 这样,您可以在两个表中获得4列(因为Bar拥有它们,而Foo使用它们来引用Bar )以及两个实体中生成的ID。 一组4列必须在Bar是唯一的,因此多对一关系不会成为多对多关系。

 @Embeddable public class AnEmbeddedObject { @Column(name = "column_1") private Long column1; @Column(name = "column_2") private Long column2; @Column(name = "column_3") private Long column3; @Column(name = "column_4") private Long column4; } @Entity public class Foo { @Id @Column(name = "id") @GeneratedValue(generator = "seqGen") @SequenceGenerator(name = "seqGen", sequenceName = "FOO_ID_SEQ", allocationSize = 1) private Long id; @ManyToOne(fetch = FetchType.LAZY) @JoinColumns({ @JoinColumn(name = "column_1", referencedColumnName = "column_1"), @JoinColumn(name = "column_2", referencedColumnName = "column_2"), @JoinColumn(name = "column_3", referencedColumnName = "column_3"), @JoinColumn(name = "column_4", referencedColumnName = "column_4") }) private Bar bar; } @Entity @Table(uniqueConstraints = @UniqueConstraint(columnNames = { "column_1", "column_2", "column_3", "column_4" })) public class Bar { @Id @Column(name = "id") @GeneratedValue(generator = "seqGen") @SequenceGenerator(name = "seqGen", sequenceName = "BAR_ID_SEQ", allocationSize = 1) private Long id; @Embedded private AnEmbeddedObject anEmbeddedObject; } 

Hibernate不会让你轻松做你想做的事情。 从Hibernate文档 :

请注意,将referencedColumnName用于非主键列时,关联的类必须是Serializable。 另请注意,非主键列的referencedColumnName必须映射到具有单个列的属性(其他情况可能不起作用)。 (重点补充)

因此,如果你不愿意将AnEmbeddableObject作为Bar的Identifier,那么Hibernate就不会AnEmbeddableObject ,自动为你找回Bar。 当然,您仍然可以使用HQL编写在AnEmbeddableObject上加入的查询,但如果您坚持使用Bar的多列非主键,则会丢失自动获取和生命周期维护。