JPA:翻译表的问题

时间:2018-02-20 18:50:35

标签: java jpa spring-data spring-data-jpa

当有2个表时,我遇到了JPA(使用Spring和Hibernate)的问题,其中一个表示另一个表的转换。我的目的是在一个查询中检索注册表的全部信息,但我无法得到它:我需要首先检索TABLE_A的注册表,然后从TABLE_A_TRANSLATION检索关联的注册表,然后合并它们&# 34;手工"。这是一个例子:

CREATE TABLE TABLE_A (
    ID INTEGER NOT NULL,
    CONSTRAINT PK_A PRIMARY KEY (ID)
);

CREATE TABLE TABLE_A_TRANSLATION (
    ID INTEGER NOT NULL,
    LANG VARCHAR2(2) NOT NULL,
    DESCRIPTION VARCHAR2(100) NOT NULL,
    CONSTRAINT PK_A_TRA PRIMARY KEY (ID, LANG),
    CONSTRAINT FK_A_TRA_A FOREIGN KEY (ID) REFERENCES TABLE_A (ID)
);

关联的JPA Java代码如下:

@Entity
@Table(name = "table_a")
public class TableA {
    @Id
    @Column(name = "id", nullable = false, unique = true)
    private Integer id;

    @Column(name = "code", nullable = false, unique = false, length = 10)
    private String code;

    private String lang;
    private String description;

    // getters and setters
}

@Entity
@Table(name = "table_a")
public class TableATranslation {
    @Id
    @Column(name = "id", nullable = false, unique = true)
    private Integer id;

    @Id
    @Column(name = "lang", nullable = false, unique = true, length = 2)
    private String lang;

    @Column(name = "description", nullable = false, unique = false, length = 100)
    private String description;

    // getters and setters
}

当我想要检索TABLE_A元素时,我会执行以下操作(请避免谈论语法错误,我知道' find'方法和实体类没有很好地描述,但它& #39; s只是一个例子):

public TableA getOne(Integer id, String lang) {
    TableA tableA = entityManager.find(TableA.class, id);
    TableATranslation tableATrans = entityManager.find(TableATranslation.class, ...);

    tableA.lang = tableATrans.lang;
    tableA.description = tableATrans.description;
}

总结一下,我需要对数据库执行2个请求才能拥有完整的注册表。是否有任何改善方法?

由于

1 个答案:

答案 0 :(得分:0)

如果我理解正确,您可能会为每个TABLE_A实体提供多个翻译。在这种情况下,最好选择我们使用@OneTwoMany关系:一个TABLE_A可以引用许多TABLE_A_TRANSLATION个实体。

为实现此目的,您需要稍微修改一下TABLE_A_TRANSLATION表:建议您添加SOURCE_ID字段以引用TABLE_A主键。

CREATE TABLE TABLE_A_TRANSLATION (
    ID INTEGER NOT NULL,
    SOURCE_ID INTEGER NOT NULL,
    LANG VARCHAR2(2) NOT NULL,
    DESCRIPTION VARCHAR2(100) NOT NULL,
    CONSTRAINT PK_A_TRA PRIMARY KEY (ID),
    CONSTRAINT FK_A_TRA_A FOREIGN KEY (SOURCE_ID) REFERENCES TABLE_A (ID)
);

然后在你的实体中:

TableATranslation

@Entity
@Table(name = "table_a_translation") // <- notice that you had a typo here
public class TableATranslation {     //    ("table_a" instead of "table_a_translation")
    @Id
    @Column(name = "id", nullable = false, unique = true)
    private Integer id;

    @Column(name = "lang", nullable = false, unique = true, length = 2)
    private String lang;

    @Column(name = "description", nullable = false, unique = false, length = 100)
    private String description;

    @ManyToOne
    private TableA source; // so you can reference the source of this translation

    // getters and setters
}

TableA

@Entity
@Table(name = "table_a")
public class TableA {
    @Id
    @Column(name = "id", nullable = false, unique = true)
    private Integer id;

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

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

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

    @OneToMany(mappedBy = "source")
    private List<TableATranslation> translations;

    // getters and setters
}

然后,如果您获取TableA实体,它将包含所有相关翻译的列表:

TableA t = entityManager.find(TableA.class, 1);
List<TableATranslation> translations = t.getTranslations();

如果您希望hibernate使用一个SQL查询获取所有theese实体,您可以指定FetchMode

@OneToMany(mappedBy = "source")
@Fetch(FetchMode.JOIN)
private List<TableATranslation> translations;

生成的SQL将如下所示:

select ...  from table_a tablea0_ 
left outer join table_a_translation translatio1_ 
on tablea0_.id=translatio1_.source_id where tablea0_.id=?

如果每个TableA实体只有一个翻译,则可以使用类似的@OneToOne关系。