JPA fetchType.Lazy 不起作用 [英] JPA fetchType.Lazy is not working

查看:51
本文介绍了JPA fetchType.Lazy 不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试 fetchType.Lazy 的示例,但是在调试代码时,fetchType.Lazy 似乎不起作用.

I am trying examples for fetchType.Lazy, however while debugging the code, it seems that fetchType.Lazy is not working.

实体 bean:地址

在地区字段添加注释@Basic,属性fetch=fetchType.Lazy.

Added annotation @Basic with property fetch=fetchType.Lazy on district field.

我的实体 bean 由以下代码定义:

My entity bean is defined by the code below:

    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的方法:

The method which uses above entity 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 方法之后,当我检查地址对象时,它已经填充了 District 字段.

So after the find method call, when I inspected the address object, it was already populated with district field.

请告诉我是我遗漏了一些配置还是代码本身有问题.

Please let me know whether I am missing some configuration or whether there is some issue with the code itself.

推荐答案

问题是在@Basic注解中使用时,应用服务器可以/可以自己决定,什么时候更好获取数据.如此处

The problem is that when using in the @Basic annotation the application server can/may decide on his own, when it is better to fetch the data. As documented here

EAGER 策略是对持久性提供程序运行时的要求,即必须急切地获取值.LAZY 策略是对持久性提供程序运行时的提示.

The EAGER strategy is a requirement on the persistence provider runtime that the value must be eagerly fetched. The LAZY strategy is a hint to the persistence provider runtime.

@OneToMany-like annotations have 根据 文档 同样的问题,但在这种情况下,JPA 提供程序更有可能考虑 FetchType 提示.

@OneToMany-like annotations have according to the documentation the same problem, but in that case it much more likely that the JPA provider will consider the FetchType hint.

另一方面,您可以尝试使用大数据字段,例如

On the other hand, you could try with a big data field, like

@Lob
@Basic(fetch=FetchType.LAZY)
private byte[] document;

查看是否有变化(尽管您的应用服务器可以决定始终获取该字段).

to see whether something changes (although again, your application server can decide to fetch always the field).

为了检查集合字段是否已加载,我将检查数据库查询日志或执行以下操作:

In order to check whether a collection field was loaded I would either check the database query logs or do the following:

@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

这篇关于JPA fetchType.Lazy 不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆