我已经搜索过,但似乎找不到答案。
我有两个表:
select ts_id, tsjoin_id, workdate from TimeSheets
select e_id, lastname from Employees
我也有一个联接表:
TSJoin
tsjoin_id, employee_id
TimeSheet只有一名员工。因此,对于任何给定的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()
但这很丑陋。 最佳答案
默认情况下,假定一个连接表包含两个已连接实体的ID。
在您的情况下,它不是:TimeSheet实体的ID映射到ts_id
列,但是您希望联接表具有一个列,该列是tsjoin_id
列的外键而不是ts_id
。
所以您需要告诉Hibernate。它无法猜测。而javadoc of JoinColumn说:
referencedColumnName
(可选)此外键列引用的列的名称。 [...]
缺省值(仅在使用单个连接列的情况下适用):与引用表的主键列同名。
所以你所需要的就是
@JoinTable(
name = "TSJoin",
joinColumns = {
@JoinColumn(name = "tsjoin_id", nullable = false, referencedColumnName = "tsjoin_id")
},
inverseJoinColumns = {
@JoinColumn(name = "e_id", nullable = false)
}
)
请注意,每个时间表只有一名员工不足以使您的关联成为OneToOne。要成为OneToOne,每个员工也应该有一个时间表。如果一个员工实际上有几个时间表,则该关联是ManyToOne,而不是OneToOne。