我面对的是:
failed to lazily initialize a collection of role: ,no session or session was closed
尝试访问(来自控制器或junit)“DataDictionary”中“DataDictionaryEntry”的集合。
@Entity
@Table( name = "IDS_RAVE_DATA_DICTIONARY",
uniqueConstraints={@UniqueConstraint(columnNames={"name"})
})
public class DataDictionary extends UnversionedObject {
@Column
private String name;
@OneToMany(mappedBy="dataDictionary",fetch=FetchType.EAGER)
private Collection<DataDictionaryEntry> dataDictionaryNames;
/* constructor */
public DataDictionary() {
super();
}
/* getters & setters */
}
@Entity
@Table( name = "IDS_RAVE_DATA_DICTIONARY_ENTRY",
uniqueConstraints={@UniqueConstraint(columnNames={"dataDictionary","codedData"})
})
public class DataDictionaryEntry extends UnversionedObject {
@ManyToOne
@JoinColumn(name="dataDictionary")
private DataDictionary dataDictionary;
@Column
private String codedData;
@Column
private Integer ordinal;
@Column
private String userDataString;
@Column
private Boolean specify;
/* constructor */
public DataDictionaryEntry() {
super();
}
/* getters & setters */
}
我有一个抽象的服务对象和另一个扩展它的服务:
@Transactional
public abstract class RaveGeneralServiceImpl<T> implements RaveGeneralService<T> {
private JpaRepository<T, Long> repo;
/**
* Init the general rave services with your specific repo
* @param repo
*/
protected void init(JpaRepository<T, Long> repo){
this.repo = repo;
}
@Override
public List<T> findAll(){
return repo.findAll();
}
@Override
public T save(T obj){
return repo.save(obj);
}
@Override
public void flush(){
repo.flush();
}
}
@Service
public class DataDictionaryServiceImpl extends RaveGeneralServiceImpl<DataDictionary> implements DataDictionaryService {
@Resource
private DataDictionaryRepository dataDictionaryRepository;
@PostConstruct
public void init() {
super.init(dataDictionaryRepository);
}
}
我可以找到有关如何解决它的回复。经常看到的第一个解决方案是将LAZY更改为EAGER。当我在访问FINDALL()方法时打印生成的查询时,它显示以下内容:
Hibernate:
/* select
generatedAlias0
from
DataDictionary as generatedAlias0 */ select
datadictio0_.ID as ID81_,
datadictio0_.createdByUser as createdB2_81_,
datadictio0_.createdTime as createdT3_81_,
datadictio0_.lastUpdateTime as lastUpda4_81_,
datadictio0_.lastUpdateUser as lastUpda5_81_,
datadictio0_.VERSION as VERSION81_,
datadictio0_.name as name81_
from
IDS_RAVE_DATA_DICTIONARY datadictio0_
Hibernate:
/* load one-to-many com.bdls.ids.model.rave.DataDictionary.dataDictionaryNames */ select
datadictio0_.dataDictionary as dataDic11_81_1_,
datadictio0_.ID as ID1_,
datadictio0_.ID as ID82_0_,
datadictio0_.createdByUser as createdB2_82_0_,
datadictio0_.createdTime as createdT3_82_0_,
datadictio0_.lastUpdateTime as lastUpda4_82_0_,
datadictio0_.lastUpdateUser as lastUpda5_82_0_,
datadictio0_.VERSION as VERSION82_0_,
datadictio0_.codedData as codedData82_0_,
datadictio0_.dataDictionary as dataDic11_82_0_,
datadictio0_.ordinal as ordinal82_0_,
datadictio0_.specify as specify82_0_,
datadictio0_.userDataString as userDat10_82_0_
from
IDS_RAVE_DATA_DICTIONARY_ENTRY datadictio0_
where
datadictio0_.dataDictionary=?
我们经常看到的第二个解决方案是调用正在懒惰地初始化的组件的.size()。所以确实将我的服务改为:
@Service
public class DataDictionaryServiceImpl extends RaveGeneralServiceImpl<DataDictionary> implements DataDictionaryService {
@Resource
private DataDictionaryRepository dataDictionaryRepository;
@PostConstruct
public void init() {
super.init(dataDictionaryRepository);
}
@Override
public List<DataDictionary> findAll() {
List<DataDictionary> results = super.findAll();
for (DataDictionary dd : results) {
dd.getDataDictionaryNames().size();// init lazy
}
return results;
}
}
懒惰的异常也消失了!但最终结果是相同的查询......那么如果最终查询是相同的那么保持LAZY的附加价值是什么?或者我做错了吗?
假设对于前端,您将拥有一个仅显示基本信息(例如名称)的数据表,它会调用findAll()但仍会查询该对象的完整依赖项吗?
答案 0 :(得分:1)
虽然这种方法的结果几乎完全相同,但保持懒惰的价值在于,如果你不需要在其他查询中获取它,你就不会自动获取它。使关系急切应用于访问该实体的每个方法,而在集合上调用大小会强制为该一个实例提取它。
还有其他方法可能更有效,例如在JPA查询本身中使用连接提取限定符,允许提供程序使用单个选择来获取关系。
答案 1 :(得分:0)
您可以使用:Hibernate.initialize()来初始化Lazy集合。
或者使用spring来避免LazyException在web.xml中使用filer:
<filter>
<filter-name>hibernateFilterChain</filter-name>
<filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>hibernateFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
但请记住,如果您正在考虑良好的应用程序设计和性能,那么使用延迟提取是个坏主意。