JPA从多个关系中获取值

时间:2015-07-03 17:00:15

标签: java hibernate jpa

我在JPA中嵌入多对一关系中的单个值时遇到问题。下面是我用来初始化测试模式以及测试实体的一些代码。

这个想法是有一个表EMPLOYEE,它引用了表RANK。表RANK又包含RANK的名称。每个员工都参考其排名。

当我尝试运行我的代码时,我得到以下异常:

Caused by: org.hibernate.AnnotationException: SecondaryTable JoinColumn cannot reference a non primary key
    at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:623)
    at org.hibernate.cfg.annotations.EntityBinder.bindJoinToPersistentClass(EntityBinder.java:764)
    at org.hibernate.cfg.annotations.EntityBinder.createPrimaryColumnsToSecondaryTable(EntityBinder.java:756)
    at org.hibernate.cfg.annotations.EntityBinder.finalSecondaryTableBinding(EntityBinder.java:684)
    at org.hibernate.cfg.SecondaryTableSecondPass.doSecondPass(SecondaryTableSecondPass.java:29)

这是一个数据库架构

CREATE TABLE RANK (
    ID INT NOT NULL, 
    NAME VARCHAR
);
ALTER TABLE RANK ADD PRIMARY KEY (ID);
INSERT INTO RANK (ID, NAME) VALUES (1, 'WORKER')

CREATE TABLE EMPLOYEE(
    ID INT NOT NULL, 
    NAME VARCHAR,
    RANK_ID INT NOT NULL
);
ALTER TABLE EMPLOYEE ADD PRIMARY KEY (ID);
INSERT INTO EMPLOYEE (ID, NAME, RANK_ID) VALUES (1, 'Bobby', 1);

最后,唯一的实体:

@Entity
@Table(name = "EMPLOYEE")
@SecondaryTable(name = "RANK", pkJoinColumns=@PrimaryKeyJoinColumn(name="ID", referencedColumnName = "RANK_ID"))
public class Employee {

    @Id
    @Column(name = "id")
    @GeneratedValue(generator = "increment")
    @GenericGenerator(name = "increment", strategy = "increment")
    private int id;

    @Column(name = "NAME")
    private String name;

    @Column(name = "RANK_ID")
    private int rankId;

    @Column(name = "name", table = "RANK")
    private String rank;

    public Employee() {

    }
}

我很感激有关如何解决此案的任何提示。看起来很常见,因为JPA无法做到这一点。

2 个答案:

答案 0 :(得分:1)

使用辅助表注释时引用Employee ID并删除rank_id。您是说通过使用该注释将数据分布在多个表中,因此两者的主键基本相同。实际上,由于两个PK都具有相同的标识符,因此甚至不需要定义@PrimaryKeyJoinColumn

请参阅此处:https://docs.jboss.org/hibernate/jpa/2.1/api/javax/persistence/SecondaryTable.html

另一方面,如果您只想要多对多关系,则可以使用@ManyToOne中的@JoinColumn注释和rank_id

答案 1 :(得分:0)

如果您阅读this section of the Java Persistence Wikibook,您会看到JPA规范不涵盖您想要的内容,因此基础提供商可能不支持:

  

JPA规范没有直接涵盖这一点,所以如果你有这个场景,首先要考虑的是,如果你有灵活性,就是改变你的数据模型,使其保持在规范的范围内。

@SecondaryTable主要用于将一对一表格链接到一个实体。

'标准'实现所需内容的方法是为Rank创建单独的实体,并在Employee中获取EAGER。然后,您可以在Employee中使用名为getRankName()的方法返回this.rank.getName()。因此,您的Employee类看起来像这样:

@Entity
@Table(name = "EMPLOYEE")
public class Employee {

    @Id
    @Column(name = "id")
    @GeneratedValue(generator = "increment")
    @GenericGenerator(name = "increment", strategy = "increment")
    private int id;

    @Column(name = "NAME")
    private String name;

    @ManyToOne(fetch = FetchType.EAGER, optional = false)
    @JoinColumn(name = "RANK_ID", referencedColumnName = "ID")
    private Rank rank;

    public Employee() {

    }

    public String getRankName() {
        if (this.rank == null) {
            return null;
        }
        return this.rank.getName();
    }
}