我已经搜索过,但似乎无法找到答案。
我有两张桌子:
select ts_id, tsjoin_id, workdate from TimeSheets
select e_id, lastname from Employees
我还有一个联接表:
TSJoin
tsjoin_id, employee_id
TimeSheet只有一个Employee。因此,对于任何给定的TimeSheet实体,我希望能够:
TimeSheet ts = tsService.getTimeSheet(123);
String lastName = ts.getEmployee().getLastName();
在SQL中,获取TimeSheet的员工:
select e.lastname from TimeSheets t
join TSJoin x on (x.tsjoin_id = t.tsjoin_id)
join Employees e on (e.e_id = x.employee_id)
where t.ts_id = 123
在我的Hibernate
映射中,我有:
@OneToOne
@JoinTable(
name = "TSJoin",
joinColumns = {
@JoinColumn(name = "tsjoin_id", nullable = false)
},
inverseJoinColumns = {
@JoinColumn(name = "e_id", nullable = false)
}
)
然而,它生成的SQL是:
select * from TimeSheet t
left outer join TSJoin x on (t.ts_id = x.tsjoin_id)
为Employee返回null。
它使用TimeSheet的主键并尝试匹配连接表的主键。
我做错了什么?
修改
我还想声明我此时只设置了一个方向。哪个是TimeSheet -> Employee
(OneToOne),而Employee
未映射到TimeSheet
尚未。不确定这是否有所不同,但我想提一下。
编辑2
我还想声明我认为错误可能是因为我的连接表不包含对TimeSheet
的引用。 Hibernate假设连接表将包含所涉及的每个实体的主键(遗留数据库)。我可以创建TimeSheet
- >的映射。 JoinTable
- > Employee
并将其设置为:ts.getJoin().getEmployee()
,但这非常难看。
答案 0 :(得分:1)
默认情况下,假定连接表包含两个连接实体的ID。
在您的情况下,它没有:TimeSheet实体的ID映射到ts_id
列,但您希望连接表具有一个列,该列是{{的外键1}}列而不是tsjoin_id
。
所以你需要告诉Hibernate。它无法猜测。 javadoc of JoinColumn说:
referencedColumnName
(可选)此外键列引用的列的名称。 [...]
默认值(仅在使用单个连接列时适用):与引用表的主键列相同的名称。
所以你需要的只是
ts_id
请注意,每个时间表只有一名员工并不足以使您的关联成为OneToOne。要成为OneToOne,每位员工也应该有一张时间表。事实上,如果一个emplyee有几个时间表,那么关联就是ManyToOne,而不是OneToOne。
答案 1 :(得分:1)
我几乎100%确定这个问题是因为当前的JPA规范不允许JoinTable中的非主键列。我们的旧数据库连接到非主键的列。