【问题标题】:Hibernate.initialize() being completely ignoredHibernate.initialize() 被完全忽略
【发布时间】:2012-11-19 22:04:25
【问题描述】:

我有一个带有一些延迟加载属性的实体,我正在尝试为一种特定方法初始化这些属性(大多数情况下,加载这些属性的成本太高,因此无法将它们设置为 EAGER)。

其中一个属性是一个集合,它在调用 Hibernate.initialize() 时可以很好地加载。另一个是单个对象,无论我尝试什么都不会加载。我什至无法查询它,因为对象的 id 本身不可用,即使在同一个会话期间也不可用。

调用initialize() 时我没有遇到任何异常,只是被忽略了。当在集合上而不是在单个对象上调用 this 时,日志会显示相应的查询。非常感谢有关加载此属性(设备)的任何帮助。这是代码:

编辑 事实证明我在数据库中缺少一个外键。一旦我纠正了这个问题,获取查询就会出现在控制台上,但是,在 initialize() 完成后,Device 对象仍然是一个代理。我想出了一个解决方法:

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

如果我将属性复制到另一个对象,则可以在方法之外访问它们,否则该对象仍然是代理。知道是什么原因造成的吗?谢谢

@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;
}

这些是我的映射:

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;
    }
}

【问题讨论】:

    标签: java hibernate lazy-loading


    【解决方案1】:

    显然您的代码已经可以使用,因为您可以访问代理上的“名称”字段。为什么需要将代理替换为底层对象?我在休眠文档中没有发现任何提示,初始化意味着将真实对象放在代理后面。

    Hibernate 可能不会丢弃代理以保持对它的引用有效。您可以按照评论部分的链接中的说明从代理获取实现。

    【讨论】:

    • 因为我返回的对象稍后将被序列化为 JSON,并且为了能够访问这些属性上的数据,我需要手动将其复制到另一个对象。出于某种原因,这在集合上的工作方式不同。在这种情况下,初始化会自动加载对象的属性,从而消除克隆对象的繁琐。
    • JSON 转换是使用反射完成的吗?尝试接口实现方法。 Hibernate 总是使用代理来处理惰性的一对一关系。对于一对多,它可以使用自定义集合类。
    • 谢谢,很高兴知道这是默认行为,不再是我的代码中的错误。我为此失去了理智。
    【解决方案2】:

    示例 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;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-15
      • 2011-10-19
      • 1970-01-01
      • 1970-01-01
      • 2014-09-03
      • 1970-01-01
      • 1970-01-01
      • 2015-06-08
      相关资源
      最近更新 更多