2012-07-29 64 views
2

我得到這個異常: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); 
    } 
} 

在我的控制器現在,我用它來獲取特定的文章:

@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> 

這裏是我的Hibernate配置,以及:

# 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(); 
} 

這不是一個解決方案,但我不能處理這個問題我會暫時使用。

我已經嘗試過這一點(如前所述here)沒有成功(從Error reading 'id' on type ...Error reading 'title' on type ...改變了ELException - 也許我用錯了?):

@Override 
public Article get(int id) 
{ 
    Article ret = (Article) sessionFactory.getCurrentSession().load(Article.class, id); 
    sessionFactory.getCurrentSession().update(ret); 
    return ret; 
} 

仍然需要一個解決方案!

回答

2

這個伎倆!從

@Override 
public Article get(int id) 
{ 
    return (Article) sessionFactory.getCurrentSession().load(Article.class, id); 
} 

更改ArticleDAO.get到

@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

不確定有什麼問題,但有些問題可以指導您 -
1。你可以調試方法

public Article get(int id) 

,看看你得到

sessionFactory.getCurrentSession() 

這是一個有效的會話?


2.您能詳細闡述Article實體嗎?與另一個實體有某種關係嗎?

我懷疑你的問題存在於我的問題之間。



更新到我的答案,下面的信息您提供的 -

正如我懷疑,你的文章實體與其他實體的關係。
您不會執行文章和相關實體的預先提取。
但是,您確實嘗試修改與文章關聯的集合。這是錯誤的
據我所知,如果你初始化了這張地圖(通過專門分配一個物體來推動Map接口,並將其設置到字段),你應該修改集合(在你的情況下是地圖)
(你沒有 - 一旦你從數據庫中檢索了一篇文章,Hibernate會爲你初始化它,通過閱讀PersistentMap),
來看更多,或者你應該修改集合,如果它被提取。

請在這裏閱讀關於eager取閱。
您也可以編寫一個HSQL,它將執行渴望獲取,而無需註釋。
閱讀here如何使用HQL執行提取(搜索左連接提取)。

+0

謝謝您的回答,我已經更新了我的問題。 – dtrunk 2012-07-30 10:28:01

+0

更新我的回答 – 2012-07-30 19:47:57

+0

查看** UPDATE2 ** – dtrunk 2012-07-31 13:57:53

1

由於您使用的是Hibernate,因此您可以調用Hibernate.initialize()來初始化該懶惰集合。

另一方面,您可以創建一個NamedQuery,以獲取與您的文章關聯的所有項目並替換該集合。但是,只有當您沒有用orphanRemoval=true註解您的收藏集時,才能使用此選項。小心,因爲如果你不小心管理你的實體,最終會導致數據庫中的條目不一致。

+0

查看** UPDATE3 ** – dtrunk 2012-07-31 14:07:34

相關問題