【问题标题】:JPA fetchType.Lazy is not workingJPA fetchType.Lazy 不工作
【发布时间】: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。

标签: jpa


【解决方案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 Set
    addresses;并检查数据库日志,当您执行 EntityManager.find(Person.class, 1) 时执行了哪些查询。您如何检查该字段是否已填充? (用 person.getAddressed() 检查它没有意义)
  • 我发布的有问题的相同代码现在工作正常...... :-)
  • 我正在使用调试器检查是否填充了字段。调用 find 方法后,我正在检查对象,并在调用 getter 后检查对象。
  • @ShashiShankar 请提及您为使代码开始工作所做的工作
【解决方案2】:

【讨论】:

  • 我使用 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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-11
    • 2011-01-07
    • 1970-01-01
    • 2013-07-28
    相关资源
    最近更新 更多