Hibernate - FetchType.LAZY 急切地加载数据
Hibernate - FetchType.LAZY loads data eagerly
Hibernate newb 试图理解 LAZY 和 EAGER 抓取之间的区别。
地址模型:
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String street;
@Column
private String city;
@OneToOne
private Department department;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
@Override
public String toString() {
return "Address [id=" + id + ", street=" + street + ", city=" + city + "]";
}
}
部门模型:
@Entity
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String name;
@OneToOne(mappedBy = "department", fetch = FetchType.LAZY)
private Address address;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "Department [id=" + id + ", name=" + name + "]";
}
}
测试方法:
@Test
public void testDepartment() {
Long departmentID;
Department department;
Long addressId;
Address address;
try (Session session = SessionUtil.getSession()) {
Transaction tx = session.beginTransaction();
department = new Department();
department.setId(69L);
department.setName("company");
address = new Address();
address.setCity("city");
address.setStreet("street");
address.setDepartment(department);
session.save(department);
session.save(address);
departmentID = department.getId();
addressId = address.getId();
tx.commit();
}
try (Session session = SessionUtil.getSession()) {
department = session.load(Department.class, departmentID);
System.out.println(department.getId());
}
}
当我从数据库加载部门对象时,执行了以下查询。
Hibernate: select department0_.id as id1_2_0_, department0_.name as name2_2_0_ from Department department0_ where department0_.id=?
Hibernate: select address0_.id as id1_0_1_, address0_.city as city2_0_1_, address0_.department_id as departme4_0_1_, address0_.street as street3_0_1_, department1_.id as id1_2_0_, department1_.name as name2_2_0_ from Address address0_ left outer join Department department1_ on address0_.department_id=department1_.id where address0_.department_id=?
1
我很惊讶看到加入 select 查询,因为我从来没有明确要求地址对象,它应该延迟加载。
如果您查看 FetchType.LAZY 的 javadoc,您会发现没有保证(与 EAGER fetchinig 相反):
The LAZY strategy is a hint to the persistence provider runtime that
data should be fetched lazily when it is first accessed. The
implementation is permitted to eagerly fetch data for which the LAZY
strategy hint has been specified.
这对于 OneToOne 可选依赖项尤其适用,例如您的情况。
Hibernate newb 试图理解 LAZY 和 EAGER 抓取之间的区别。
地址模型:
@Entity
public class Address {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String street;
@Column
private String city;
@OneToOne
private Department department;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getStreet() {
return street;
}
public void setStreet(String street) {
this.street = street;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
@Override
public String toString() {
return "Address [id=" + id + ", street=" + street + ", city=" + city + "]";
}
}
部门模型:
@Entity
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column
private String name;
@OneToOne(mappedBy = "department", fetch = FetchType.LAZY)
private Address address;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public String toString() {
return "Department [id=" + id + ", name=" + name + "]";
}
}
测试方法:
@Test
public void testDepartment() {
Long departmentID;
Department department;
Long addressId;
Address address;
try (Session session = SessionUtil.getSession()) {
Transaction tx = session.beginTransaction();
department = new Department();
department.setId(69L);
department.setName("company");
address = new Address();
address.setCity("city");
address.setStreet("street");
address.setDepartment(department);
session.save(department);
session.save(address);
departmentID = department.getId();
addressId = address.getId();
tx.commit();
}
try (Session session = SessionUtil.getSession()) {
department = session.load(Department.class, departmentID);
System.out.println(department.getId());
}
}
当我从数据库加载部门对象时,执行了以下查询。
Hibernate: select department0_.id as id1_2_0_, department0_.name as name2_2_0_ from Department department0_ where department0_.id=?
Hibernate: select address0_.id as id1_0_1_, address0_.city as city2_0_1_, address0_.department_id as departme4_0_1_, address0_.street as street3_0_1_, department1_.id as id1_2_0_, department1_.name as name2_2_0_ from Address address0_ left outer join Department department1_ on address0_.department_id=department1_.id where address0_.department_id=?
1
我很惊讶看到加入 select 查询,因为我从来没有明确要求地址对象,它应该延迟加载。
如果您查看 FetchType.LAZY 的 javadoc,您会发现没有保证(与 EAGER fetchinig 相反):
The LAZY strategy is a hint to the persistence provider runtime that data should be fetched lazily when it is first accessed. The implementation is permitted to eagerly fetch data for which the LAZY strategy hint has been specified.
这对于 OneToOne 可选依赖项尤其适用,例如您的情况。