2012-12-02 52 views
1

我有一個實體,有一些懶加載的屬性,我試圖初始化一個特定的方法(大部分時間它太昂貴,這些被加載,所以他們不能被設置爲EAGER)。Hibernate.initialize()被完全忽略

其中一個屬性是一個集合,它在調用Hibernate.initialize()時加載得很漂亮。另一個是單個對象,不管我嘗試什麼都不會加載。我甚至不能查詢它,因爲對象的ID本身不可用,即使在同一個會話中也是如此。

我在調用initialize()時沒有收到任何異常,它只是簡單地被忽略。該日誌在集合上調用此查詢時會顯示相應的查詢,但不會顯示在單個對象上。加載此屬性(設備)的任何幫助,非常感謝。這是代碼:

編輯 事實證明,我在數據庫中缺少一個外鍵。一旦我糾正了這個問題,控制檯上就會出現提取查詢,但是在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; 
    } 
} 

回答

1

顯然你的代碼已經工作的,因爲你可以在代理訪問場「名」。爲什麼您需要將代理替換爲基礎對象?在hibernate文檔中我沒有發現任何提示,意味着初始化不僅僅是將真實對象放在代理之後。

Hibernate可能不會放棄代理以保持對它的引用有效。您可以按照註釋部分中的鏈接所述從代理獲取實施。

+0

因爲我返回的對象將被序列化爲JSON,並且爲了能夠訪問這些屬性的數據,我需要手動將它複製到另一個對象。出於某種原因,這在集合上的作用是不同的。在這種情況下,初始化會自動加載對象的屬性,從而消除克隆對象的繁瑣。 – JayPea

+0

使用反射完成了JSON轉換嗎?嘗試一種接口實現方法。 Hibernate總是使用代理來實現懶惰的一對一關係。對於一對多,它可以使用自定義集合類。 – sorencito

+1

https://forum.hibernate.org/viewtopic.php?t=947035 – sorencito