初始化惰性集合时出错
Error Initializing Lazy Collection
我正在尝试编写一些代码来确定客户是否具有某些功能。我有这个方法:
@Transactional(readOnly = true)
public boolean customerHasFeature(String customerId, String feature) {
Customer customer = customerDAO.findByCid(customerId);
if(customer != null) {
return customer.hasFeatureNamed(feature);
}
return false;
}
customerDAO 方法在这里
@Transactional(readOnly = true)
public Customer findByCid(String cid) {
List<Customer> customers = findByCriteriaImpl(Restrictions.eq("cid", cid));
if(customers.size() > 0)
return customers.get(0);
return null;
}
在我检索客户后,在 customerHasFeature 中它没有加载功能,我收到错误
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.socialware.model.Customer.features, no session or session was closed
调试findbyCid时,可以看到criteria检索customer后加载的features,但是return customer到customerHasFeature时出错。
我尝试添加
Hibernate.initialize(customer.getFeatures());
在我调用 customerHasFeature 方法中的 customerDAO 之后,我得到了
org.hibernate.HibernateException: collection is not associated with any session
我正在使用 hibernate 3,感谢任何帮助或指导。
编辑
这是 findByCriteriaImpl 方法。
List<T> findByCriteriaImpl(Criterion... criterion) {
Criteria crit = createCriteria(getPersistentClass());
if (criterion != null) {
for (Criterion c : criterion) {
crit.add(c);
}
}
long startTime = System.currentTimeMillis();
List<T> toReturn = crit.list();
reportQueryTimeForMonitoring(System.currentTimeMillis() - startTime, "findByCriteriaImpl", "for criteria " + crit);
return toReturn;
}
和客户 class
public class Customer implements Serializable{
private static final long serialVersionUID = -1L;
@Field(index=Index.UN_TOKENIZED)
private long customerId;
private String cid;
//@Field
private String name;
private Set<Feature> features;
private boolean deleted = false;
private String randomKey;
public Customer() {
}
@Override
public String toString() {
return new StringBuilder()
.append("Customer{")
.append(customerId).append(", ")
.append(cid).append(", ")
.append(name).append(", ")
.append(deleted)
.append("}").toString();
}
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
Customer other = (Customer) obj;
if(cid == null) {
if(other.cid != null)
return false;
}
else if(!cid.equals(other.cid))
return false;
if(customerId != other.customerId)
return false;
if(name == null) {
if(other.name != null)
return false;
}
else if(!name.equals(other.name))
return false;
return true;
}
public long getCustomerId() {
return customerId;
}
public void setCustomerId(long customerId) {
this.customerId = customerId;
}
public void addFeature(Feature feature) {
if(null == getFeatures()) {
features = new HashSet<Feature>();
}
features.add(feature);
}
public Set<Feature> getFeatures() {
return features;
}
public void setFeatures(Set<Feature> features) {
this.features = features;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCid() {
return cid;
}
public void setCid(String cid) {
this.cid = cid;
}
public boolean isDeleted() {
return deleted;
}
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
public String getRandomKey() {
return randomKey;
}
public void setRandomKey(String randomKey) {
this.randomKey = randomKey;
}
public boolean hasFeatureNamed(String name) {
Set<Feature> features = getFeatures();
if (features == null) {
return false;
}
for (Feature feature : features) {
if (feature != null && feature.getName().equals(name)) {
return true;
}
}
return false;
}
public void removeFeature(String name) {
Set<Feature> features = getFeatures();
if (features == null) {
return;
}
for (Iterator<Feature> i = features.iterator(); i.hasNext();) {
Feature feature = i.next();
if (feature.getName().equals(name)) {
i.remove();
}
}
}
}
查看您的 Customer
class,我看不出您是如何映射 features
集合的,但请注意,无论您如何映射,默认的抓取类型都是 LAZY
,意味着你的集合不会在读取过程中被初始化。
请尝试以下操作:
List<T> findByCriteriaImpl(List<String> fetches, Criterion... criterion) {
Criteria crit = createCriteria(getPersistentClass());
if (criterion != null) {
for (Criterion c : criterion) {
crit.add(c);
}
for (String s : fetches) {
crit.setFetchMode(s, FetchMode.JOIN);
}
}
long startTime = System.currentTimeMillis();
List<T> toReturn = crit.list();
reportQueryTimeForMonitoring(System.currentTimeMillis() - startTime, "findByCriteriaImpl", "for criteria " + crit);
return toReturn;
}
并像这样调用 findByCriteriaImpl
:
List<Customer> customers = findByCriteriaImpl(Collections.asList("features"), Restrictions.eq("cid", cid));
这样您就可以告诉您的方法您想要将哪些集合与您的实体一起获取。
我正在尝试编写一些代码来确定客户是否具有某些功能。我有这个方法:
@Transactional(readOnly = true)
public boolean customerHasFeature(String customerId, String feature) {
Customer customer = customerDAO.findByCid(customerId);
if(customer != null) {
return customer.hasFeatureNamed(feature);
}
return false;
}
customerDAO 方法在这里
@Transactional(readOnly = true)
public Customer findByCid(String cid) {
List<Customer> customers = findByCriteriaImpl(Restrictions.eq("cid", cid));
if(customers.size() > 0)
return customers.get(0);
return null;
}
在我检索客户后,在 customerHasFeature 中它没有加载功能,我收到错误
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.socialware.model.Customer.features, no session or session was closed
调试findbyCid时,可以看到criteria检索customer后加载的features,但是return customer到customerHasFeature时出错。
我尝试添加
Hibernate.initialize(customer.getFeatures());
在我调用 customerHasFeature 方法中的 customerDAO 之后,我得到了
org.hibernate.HibernateException: collection is not associated with any session
我正在使用 hibernate 3,感谢任何帮助或指导。
编辑
这是 findByCriteriaImpl 方法。
List<T> findByCriteriaImpl(Criterion... criterion) {
Criteria crit = createCriteria(getPersistentClass());
if (criterion != null) {
for (Criterion c : criterion) {
crit.add(c);
}
}
long startTime = System.currentTimeMillis();
List<T> toReturn = crit.list();
reportQueryTimeForMonitoring(System.currentTimeMillis() - startTime, "findByCriteriaImpl", "for criteria " + crit);
return toReturn;
}
和客户 class
public class Customer implements Serializable{
private static final long serialVersionUID = -1L;
@Field(index=Index.UN_TOKENIZED)
private long customerId;
private String cid;
//@Field
private String name;
private Set<Feature> features;
private boolean deleted = false;
private String randomKey;
public Customer() {
}
@Override
public String toString() {
return new StringBuilder()
.append("Customer{")
.append(customerId).append(", ")
.append(cid).append(", ")
.append(name).append(", ")
.append(deleted)
.append("}").toString();
}
@Override
public boolean equals(Object obj) {
if(this == obj)
return true;
if(obj == null)
return false;
if(getClass() != obj.getClass())
return false;
Customer other = (Customer) obj;
if(cid == null) {
if(other.cid != null)
return false;
}
else if(!cid.equals(other.cid))
return false;
if(customerId != other.customerId)
return false;
if(name == null) {
if(other.name != null)
return false;
}
else if(!name.equals(other.name))
return false;
return true;
}
public long getCustomerId() {
return customerId;
}
public void setCustomerId(long customerId) {
this.customerId = customerId;
}
public void addFeature(Feature feature) {
if(null == getFeatures()) {
features = new HashSet<Feature>();
}
features.add(feature);
}
public Set<Feature> getFeatures() {
return features;
}
public void setFeatures(Set<Feature> features) {
this.features = features;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCid() {
return cid;
}
public void setCid(String cid) {
this.cid = cid;
}
public boolean isDeleted() {
return deleted;
}
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
public String getRandomKey() {
return randomKey;
}
public void setRandomKey(String randomKey) {
this.randomKey = randomKey;
}
public boolean hasFeatureNamed(String name) {
Set<Feature> features = getFeatures();
if (features == null) {
return false;
}
for (Feature feature : features) {
if (feature != null && feature.getName().equals(name)) {
return true;
}
}
return false;
}
public void removeFeature(String name) {
Set<Feature> features = getFeatures();
if (features == null) {
return;
}
for (Iterator<Feature> i = features.iterator(); i.hasNext();) {
Feature feature = i.next();
if (feature.getName().equals(name)) {
i.remove();
}
}
}
}
查看您的 Customer
class,我看不出您是如何映射 features
集合的,但请注意,无论您如何映射,默认的抓取类型都是 LAZY
,意味着你的集合不会在读取过程中被初始化。
请尝试以下操作:
List<T> findByCriteriaImpl(List<String> fetches, Criterion... criterion) {
Criteria crit = createCriteria(getPersistentClass());
if (criterion != null) {
for (Criterion c : criterion) {
crit.add(c);
}
for (String s : fetches) {
crit.setFetchMode(s, FetchMode.JOIN);
}
}
long startTime = System.currentTimeMillis();
List<T> toReturn = crit.list();
reportQueryTimeForMonitoring(System.currentTimeMillis() - startTime, "findByCriteriaImpl", "for criteria " + crit);
return toReturn;
}
并像这样调用 findByCriteriaImpl
:
List<Customer> customers = findByCriteriaImpl(Collections.asList("features"), Restrictions.eq("cid", cid));
这样您就可以告诉您的方法您想要将哪些集合与您的实体一起获取。