当有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个请求才能拥有完整的注册表。是否有任何改善方法?
由于
答案 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
关系。