简体   繁体   English

Hibernate.initialize()被完全忽略

[英]Hibernate.initialize() being completely ignored

I have an entity with some lazy loaded properties which I'm trying to initialize for one particular method (most of the time it's too expensive for these to be loaded, so they can't be set to EAGER). 我有一个带有一些延迟加载属性的实体,我正在尝试为一种特定方法进行初始化(大多数情况下,这些属性加载起来过于昂贵,因此无法将其设置为EAGER)。

One of these properties is a collection and it loads beautifully when calling Hibernate.initialize(). 这些属性之一是一个集合,在调用Hibernate.initialize()时,它可以精美地加载。 The other is a single object and it won't load no matter what I try. 另一个是单个对象,无论我尝试什么都不会加载。 I can't even query for it, since the object's id itself isn't available, not even during the same session. 我什至无法查询它,因为对象的ID本身不可用,即使在同一会话期间也是如此。

I'm not getting any exceptions when calling initialize(), it's just simply being ignored. 调用initialize()时,我没有任何异常,只是被忽略了。 The log shows the corresponding query when calling this on the collection but not on the single object. 当在集合上调用此查询时,日志显示了相应的查询,但在单个对象上却没有。 Any help on loading this property (Device) is greatly appreciated. 非常感谢在加载此属性(设备)方面的任何帮助。 This is the code: 这是代码:

EDIT It turns out I had a missing foreign key in the database. 编辑事实证明,我在数据库中缺少外键。 Once I corrected this, the fetch query appeared on the console, however, the Device object is still a proxy after initialize() completes. 一旦更正此问题,提取查询就会出现在控制台上,但是,initialize()完成后,Device对象仍然是代理。 I came up with a workaround by doing this: 我想出了一种解决方法:

Device device = new Device();
        device.setIdDevice(surveyLog.getDevice().getIdDevice());
        device.setName(surveyLog.getDevice().getName());
        surveyLog.setDevice(device);

If I copy the properties to another object, they can be accessed outside the method, otherwise the object remains a proxy. 如果我将属性复制到另一个对象,则可以在方法外部访问它们,否则该对象仍然是代理。 Any idea what could be causing this? 知道是什么原因造成的吗? Thanks 谢谢

@Transactional    
public SurveyLog getById(Long id)
{
    SurveyLog surveyLog = this.surveyLogDAO.findById(id);

    Hibernate.initialize(surveyLog.getDevice()); //doesn't work 
    Hibernate.initialize(surveyLog.getSurveyAnswers()); //works like a charm
    return surveyLog;
}

And these are my mappings: 这些是我的映射:

import static javax.persistence.GenerationType.IDENTITY;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;

import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode;

import com.google.gson.annotations.Expose;

@Entity
@Table(name="SurveyLog")
public class SurveyLog
{
    // Fields    
    @Expose private Long idSurveyLog;
    @Expose private Survey survey;
    @Expose private Device device;
    @Expose private BigDecimal latitude;
    @Expose private BigDecimal longitude;
    @Expose private Timestamp timestamp;
    @Expose private List<SurveyAnswerLog> surveyAnswers = new ArrayList<SurveyAnswerLog>();

    /**
     * Constructor.
     * 
     */
    public SurveyLog() {}

    // Property accessors
    @Id
    @GeneratedValue(strategy=IDENTITY)
    @Column(name="idSurveyLog", unique=true, nullable=false)
    public Long getIdSurveyLog()
    {
        return idSurveyLog;
    }

    public void setIdSurveyLog(Long idSurveyLog)
    {
        this.idSurveyLog = idSurveyLog;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumn(name="idSurvey", nullable=false)
    public Survey getSurvey()
    {
        return survey;
    }

    public void setSurvey(Survey survey)
    {
        this.survey = survey;
    }

    @ManyToOne(fetch=FetchType.LAZY)
    @Fetch(value = FetchMode.SELECT)
    @JoinColumn(name="idDevice", nullable=false)    
    public Device getDevice()
    {
        return device;
    }

    public void setDevice(Device device)
    {
        this.device = device;
    }

    @Column(name="latitude", precision=8, scale=6)
    public BigDecimal getLatitude()
    {
        return latitude;
    }

    public void setLatitude(BigDecimal latitude)
    {
        this.latitude = latitude;
    }

    @Column(name="longitude", precision=9, scale=6)
    public BigDecimal getLongitude()
    {
        return longitude;
    }

    public void setLongitude(BigDecimal longitude)
    {
        this.longitude = longitude;
    }

    @Column(name="timestamp", length=19)
    public Timestamp getTimestamp()
    {
        return timestamp;
    }

    public void setTimestamp(Timestamp timestamp)
    {
        this.timestamp = timestamp;
    }

    @OneToMany(fetch=FetchType.LAZY, mappedBy="surveyLog")
    @Cascade({CascadeType.ALL, CascadeType.DELETE_ORPHAN})
    public List<SurveyAnswerLog> getSurveyAnswers()
    {
        return surveyAnswers;
    }

    public void setSurveyAnswers(List<SurveyAnswerLog> surveyAnswers)
    {
        this.surveyAnswers = surveyAnswers;
    }
}



import static javax.persistence.GenerationType.IDENTITY;

import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import javax.persistence.Version;

import com.google.gson.annotations.Expose;
import com.sitei.base.model.City;
import com.sitei.base.model.Company;

@Entity
@Table(name="Device", uniqueConstraints = @UniqueConstraint(columnNames = "macAddress"))
public class Device
{
    // Fields
    @Expose private Integer idDevice;
    @Expose private String macAddress;
    @Expose private String name;
    @Expose private String description;
    @Expose private Short type;
    @Expose private City city;
    @Expose private Company company;
    @Expose private Survey survey;
    @Expose private Integer surveyPoints;
    @Expose private boolean active;
    @Expose private Long version;



    /**
     * Constructor.
     * 
     */
    public Device() {}

    // Property accessors
    @Id
    @GeneratedValue(strategy=IDENTITY)
    @Column(name="idDevice", unique=true, nullable=false)
    public Integer getIdDevice()
    {
        return idDevice;
    }

    public void setIdDevice(Integer idDevice)
    {
        this.idDevice = idDevice;
    }

    @Column(name="macAddress", nullable=false, length=17)
    public String getMacAddress()
    {
        return macAddress;
    }

    public void setMacAddress(String macAddress)
    {
        this.macAddress = macAddress;
    }

    @Column(name="name", nullable=false, length=64)
    public String getName()
    {
        return name;
    }

    public void setName(String name)
    {
        this.name = name;
    }

    @Column(name="description", length=256)
    public String getDescription() 
    {
        return description;
    }

    public void setDescription(String description)
    {
        this.description = description;
    }

    @Column(name="type", nullable=false)
    public Short getType()
    {
        return type;
    }

    public void setType(Short type)
    {
        this.type = type;
    }

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="idCity", nullable=false)
    public City getCity()
    {
        return city;
    }

    public void setCity(City city)
    {
        this.city = city;
    }

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="idCompany")
    public Company getCompany()
    {
        return company;
    }

    public void setCompany(Company company)
    {
        this.company = company;
    }

    @ManyToOne(fetch=FetchType.EAGER)
    @JoinColumn(name="idSurvey")
    public Survey getSurvey()
    {
        return survey;
    }

    public void setSurvey(Survey survey)
    {
        this.survey = survey;
    }

    @Column(name="surveyPoints", nullable=false)
    public Integer getSurveyPoints()
    {
        return surveyPoints;
    }

    public void setSurveyPoints(Integer surveyPoints)
    {
        this.surveyPoints = surveyPoints;
    }

    @Column(name="active", nullable=false)
    public boolean isActive()
    {
        return active;
    }

    public void setActive(boolean active)
    {
        this.active = active;
    }

    @Version
    public Long getVersion()
    {
        return version;
    }

    public void setVersion(Long version)
    {
        this.version = version;
    }
}

Obviously your code already works, because you can access field 'name' on the proxy. 显然,您的代码已经可以使用,因为您可以访问代理上的字段“名称”。 Why do you need the proxy to be replaced by the underlying object? 为什么需要将代理替换为基础对象? I have not found any hint in the hibernate documentation that initializing means anything more than putting the real object behind the proxy. 我在休眠文档中没有发现任何暗示,除了将实际对象放在代理之后,初始化还意味着什么。

Hibernate probably does not discard the proxy in order to keep references to it valid. Hibernate可能不会为了保持对代理的引用而不会丢弃该代理。 You can get the implementation from the proxy as explained in the link in the comment section. 您可以按照注释部分链接中的说明从代理获取实现。

Example DAO layer 示例DAO层

List<String> methodNames= new ArrayList();

methodNames.add("getScTeamUserses");


public T getByID(PK id, List<String> methodNames) {
    T object = null;
    Session sess = getSession();
    try {
        sess.beginTransaction();
        object = (T) sess.get(clazz, id);
        Class[] clazz = null;


        for (String methodName : methodNames) {
            Method method = object.getClass().getMethod(methodName, clazz);                
            Hibernate.initialize(method.invoke(object, clazz));
        }   



        sess.getTransaction().commit();
    } catch (Exception e) {
         logger.error("getByID id=" + id, e);
        try {               
            sess.getTransaction().rollback();
            throw e;
        } catch (Exception ex) {
            logger.error("getByID methodNames id=" + id, e);
        }
    } finally {
        closeSession(sess);
    }
    return object;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM