我有一个具有一些延迟加载属性的实体,我正在尝试为一个特定方法初始化(大多数情况下,加载这些属性太昂贵,所以它们不能设置为EAGER)。
其中一个属性是一个集合,它在调用Hibernate.initialize()时可以很好地加载。另一个是单个对象,无论我尝试什么,它都不会加载。我甚至无法查询它,因为对象的id本身不可用,即使在同一个会话期间也是如此。
调用initialize()时我没有遇到任何异常,只是被忽略了。日志在集合上调用此对象时显示相应的查询,但在单个对象上不显示。任何有关加载此属性(设备)的帮助非常感谢。这是代码:
修改 事实证明我在数据库中丢失了一个外键。一旦我更正了这一点,fetch查询出现在控制台上,但是,在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;
}
}
答案 0 :(得分:1)
显然,您的代码已经有效,因为您可以在代理上访问字段“name”。为什么需要将代理替换为底层对象?我没有在hibernate文档中找到任何提示,初始化意味着除了将真实对象放在代理之后。
Hibernate可能不会丢弃代理,以保持对它的引用有效。您可以从代理中获取实现,如注释部分中的链接所述。
答案 1 :(得分:0)
示例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;
}