[英]LazyInitializationException
我收到以下例外情況:
javax.el.ELException: Error reading 'id' on type com.example.model.Article_$$_javassist_2
...
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:149)
org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:195)
org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
com.example.model.Article_$$_javassist_2.getId(Article_$$_javassist_2.java)
...
這是我的代碼:
@Entity
@Table( name = "tbl_articles" )
public class Article implements Comparable<Article>, Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Column( nullable = false )
@GeneratedValue( strategy = GenerationType.IDENTITY )
private Integer id;
// some other fields
@ManyToMany( cascade = { CascadeType.ALL } )
@JoinTable( name = "tbl_articles_categories",
joinColumns = { @JoinColumn( name = "article_id" ) },
inverseJoinColumns = { @JoinColumn( name = "category_id" ) })
@ForeignKey( name = "tbl_articles_categories_fkey_article",
inverseName = "tbl_articles_categories_fkey_category" )
private Set<Category> categories = new HashSet<Category>();
@ManyToMany( cascade = { CascadeType.ALL } )
@JoinTable( name = "tbl_articles_tags",
joinColumns = { @JoinColumn( name = "article_id" ) },
inverseJoinColumns = { @JoinColumn( name = "tag_id" ) })
@ForeignKey( name = "tbl_articles_tags_fkey_article",
inverseName = "tbl_articles_tags_fkey_tag" )
private Set<Tag> tags = new HashSet<Tag>();
// getters and setters
}
public abstract class BaseService<E, D extends BaseDAO<E>>
{
protected D dao;
public BaseService()
{
}
protected D getDao()
{
return dao;
}
@Autowired
protected void setDAO( D dao )
{
this.dao = dao;
}
@Transactional
public E get( int id )
{
return dao.get( id );
}
}
@Service
public class ArticleService extends BaseService<Article, ArticleDAO>
{
public ArticleService()
{
setDAO( dao );
}
}
public abstract class BaseDAO<E>
{
public abstract E get( int id );
}
@Repository
public class ArticleDAO extends BaseDAO<Article>
{
@Autowired
private SessionFactory sessionFactory;
@Override
public Article get( int id )
{
return ( Article ) sessionFactory.getCurrentSession().load( Article.class, id );
}
}
現在,在我的Controller中,我正在使用它來獲取特定的文章:
@RequestMapping( "/{id}/{title}.html" )
public String article( @PathVariable( "id" ) Integer id, Map<String, Object> map )
{
map.put( "article", articleService.get( id ) );
return "article";
}
我在JSP中使用的是這樣的:
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="slg" uri="http://github.com/slugify" %>
<article>
<c:url value="/blog/${article.id}/${slg:slugify(article.title)}.html" var="articleUrl" />
<h2><a href="${articleUrl}">${article.title}</a></h2>
<span><fmt:formatDate value="${article.creationDate}" pattern="E, dd MMM yyyy" /></span>
<p>
${article.text}
</p>
</article>
這也是我的休眠配置:
# Properties file with Hibernate Settings.
#-------------------------------------------------------------------------------
# Common Settings
hibernate.generate_statistics=false
#hibernate.hbm2ddl.auto=update
hibernate.show_sql=false
#-------------------------------------------------------------------------------
# DB specific Settings
# Property that determines which Hibernate dialect to use
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
我做錯了什么?
UPDATE
調試sessionFactory.getCurrentSession()
結果為:
DEBUG : com.example.model.ArticleDAO - SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])
我正在添加一些全局變量,也許這會導致錯誤? 在我的控制器中,有一個方法:
@ModelAttribute
public void addGlobalObjects( Map<String, Object> map )
{
map.put( "section", "blog" );
SortedMap<Category, Integer> categories = new TreeMap<Category, Integer>();
for ( Category category : categoryService.list() )
{
categories.put( category, articleService.size( category ) );
}
Calendar cal = Calendar.getInstance();
cal.set( Calendar.DAY_OF_MONTH, 1 );
cal.add( Calendar.MONTH, ARCHIVE_MONTHS * -1 );
SortedMap<Date, Integer> archive = new TreeMap<Date, Integer>();
for ( int i = 0; i < ARCHIVE_MONTHS; ++i )
{
cal.add( Calendar.MONTH, 1 );
archive.put( cal.getTime(), articleService.size( cal ) );
}
SortedMap<Tag, Integer> tags = new TreeMap<Tag, Integer>();
for ( Tag tag : tagService.list() )
{
tags.put( tag, articleService.size( tag ) );
}
map.put( "categories", categories );
map.put( "archive", archive );
map.put( "tags", tags );
map.put( "categoriesSize", categoryService.size() );
map.put( "tagsSize", tagService.size() );
map.put( "date", new Date() );
}
有關更新的文章實體,請參見上文。
UPDATE2
渴望獲取並不能解決問題-仍然是相同的例外:
@ManyToMany( fetch = FetchType.EAGER, cascade = { CascadeType.ALL } )
最后,我得到了不需要的重復文章...
UPDATE3
嘗試Hibernate.initialize()
我收到此異常:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.LazyInitializationException: could not initialize proxy - no Session
UPDATE4
我以這種方式更改了get方法:
@Override
public Article get( int id )
{
// return ( Article ) sessionFactory.getCurrentSession().load( Article.class, id );
return ( Article ) sessionFactory.getCurrentSession().createCriteria( Article.class ).add( Restrictions.eq( "id", id ) ).uniqueResult();
}
這不是解決方案,但由於無法解決此問題,因此將暫時使用它。
我已經嘗試過這一點(如提到這里 )沒有成功(它改變了ELException Error reading 'id' on type ...
到Error reading 'title' on type ...
-也許我用錯了?):
@Override
public Article get( int id )
{
Article ret = ( Article ) sessionFactory.getCurrentSession().load( Article.class, id );
sessionFactory.getCurrentSession().update( ret );
return ret;
}
仍然需要解決方案!
這成功了!
已將ArticleDAO.get從
@Override
public Article get( int id )
{
return ( Article ) sessionFactory.getCurrentSession().load( Article.class, id );
}
至
@Override
public Article get( int id )
{
Article ret = ( Article ) sessionFactory.getCurrentSession().get( Article.class, id );
if ( ret == null )
{
ret = ( Article ) sessionFactory.getCurrentSession().load( Article.class, id );
}
return ret;
}
不確定發生了什么問題,但有一些問題可以指導您-
1.可以調試方法嗎
public Article get( int id )
看看你能得到什么
sessionFactory.getCurrentSession()
這是有效的會話嗎?
2.您能否詳細說明商品實體? 與另一個實體有某種關系嗎?
我懷疑您的問題介於我的問題之間。
根據您提供的信息更新我的答案-
如我所懷疑,您的Article實體與其他實體有關系。
您不會急切地獲取Article和相關實體。
但是,您確實嘗試修改與Article關聯的集合。 這是錯的
據我所知,如果初始化此地圖,則應該修改集合(以您的情況為例的地圖)(通過專門分配可推動Map接口的對象並將其設置為字段)
(您沒有-Hibernate從數據庫中檢索到一篇文章后就為您初始化了它,請閱讀有關PersistentMap的更多內容,以了解更多信息),
或者您應該修改集合(如果已獲取)。
請在這里閱讀有關渴望獲取的信息。
您還可以編寫一個HSQL,執行不帶注釋的熱切獲取。
在這里閱讀如何使用HQL執行提取(搜索左連接提取)。
由於您正在使用Hibernate,因此可以調用Hibernate.initialize()
來初始化該惰性集合。
另一方面,您可以創建一個NamedQuery來獲取與您的Article關聯的所有項目並替換該集合。 但是,僅當您的集合沒有使用orphanRemoval=true
注釋時,此選項才可用。 請注意,如果您不小心管理實體,最終可能會導致數據庫中的條目不一致。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.