使用主键连接列进行一对一映射

时间:2015-06-29 15:30:22

标签: hibernate persistence

我使用主键连接列(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("来自Employee")时会说明.list();

A)执行2),3)和4)之类的连接查询以从employeedetail获取数据?     为什么不使用employee对象中的employeeid值直接从employeedetail表中获取而没有连接?

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("来自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=?

2 个答案:

答案 0 :(得分:0)

A)有点奇怪,Hibernate可以做得更好。但是,这是因为Employee急切地加载EmployeeDetail,而Hibernate希望避免其他查询为每个EmployeeDetail加载相应的员工。它可以做得更好,因为相应的员工已经加载了第一个查询。

如果您在B)中应用我的建议,这应该会消失。

B)默认情况下,JPA中一对一的关联是渴望的。为了让它变得懒惰:

@OneToOne(fetch = FetchType.LAZY)
@PrimaryKeyJoinColumn
private Employee empl;

但是,请记住here描述的一对一关联的行为。如果Hibernate无法确定一对一关系中的代理对象是否存在或者是null,那么无论如何都会执行其他查询来检查它。

要解决此问题,如果每个empl都必须EmployeeDetail(并且在您的用例中,员工详细信息在没有员工的情况下不能存在),请在关联映射中指明:< / p>

@OneToOne(fetch = FetchType.LAZY, optional = false)
@PrimaryKeyJoinColumn
private Employee empl;

这样,在加载Employee实体实例时,Hibernate将只生成一个包含EmployeeDetail id的代理,而根本不查询employee表。

答案 1 :(得分:0)

  

有人可以澄清为什么在执行以下查询session.createQuery(&#34;来自员工&#34;)。list();

这应该发生,因为您的employee表必须有3个条目。由于它是一对一映射,对于从员工返回的每一行,它将触发查询以获取其employeedetail。所以这三个问题。

  

B)也用于查询session.createQuery(&#34;来自EmployeeDetail&#34;)。list();

仅为延迟加载的实体创建代理。