JPA fetchType.Lazy 不工作
Posted
技术标签:
【中文标题】JPA fetchType.Lazy 不工作【英文标题】:JPA fetchType.Lazy is not working 【发布时间】:2013-09-09 08:00:56 【问题描述】:我正在尝试fetchType.Lazy
的示例,但是在调试代码时,fetchType.Lazy
似乎不起作用。
实体 bean:地址
在区字段上添加了带有属性 fetch=fetchType.Lazy 的注释 @Basic。
我的实体 bean 由以下代码定义:
package model;
import java.io.Serializable;
import javax.persistence.*;
import java.util.List;
/**
* The persistent class for the address database table.
*/
@Entity
@Table(name="address", schema="home")
public class Address implements Serializable
private static final long serialVersionUID = 1L;
@TableGenerator(name = "addr_gen", table = "table_generator", pkColumnName = "gen_name", valueColumnName = "gen_val", allocationSize=1)
@Id
@GeneratedValue(strategy=GenerationType.TABLE, generator="addr_gen")
private String addressId;
private String city;
@Basic(fetch=FetchType.LAZY)
@Column(name="district")
private String district;
private String houseNumber;
private String pincode;
private String state;
private String street;
//bi-directional many-to-one association to Employee
@OneToMany(mappedBy="address")
private List<Employee> employees;
public Address()
public String getAddressId()
return this.addressId;
public void setAddressId(String addressId)
this.addressId = addressId;
public String getCity()
return this.city;
public void setCity(String city)
this.city = city;
public String getDistrict()
return this.district;
public void setDistrict(String district)
this.district = district;
public String getHouseNumber()
return this.houseNumber;
public void setHouseNumber(String houseNumber)
this.houseNumber = houseNumber;
public String getPincode()
return this.pincode;
public void setPincode(String pincode)
this.pincode = pincode;
public String getState()
return this.state;
public void setState(String state)
this.state = state;
public String getStreet()
return this.street;
public void setStreet(String street)
this.street = street;
public List<Employee> getEmployees()
return this.employees;
public void setEmployees(List<Employee> employees)
this.employees = employees;
public Employee addEmployees(Employee employees)
getEmployees().add(employees);
employees.setAddress(this);
return employees;
public Employee removeEmployees(Employee employees)
getEmployees().remove(employees);
employees.setAddress(null);
return employees;
/*@Override
public String toString()
return "Address [addressId=" + addressId + ", city=" + city
+ ", district=" + district + ", houseNumber=" + houseNumber
+ ", pincode=" + pincode + ", state=" + state + ", street="
+ street + ", employees=" + employees + "]";
*/
使用上述实体bean的方法:
public Address findAddress(EntityManagerFactory emf, UserTransaction tx)
EntityManager em = emf.createEntityManager();
Address addr = null;
try
tx.begin();
addr = em.find(Address.class, new String("154"));
tx.commit();
catch (Exception e)
e.printStackTrace();
return addr;
所以在find
方法调用之后,当我检查地址对象时,它已经填充了地区字段。
请让我知道我是否缺少某些配置或代码本身是否存在问题。
【问题讨论】:
作为旁注,但您何时(如果有的话)关闭 EntityManager? 对不起我的错误,我应该在所有操作完成后关闭 entityManager。 【参考方案1】:问题在于,当在@Basic
注释中使用时,应用程序服务器可以/可能自行决定何时获取数据更好。如记录的here
EAGER 策略是对持久性提供程序运行时的要求,即必须急切地获取值。 LAZY 策略是对持久性提供程序运行时的提示。
@OneToMany
-like annotations 根据documentation 有同样的问题,但在这种情况下,JPA 提供者更有可能考虑 FetchType 提示。
另一方面,您可以尝试使用大数据字段,例如
@Lob
@Basic(fetch=FetchType.LAZY)
private byte[] document;
查看是否有变化(尽管同样,您的应用程序服务器可以决定始终获取该字段)。
为了检查是否加载了集合字段,我会检查数据库查询日志或执行以下操作:
@PersistenceContext private EntityManager em;
.....
Person person = em.find(Person.class, 1L);//Person entity has a OneToMany relationship to entity Address
em.detach(person);
person.getAddresses().size();//if the Address are now not fetched, it the call should throw an error
【讨论】:
感谢 Andrei 的回复,我会检查并更新。除此之外,我还尝试了 @ManytoOne 关系,但 fetchType.Lazy 没有用。 我的意思是@OneToMany。在虚构的 Person 实体中试试这个:@OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL) private Setaddresses;并检查数据库日志,当您执行 EntityManager.find(Person.class, 1) 时执行了哪些查询。您如何检查该字段是否已填充? (用 person.getAddressed() 检查它没有意义) 我发布的有问题的相同代码现在工作正常...... :-) 我正在使用调试器检查是否填充了字段。调用 find 方法后,我正在检查对象,并在调用 getter 后检查对象。 @ShashiShankar 请提及您为使代码开始工作所做的工作【参考方案2】:确保您已启用编织。
http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Performance/Weaving
【讨论】:
我使用 glassfish 3.1 作为我的 JPA 提供程序,所以我应该进行编织配置吗? 这个答案是 EclipseLink 特定的,OP 从来没有说过他正在使用 eclipselink。 (现在 FWIW 已弃用)【参考方案3】:要在JPA中初始化laze,需要调用jar库并启动它,如果是maven或者手动por example,如果需要laze,在maven中使用jar jar de.empulse.eclipselink 更多信息http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Performance/Weaving/Static_Weaving#Use_the_Maven_plugin
如果你不使用maven,你可以手动启用jar
【讨论】:
以上是关于JPA fetchType.Lazy 不工作的主要内容,如果未能解决你的问题,请参考以下文章
JPA。 FetchType.Lazy 引起了奇怪的行为@ManyToOne
FetchType.Lazy 在 Spring Boot 中无法在 JPA 中工作
Spring Boot 2. Jackson json 序列化或 Spring Data JPA FetchType.Lazy
使用 FetchType.LAZY 防止 JPA/Hibernate 中的延迟加载(尤其是在使用 @Transactional 时)?