简体   繁体   English

LazyInitializationException中

[英]LazyInitializationException

I'm getting this exceptions: 我收到以下例外情况:

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)
...

Here's my code: 这是我的代码:

@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 );
    }
}

In my Controller now, I'm using this to get a specific article: 现在,在我的Controller中,我正在使用它来获取特定的文章:

@RequestMapping( "/{id}/{title}.html" )
public String article( @PathVariable( "id" ) Integer id, Map<String, Object> map )
{
    map.put( "article", articleService.get( id ) );
    return "article";
}

Which I'm using in my JSP just like this: 我在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>

Here's my hibernate configuration as well: 这也是我的休眠配置:

# 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

What I'm doing wrong? 我做错了什么?

UPDATE UPDATE

Debugging sessionFactory.getCurrentSession() results in: 调试sessionFactory.getCurrentSession()结果为:

DEBUG : com.example.model.ArticleDAO - SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];ActionQueue[insertions=[] updates=[] deletions=[] collectionCreations=[] collectionRemovals=[] collectionUpdates=[] unresolvedInsertDependencies=UnresolvedEntityInsertActions[]])

I'm adding some global variables, maybe this causing the errors? 我正在添加一些全局变量,也许这会导致错误? In my controller there's a method: 在我的控制器中,有一个方法:

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

For updated article entity see above. 有关更新的文章实体,请参见上文。

UPDATE2 UPDATE2

Eager fetching didn't solved the problem - still the same exception: 渴望获取并不能解决问题-仍然是相同的例外:

@ManyToMany( fetch = FetchType.EAGER, cascade = { CascadeType.ALL } )

And finally I'm getting duplicated articles what I don't need... 最后,我得到了不需要的重复文章...

UPDATE3 UPDATE3

Trying Hibernate.initialize() I'm getting this exception: 尝试Hibernate.initialize()我收到此异常:

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.hibernate.LazyInitializationException: could not initialize proxy - no Session

UPDATE4 UPDATE4

I changed my get method this way: 我以这种方式更改了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();
}

This is NOT a solution, but as I can't handle this problem I'll use this temporarily. 这不是解决方案,但由于无法解决此问题,因此将暂时使用它。

I already tried this (as mentioned here ) without success (it changed the ELException from Error reading 'id' on type ... to Error reading 'title' on type ... - maybe i used it wrong?): 我已经尝试过这一点(如提到这里 )没有成功(它改变了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;
}

A solution is still needed! 仍然需要解决方案!

This did the trick! 这成功了!

Changed ArticleDAO.get from 已将ArticleDAO.get从

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

to

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

Not sure what's wrong but some questions to guide you - 不确定发生了什么问题,但有一些问题可以指导您-
1. Can you debug the method 1.可以调试方法吗

public Article get( int id )

And see what do you get for 看看你能得到什么

sessionFactory.getCurrentSession()

Is this a valid session? 这是有效的会话吗?


2. Can you elaborate more on the Article entity? 2.您能否详细说明商品实体? is there some sort of relation to another entity? 与另一个实体有某种关系吗?

I suspect your issues lies somewhere between my questions. 我怀疑您的问题介于我的问题之间。



Update to my answer, following the information your provided - 根据您提供的信息更新我的答案-

As I suspected, your Article entity has relation with other entities. 如我所怀疑,您的Article实体与其他实体有关系。
You do not perform eager fetching of Article and the related entities. 您不会急切地获取Article和相关实体。
However, you do try to modify the collection associated with Article. 但是,您确实尝试修改与Article关联的集合。 This is wrong 这是错的
As far as I know, you should can modify the collection (the map in your case) either if you initialized this map (by specifically allocating an object that impelements the Map interface, and set it to the field) 据我所知,如果初始化此地图,则应该修改集合(以您的情况为例的地图)(通过专门分配可推动Map接口的对象并将其设置为字段)
(which you didn't - Hibernate initialized it for you once you retrieved an article from the DB, see more by reading about PersistentMap ), (您没有-Hibernate从数据库中检索到一篇文章后就为您初始化了它,请阅读有关PersistentMap的更多内容,以了解更多信息),
or you should modify the collection if it was fetched. 或者您应该修改集合(如果已获取)。

Please read here about eager fetching. 请在这里阅读有关渴望获取的信息。
You can also write an HSQL which will perform the eager fetch, without an annotation. 您还可以编写一个HSQL,执行不带注释的热切获取。
Read here how to perform fetching using HQL (search for left join fetch). 在这里阅读如何使用HQL执行提取(搜索左连接提取)。

Since you're using Hibernate you can invoke Hibernate.initialize() to initialize that lazy collection. 由于您正在使用Hibernate,因此可以调用Hibernate.initialize()来初始化该惰性集合。

On the other hand, you can create a NamedQuery that fetches all the items that are associated to your Article and replacing that collection. 另一方面,您可以创建一个NamedQuery来获取与您的Article关联的所有项目并替换该集合。 However, this option is only possible if you don't have your collection annotated with orphanRemoval=true . 但是,仅当您的集合没有使用orphanRemoval=true注释时,此选项才可用。 Watch out, since you can end up having inconsistent entries in your database if you don't manage your entities with care. 请注意,如果您不小心管理实体,最终可能会导致数据库中的条目不一致。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM