2012-07-29 59 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

相关问题