使用主键连接列的一对一映射
one to one mapping using primary key join column
我使用主键连接列 (employee_id) 类 映射(双向)员工和员工详细信息
@Entity
@Table(name="employee")
public class Employee {
@Id
@GeneratedValue
@Column(name="employee_id")
private Long employeeId;
@Column(name="firstname")
private String firstname;
@Column(name="lastname")
private String lastname;
@Column(name="birth_date")
@Temporal(value = TemporalType.DATE )
private Date birthDate;
@Column(name="cell_phone")
private String cellphone;
@OneToOne(mappedBy="empl", cascade=CascadeType.ALL)
private EmployeeDetail employeeDetail;
...
}
@Table(name="employeedetail")
public class EmployeeDetail {
@Id
@Column(name="employee_id", unique=true, nullable=false)
@GeneratedValue(generator="gen")
@GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="empl"))
private Long employeeId;
@Column(name="street")
private String street;
@Column(name="city")
private String city;
@Column(name="state")
private String state;
@Column(name="country")
private String country;
@OneToOne
@PrimaryKeyJoinColumn
private Employee empl;
....................
}
有人可以解释为什么在执行以下查询时 session.createQuery("from Employee").list();
A) 像 2)、3) 和 4) 这样的连接查询被执行以从 employeedetail 获取数据?
为什么不使用 employee 对象中的 employeeid 值直接从 employeedetail table 中获取而不进行连接?
1) Hibernate: select employee0_.employee_id as employee1_0_, employee0_.birth_date as birth_da2_0_, employee0_.cell_phone as cell_pho3_0_, employee0_.firstname as firstnam4_0_, employee0_.lastname as lastname5_0_ from employee employee0_
2) Hibernate: select employeede0_.employee_id as employee1_1_0_, employeede0_.city as city2_1_0_, employeede0_.country as country3_1_0_, employeede0_.state as state4_1_0_, employeede0_.street as street5_1_0_, employee1_.employee_id as employee1_0_1_, employee1_.birth_date as birth_da2_0_1_, employee1_.cell_phone as cell_pho3_0_1_, employee1_.firstname as firstnam4_0_1_, employee1_.lastname as lastname5_0_1_ from employeedetail employeede0_ left outer join employee employee1_ on employeede0_.employee_id=employee1_.employee_id where employeede0_.employee_id=?
3) Hibernate: select employeede0_.employee_id as employee1_1_0_, employeede0_.city as city2_1_0_, employeede0_.country as country3_1_0_, employeede0_.state as state4_1_0_, employeede0_.street as street5_1_0_, employee1_.employee_id as employee1_0_1_, employee1_.birth_date as birth_da2_0_1_, employee1_.cell_phone as cell_pho3_0_1_, employee1_.firstname as firstnam4_0_1_, employee1_.lastname as lastname5_0_1_ from employeedetail employeede0_ left outer join employee employee1_ on employeede0_.employee_id=employee1_.employee_id where employeede0_.employee_id=?
4) Hibernate: select employeede0_.employee_id as employee1_1_0_, employeede0_.city as city2_1_0_, employeede0_.country as country3_1_0_, employeede0_.state as state4_1_0_, employeede0_.street as street5_1_0_, employee1_.employee_id as employee1_0_1_, employee1_.birth_date as birth_da2_0_1_, employee1_.cell_phone as cell_pho3_0_1_, employee1_.firstname as firstnam4_0_1_, employee1_.lastname as lastname5_0_1_ from employeedetail employeede0_ left outer join employee employee1_ on employeede0_.employee_id=employee1_.employee_id where employeede0_.employee_id=?
B) 同样,对于查询 session.createQuery("from EmployeeDetail").list();
why employee info is fetched as per below select queries instead of being proxied?
Hibernate: select employeede0_.employee_id as employee1_1_, employeede0_.city as city2_1_, employeede0_.country as country3_1_, employeede0_.state as state4_1_, employeede0_.street as street5_1_ from employeedetail employeede0_
Hibernate: select employee0_.employee_id as employee1_0_0_, employee0_.birth_date as birth_da2_0_0_, employee0_.cell_phone as cell_pho3_0_0_, employee0_.firstname as firstnam4_0_0_, employee0_.lastname as lastname5_0_0_ from employee employee0_ where employee0_.employee_id=?
Hibernate: select employee0_.employee_id as employee1_0_0_, employee0_.birth_date as birth_da2_0_0_, employee0_.cell_phone as cell_pho3_0_0_, employee0_.firstname as firstnam4_0_0_, employee0_.lastname as lastname5_0_0_ from employee employee0_ where employee0_.employee_id=?
Hibernate: select employee0_.employee_id as employee1_0_0_, employee0_.birth_date as birth_da2_0_0_, employee0_.cell_phone as cell_pho3_0_0_, employee0_.firstname as firstnam4_0_0_, employee0_.lastname as last`enter code here`name5_0_0_ from employee employee0_ where employee0_.employee_id=?
A) 这有点奇怪,Hibernate 可以做得更好。然而,这是由于 Employee
在 EmployeeDetail
中被急切地加载,Hibernate 希望避免额外的查询来为每个 EmployeeDetail
加载相应的员工。它可以做得更好,因为相应的员工已经加载了第一个查询。
如果你在 B 中采纳我的建议,这应该会消失。
B) 默认情况下,一对一关联在 JPA 中是热切的。使其变得懒惰:
@OneToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
private Employee empl;
但是,请记住描述的一对一关联的行为 here。如果 Hibernate 无法确定一对一关系中的代理对象是否存在或者是null
,那么无论如何都会执行额外的查询来检查这一点。
为了解决这个问题,如果 empl
对于每个 EmployeeDetail
都是强制性的(并且在您的用例中,没有员工就不能存在员工详细信息),然后在关联映射中指出它:
@OneToOne(fetch = FetchType.LAZY, optional = false)
@PrimaryKeyJoinColumn
private Employee empl;
这样,当加载 EmployeeDetail
实体实例时,Hibernate 将创建仅包含 Employee
id 的代理,而根本不会查询 employee
table。
Can someone please clarify why when executing the following query session.createQuery("from Employee").list();
这应该会发生,因为您的 employee
table 必须有 3 个条目。由于它是一对一的映射,对于从员工返回的每一行,它将触发一个查询以获取其 employeedetail
。所以三个查询。
B) also, for the query session.createQuery("from EmployeeDetail").list();
代理仅为延迟加载的实体创建。
我使用主键连接列 (employee_id) 类 映射(双向)员工和员工详细信息
@Entity
@Table(name="employee")
public class Employee {
@Id
@GeneratedValue
@Column(name="employee_id")
private Long employeeId;
@Column(name="firstname")
private String firstname;
@Column(name="lastname")
private String lastname;
@Column(name="birth_date")
@Temporal(value = TemporalType.DATE )
private Date birthDate;
@Column(name="cell_phone")
private String cellphone;
@OneToOne(mappedBy="empl", cascade=CascadeType.ALL)
private EmployeeDetail employeeDetail;
...
}
@Table(name="employeedetail")
public class EmployeeDetail {
@Id
@Column(name="employee_id", unique=true, nullable=false)
@GeneratedValue(generator="gen")
@GenericGenerator(name="gen", strategy="foreign", parameters=@Parameter(name="property", value="empl"))
private Long employeeId;
@Column(name="street")
private String street;
@Column(name="city")
private String city;
@Column(name="state")
private String state;
@Column(name="country")
private String country;
@OneToOne
@PrimaryKeyJoinColumn
private Employee empl;
....................
}
有人可以解释为什么在执行以下查询时 session.createQuery("from Employee").list();
A) 像 2)、3) 和 4) 这样的连接查询被执行以从 employeedetail 获取数据? 为什么不使用 employee 对象中的 employeeid 值直接从 employeedetail table 中获取而不进行连接?
1) Hibernate: select employee0_.employee_id as employee1_0_, employee0_.birth_date as birth_da2_0_, employee0_.cell_phone as cell_pho3_0_, employee0_.firstname as firstnam4_0_, employee0_.lastname as lastname5_0_ from employee employee0_
2) Hibernate: select employeede0_.employee_id as employee1_1_0_, employeede0_.city as city2_1_0_, employeede0_.country as country3_1_0_, employeede0_.state as state4_1_0_, employeede0_.street as street5_1_0_, employee1_.employee_id as employee1_0_1_, employee1_.birth_date as birth_da2_0_1_, employee1_.cell_phone as cell_pho3_0_1_, employee1_.firstname as firstnam4_0_1_, employee1_.lastname as lastname5_0_1_ from employeedetail employeede0_ left outer join employee employee1_ on employeede0_.employee_id=employee1_.employee_id where employeede0_.employee_id=?
3) Hibernate: select employeede0_.employee_id as employee1_1_0_, employeede0_.city as city2_1_0_, employeede0_.country as country3_1_0_, employeede0_.state as state4_1_0_, employeede0_.street as street5_1_0_, employee1_.employee_id as employee1_0_1_, employee1_.birth_date as birth_da2_0_1_, employee1_.cell_phone as cell_pho3_0_1_, employee1_.firstname as firstnam4_0_1_, employee1_.lastname as lastname5_0_1_ from employeedetail employeede0_ left outer join employee employee1_ on employeede0_.employee_id=employee1_.employee_id where employeede0_.employee_id=?
4) Hibernate: select employeede0_.employee_id as employee1_1_0_, employeede0_.city as city2_1_0_, employeede0_.country as country3_1_0_, employeede0_.state as state4_1_0_, employeede0_.street as street5_1_0_, employee1_.employee_id as employee1_0_1_, employee1_.birth_date as birth_da2_0_1_, employee1_.cell_phone as cell_pho3_0_1_, employee1_.firstname as firstnam4_0_1_, employee1_.lastname as lastname5_0_1_ from employeedetail employeede0_ left outer join employee employee1_ on employeede0_.employee_id=employee1_.employee_id where employeede0_.employee_id=?
B) 同样,对于查询 session.createQuery("from EmployeeDetail").list();
why employee info is fetched as per below select queries instead of being proxied?
Hibernate: select employeede0_.employee_id as employee1_1_, employeede0_.city as city2_1_, employeede0_.country as country3_1_, employeede0_.state as state4_1_, employeede0_.street as street5_1_ from employeedetail employeede0_
Hibernate: select employee0_.employee_id as employee1_0_0_, employee0_.birth_date as birth_da2_0_0_, employee0_.cell_phone as cell_pho3_0_0_, employee0_.firstname as firstnam4_0_0_, employee0_.lastname as lastname5_0_0_ from employee employee0_ where employee0_.employee_id=?
Hibernate: select employee0_.employee_id as employee1_0_0_, employee0_.birth_date as birth_da2_0_0_, employee0_.cell_phone as cell_pho3_0_0_, employee0_.firstname as firstnam4_0_0_, employee0_.lastname as lastname5_0_0_ from employee employee0_ where employee0_.employee_id=?
Hibernate: select employee0_.employee_id as employee1_0_0_, employee0_.birth_date as birth_da2_0_0_, employee0_.cell_phone as cell_pho3_0_0_, employee0_.firstname as firstnam4_0_0_, employee0_.lastname as last`enter code here`name5_0_0_ from employee employee0_ where employee0_.employee_id=?
A) 这有点奇怪,Hibernate 可以做得更好。然而,这是由于 Employee
在 EmployeeDetail
中被急切地加载,Hibernate 希望避免额外的查询来为每个 EmployeeDetail
加载相应的员工。它可以做得更好,因为相应的员工已经加载了第一个查询。
如果你在 B 中采纳我的建议,这应该会消失。
B) 默认情况下,一对一关联在 JPA 中是热切的。使其变得懒惰:
@OneToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
private Employee empl;
但是,请记住描述的一对一关联的行为 here。如果 Hibernate 无法确定一对一关系中的代理对象是否存在或者是null
,那么无论如何都会执行额外的查询来检查这一点。
为了解决这个问题,如果 empl
对于每个 EmployeeDetail
都是强制性的(并且在您的用例中,没有员工就不能存在员工详细信息),然后在关联映射中指出它:
@OneToOne(fetch = FetchType.LAZY, optional = false)
@PrimaryKeyJoinColumn
private Employee empl;
这样,当加载 EmployeeDetail
实体实例时,Hibernate 将创建仅包含 Employee
id 的代理,而根本不会查询 employee
table。
Can someone please clarify why when executing the following query session.createQuery("from Employee").list();
这应该会发生,因为您的 employee
table 必须有 3 个条目。由于它是一对一的映射,对于从员工返回的每一行,它将触发一个查询以获取其 employeedetail
。所以三个查询。
B) also, for the query session.createQuery("from EmployeeDetail").list();
代理仅为延迟加载的实体创建。