未能懒惰地初始化一个角色集合,..无法初始化代理 - 没有会话 - JPA + SPRING [英] failed to lazily initialize a collection of role,..could not initialize proxy - no Session - JPA + SPRING

查看:774
本文介绍了未能懒惰地初始化一个角色集合,..无法初始化代理 - 没有会话 - JPA + SPRING的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我沿着Spring(3.2.2)使用JPA(使用Hibernate 4.3.3作为持久化提供者),所有的字段都加载正常,但是当我试图访问我的Collection时抛出错误 -

 线程main中的异常org.hibernate.LazyInitializationException:未能懒惰地初始化一个角色集合:com.br.common.catalog.entity。 Category.allParentCategoryXrefs,无法初始化代理 - 没有会话
在org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:572)
在org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded (AbstractPersistentCollection.java:212)
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:551)
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java :140)
org.hibernate。 (java.lang.String.valueOf(String.java:2827))
位于java.io.PrintStream.println(PrintStream.java: 771)
at test.Test.main(Test.java:30)

当我调试了这个我得到了我的实体类中定义的每个集合的错误 - com.sun.jdi.InvocationException发生了调用方法。



我尝试使用collection.size()和Hibernate.initialize(),但没有一个工作。
在互联网上搜索时,我发现扩展Persitence将解决问题,即。

  @PersistenceContext(type = PersistenceContextType。 EXTENDED)

受保护的EntityManager em;

这个工作正常,但是通过这个我发现em会一直保持打开状态,现在spring不会处理这个。有没有什么办法可以用Spring来解决这个问题。任何帮助的高度赞赏。



我的实体是 -

  @Entity 
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name =CATEGORY)
public class Category implements Serializable {
@Id
@GeneratedValue (generator =CategoryId)
@Column(name =CATEGORY_ID)
保护长ID;

@ManyToOne(targetEntity = Category.class)
@JoinColumn(name =DEFAULT_PARENT_CATEGORY_ID)
@Index(name =CATEGORY_PARENT_INDEX,columnNames = {DEFAULT_PARENT_CATEGORY_ID} )
保护类别defaultParentCategory;

@OneToMany(targetEntity = Categoryref.class,mappedBy =categoryrefPK.category)
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE,region =test)
@OrderBy (value =displayOrder)
@BatchSize(size = 50)

protected List< Categoryref> childCategoryRefs = new ArrayList< Categoryref>(10);
@OneToMany(targetEntity = Categoryref.class,mappedBy =categoryrefPK.subCategory,fetch = FetchType.LAZY)
@Cascade(value = {org.hibernate.annotations.CascadeType.MERGE,org.hibernate .annotations.CascadeType.PERSIST})
@OrderBy(value =displayOrder)
@BatchSize(size = 50)
protected List< Categoryref> parentCategoryRefs = new ArrayList< Categoryref>(10);



$ b @Entity
@Polymorphism(type = PolymorphismType.EXPLICIT)
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name =CATEGORY_REF)
public class Categoryref实现Serializable {
/ **类别ID。 * /
@EmbeddedId
CategoryrefPK categoryrefPK = new CategoryrefPK();

public CategoryrefPK getCategoryrefPK(){
return categoryrefPK;
}

public void setCategoryrefPK(final CategoryrefPK categoryrefPK){
this.categoryrefPK = categoryrefPK;



可嵌入的
public class CategoryrefPK实现Serializable {

@ManyToOne(targetEntity = Category.class,optional = false )
@JoinColumn(name =CATEGORY_ID)
protected Category category = new Category();

@ManyToOne(targetEntity = Category.class,可选= false)
@JoinColumn(name =SUB_CATEGORY_ID)
protected Category subCategory = new Category();


$ / code>

我的Xml配置为 -

 <?xml version =1.0encoding =UTF-8?> 
< beans xmlns =http://www.springframework.org/schema/beans
xmlns:xsi =http://www.w3.org/2001/XMLSchema-instancexmlns :aop =http://www.springframework.org/schema/aop
xmlns:context =http://www.springframework.org/schema/contextxmlns:tx =http:// www.springframework.org/schema/tx
xsi:schemaLocation =http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/ spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http:// www .springframework.org / schema / tx
http://www.springframework.org/schema/tx/spring-tx.xsd\">

< context:component-scan base-package =com.br/>

< bean id =dataSource
class =org.springframework.jdbc.datasource.DriverManagerDataSource>
....
< / bean>
<! - 这也用于我们也可以使用这个 - >
< tx:注解驱动的事务管理器=transactionManager/>
< bean id =transactionManagerclass =org.springframework.orm.jpa.JpaTransactionManager>
< property name =entityManagerFactoryref =entityManagerFactory/>
< / bean>
< bean id =entityManagerFactoryclass =org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean>
< property name =persistenceXmlLocationvalue =classpath:META-INF / persistence.xml/>
< property name =dataSourceref =dataSource/>
< property name =persistenceUnitNamevalue =abc/>
< property name =packagesToScanvalue =com.br.common。*/>
< property name =jpaVendorAdapter>
< bean class =org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter>
< property name =showSqlvalue =true/>
< property name =databasePlatformvalue =org.hibernate.dialect.MySQLDialect/>
< / bean>
< / property>
< / bean>


< / beans>

Persitence.xml

 <?xml version =1.0encoding =UTF-8?> 
< persistence version =2.0
xmlns =http://java.sun.com/xml/ns/persistencexmlns:xsi =http://www.w3.org/ 2001 / XMLSchema-instance
xsi:schemaLocation =http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd >
< persistence-unit name =abc>
transaction-type =RESOURCE_LOCAL>
< mapping-file> META-INF / category.orm.xml< / mapping-file>
< class> com.br.common.Category< / class>
< class> com.br.common.Categoryref< / class>
< class> com.br.common.CategoryrefPK< / class>

<属性>
< property name =javax.persistence.jdbc.uservalue =user
< property name =javax.persistence.jdbc.drivervalue =com.mysql.jdbc。 Driver/>
< property name =javax.persistence.jdbc.urlvalue =jdbc:mysql:// localhost:3306 / test>
< property name =javax.persistence.jdbc.password value =...>
< property name =hibernate.show_sqlvalue =true/>

< property name =hibernate.transaction。 flush_before_completion
value =false/>
< property name =hibernate.connection.autocommitvalue =true/>
< property name =hibernate。
< property name =hibernate.cache.use_second_level_cachevalue =true/>
< property name =hibernate.cache.use_query_cachevalue =true/>
< property name =hibernate.generate_statisticsvalue =false/>
<属性名称=hibernate.archive.autodetectionvalue =false/>
< property name =hibernate.dialectvalue =org.hibernate.dialect.MySQLDialect/>
< property name =hibernate.id.new_generator_mappingsvalue =true/>
< / properties>
< / persistence-unit>
< /余辉>

这是我的道,我通过服务层调用dao

  @Repository(categoryDaoImpl)
public class CategoryDaoImpl implements ICategoryDAO {

@PersistenceContext
protected EntityManager em;


public类别保存(Category category){
Category category2 = em.merge(category);

em.flush();
返回类别2;
}
public类别readCategoryById(Long categoryId){
return em.find(Category.class,categoryId);
}


}

服务层

  @Service(blCatalogService)
@Transactional(propagation = Propagation.REQUIRED)
public class CatalogServiceImpl实现ICatalogService {

@Resource(name =categoryDaoImpl)
protected ICategoryDAO categoryDao;

@Transactional
public产品saveProduct(Product product){
return productDao.save(product);
}

public类别findCategoryById(Long categoryId){
return categoryDao.readCategoryById(categoryId);
}

}

这是主要的

  public class Test {


public static void main(String [] args){
ApplicationContext context = new ClassPathXmlApplicationContext(
applicationContext-persistence.xml);
ICatalogService serviceCategory =(ICatalogService)context
.getBean(blCatalogService);
类别parentCategory = serviceCategory.findCategoryById(2l);
System.out.println(parentCategory.getAllParentCategoryrefs()); //在访问集合
}时出现错误
}


<$ p

解决方案

$ p> 类别parentCategory = serviceCategory.findCategoryById(2l);

您不再处于 @Transactional 上下文。这意味着链接到parentCategory的会话已关闭。现在当您尝试访问链接到已关闭会话的集合时,会发生 No Session 错误。



要注意的是主要方法在任何spring bean之外运行,并且没有持久化上下文的概念。



解决方法是调用 parentCategory.getAllParentCategoryrefs ()从事务上下文,它永远不会是你的应用程序的主要方法。

然后将parentCategory重新连接到新的持久化上下文,然后调用getter。



将parentCategory传回给相同服务的事务方法:

  serviceCategory.nowItWorks(parentCategory); 

其中服务的方法是事务性的:

  @Transactional(readOnly = true)
public void nowItWorks(Category category){
dao.nowItWorks(category);
}

而在DAO中:

  public void nowItWorks(Category category){
Category reattached = em.merge(category);
System.out.println(It works:+ reattached.getAllParentCategoryrefs());
}


I am using JPA(with Hibernate 4.3.3 as persistence provider ) along Spring (3.2.2) , all my fields are loading fine but when I am trying to access my Collection it's throwing the error-

Exception in thread "main" org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.br.common.catalog.entity.Category.allParentCategoryXrefs, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:572)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:212)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:551)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:140)
    at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:526)
    at java.lang.String.valueOf(String.java:2827)
    at java.io.PrintStream.println(PrintStream.java:771)
    at test.Test.main(Test.java:30)

When I debugged this I was getting error for every collection defined in my entity class - com.sun.jdi.InvocationException occurred invoking method.

I tried using collection.size() and Hibernate.initialize() but none of this worked. On searching on internet I found that extending Persitence will solve the problem ie.

 @PersistenceContext(type=PersistenceContextType.EXTENDED)

        protected EntityManager em;

this worked fine but through this I found that em will always remain opened , now spring will not handle this. Is there any way to solve this problem using Spring. Any Help is highly appreciated.

My Entities are as -

  @Entity
    @Inheritance(strategy = InheritanceType.JOINED)
    @Table(name="CATEGORY")
    public class Category implements Serializable {
       @Id
        @GeneratedValue(generator= "CategoryId")
         @Column(name = "CATEGORY_ID")
        protected Long id;

        @ManyToOne(targetEntity = Category.class)
        @JoinColumn(name = "DEFAULT_PARENT_CATEGORY_ID")
        @Index(name="CATEGORY_PARENT_INDEX", columnNames={"DEFAULT_PARENT_CATEGORY_ID"})
        protected Category defaultParentCategory;

        @OneToMany(targetEntity = Categoryref.class, mappedBy = "categoryrefPK.category")
        @Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region="test")
        @OrderBy(value="displayOrder")
        @BatchSize(size = 50)

        protected List<Categoryref> childCategoryRefs = new ArrayList<Categoryref>(10);
        @OneToMany(targetEntity = Categoryref.class, mappedBy = "categoryrefPK.subCategory",fetch=FetchType.LAZY)
        @Cascade(value={org.hibernate.annotations.CascadeType.MERGE, org.hibernate.annotations.CascadeType.PERSIST})
        @OrderBy(value="displayOrder")
        @BatchSize(size = 50)
        protected List<Categoryref> parentCategoryRefs = new ArrayList<Categoryref>(10);

    }


@Entity
@Polymorphism(type = PolymorphismType.EXPLICIT)
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "CATEGORY_REF")
public class Categoryref implements Serializable {
    /** The category id. */
    @EmbeddedId
    CategoryrefPK categoryrefPK = new CategoryrefPK();

    public CategoryrefPK getCategoryrefPK() {
        return categoryrefPK;
    }

    public void setCategoryrefPK(final CategoryrefPK categoryrefPK) {
        this.categoryrefPK = categoryrefPK;
    }
  }

@Embeddable
public class CategoryrefPK implements Serializable {

    @ManyToOne(targetEntity = Category.class, optional=false)
    @JoinColumn(name = "CATEGORY_ID")
    protected Category category = new Category();

    @ManyToOne(targetEntity = Category.class, optional=false)
    @JoinColumn(name = "SUB_CATEGORY_ID")
    protected Category subCategory = new Category();

}

My Xml Configuration is as -

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd
           http://www.springframework.org/schema/tx  
           http://www.springframework.org/schema/tx/spring-tx.xsd">

    <context:component-scan base-package="com.br" />

    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        ....
    </bean>
<!--  this is also used we can used this also  -->
  <tx:annotation-driven transaction-manager="transactionManager" />  
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
        <property name="dataSource" ref="dataSource" />
         <property name="persistenceUnitName" value="abc" />   
        <property name="packagesToScan" value="com.br.common.*" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="databasePlatform" value="org.hibernate.dialect.MySQLDialect" />
            </bean>
        </property>
    </bean>  


</beans>  

Persitence.xml

    <?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
    xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="abc">
        transaction-type="RESOURCE_LOCAL">
          <mapping-file>META-INF/category.orm.xml</mapping-file>
        <class>com.br.common.Category</class>
        <class>com.br.common.Categoryref</class>
        <class>com.br.common.CategoryrefPK</class>

        <properties>
            <property name="javax.persistence.jdbc.user" value="user"
            <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect"></property>
            <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test>
            <property name="javax.persistence.jdbc.password" value="...">
            <property name="hibernate.show_sql" value="true" />

            <property name="hibernate.transaction.flush_before_completion"
                value="false" />
            <property name="hibernate.connection.autocommit" value="true" />
            <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/>
            <property name="hibernate.cache.use_second_level_cache" value="true" /> 
            <property name="hibernate.cache.use_query_cache" value="true"/>
            <property name="hibernate.generate_statistics" value="false" />
            <property name="hibernate.archive.autodetection" value="false" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
            <property name="hibernate.id.new_generator_mappings" value="true" />
        </properties>
    </persistence-unit>
</persistence>

this is my dao i am calling dao through service layer

@Repository("categoryDaoImpl")
public class CategoryDaoImpl implements ICategoryDAO {

    @PersistenceContext
    protected EntityManager em;


    public Category save(Category category) {
      Category category2=   em.merge(category);

         em.flush();
         return category2;
  }
    public Category readCategoryById(Long categoryId) {
        return em.find(Category.class, categoryId);
    }


}

servie layer

    @Service("blCatalogService")
@Transactional(propagation=Propagation.REQUIRED)
public class CatalogServiceImpl implements ICatalogService {

    @Resource(name="categoryDaoImpl")
    protected ICategoryDAO categoryDao;

    @Transactional
    public Product saveProduct(Product product) {
        return productDao.save(product);
    }

    public Category findCategoryById(Long categoryId) {
        return categoryDao.readCategoryById(categoryId);
    }

}

this is main

public class Test {


        public static void main(String[] args) {
                ApplicationContext context = new ClassPathXmlApplicationContext(
                    "applicationContext-persistence.xml");
            ICatalogService serviceCategory= (ICatalogService) context
                    .getBean("blCatalogService");
                Category parentCategory=serviceCategory.findCategoryById(2l);
    System.out.println(parentCategory.getAllParentCategoryrefs());//here error is coming while accessing collection
    }
    }

解决方案

The problem is that when this method call returns:

Category parentCategory=serviceCategory.findCategoryById(2l);

Here you are no longer in a @Transactional context. this means that the session linked to parentCategory got closed. now when you try to access a collection linked to a closed session, the No Session error occurs.

One thing to notice is that the main method runs outside any spring bean and has no notion of persistence context.

The solution is to call the parentCategory.getAllParentCategoryrefs() from a transactional context, which can never be the main method of your application.

Then reattach the parentCategory to the new persistence context, and then call the getter.

Try for example to pass the parentCategory back to a transactional method of the same service:

serviceCategory.nowItWorks(parentCategory);

where the method on the service is transactional:

@Transactional(readOnly=true)
public void nowItWorks(Category category) {
    dao.nowItWorks(category);
}

And in the DAO:

public void nowItWorks(Category category) {
    Category reattached = em.merge(category);
    System.out.println("It works: " + reattached.getAllParentCategoryrefs());
}

这篇关于未能懒惰地初始化一个角色集合,..无法初始化代理 - 没有会话 - JPA + SPRING的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆