2014-03-25 96 views
13

我沿着Spring(3.2.2)使用JPA(與Hibernate 4.3.3一起作爲持久性提供者),我的所有字段加載罰款,但是當我試圖進入我的收藏它拋出的錯誤 -未能懶惰地初始化一個角色的集合,..無法初始化代理 - 沒有會話 - JPA + SPRING

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) 

當我調試在我的實體類中定義的每個收集這個,我得到錯誤 - com.sun.jdi.InvocationException occurred invoking method.

我試圖用收集.size()和Hibernate.initialize(),但沒有一個工作。 在互聯網上搜索我發現擴展Persitence將解決問題即。

@PersistenceContext(type=PersistenceContextType.EXTENDED) 

     protected EntityManager em; 

這個工作不錯,但通過這次我發現,EM會一直保持打開,現在春天不會處理這個問題。有沒有什麼辦法可以用Spring來解決這個問題。任何幫助,高度讚賞。

我的實體是爲 -

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

} 

我的XML配置是 -

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

通過服務層,這是我的道我打電話道

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


} 

役層

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

} 

這是主要

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 
    } 
    } 
+0

這個問題已經被問了幾次,您試圖訪問子集時,出會話上下文的,你可能有內時加載它會話上下文不會得到這個錯誤。 – Zeus

+0

可能重複的[hibernate:LazyInitializationException:無法初始化代理](http://stackoverflow.com/questions/345705/hibernate-lazyinitializationexception-could-not-initialize-proxy) – Zeus

+0

@Zeus我知道這個錯誤時懶惰初始化但我想通過使用彈簧 – henrycharles

回答

9

像@Zeus說,這之前已經很多很多,時間回答。因爲你的事務開始,併爲您服務呼叫結束您在你的測試類這一問題:從Hibernate文檔

Category parentCategory=serviceCategory.findCategoryById(2l); 

回想一下,延遲加載只有Hibernate的Session內有效(在這種情況下,Hibernate的Session開始,以您的服務電話結束)。你不能重新連接到休眠會話(簡單地)來初始化集合。

我不完全確定你的意思,當你想解決它「春天」。由於這不是春季問題。從本質上來說,解決這個問題的兩種方法是在加載父進程的hibernate會話中加載集合,或者在原始休眠會話之外執行單獨的提取。

+3

來解決它我不知道你們爲什麼迴應,因爲這是一種簡單的解決方案。我一直在關注宙斯的反應,他們都沒有爲我工作。我試過Transactional,只會通過返回null而不是錯誤響應而變得更糟。我試過其他人的解決方案,其大部分解決方案都是不贊成使用的解決方案。儘管我在JUNIT中使用了我的嵌入式休眠功能。 – numerical25

+0

我認爲這是一個答案很簡單但分辨率很複雜的例子。我不是故意輕視這個問題。答案真的取決於你的代碼是如何設計的,以及你試圖測試的級別。 Spring爲你抽象了許多樣板代碼,但你必須知道它是如何有效地使用它的。 – Aaron

15

的問題是,當這個方法調用返回:

Category 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()); 
} 
+0

在我的情況下,我有2種方法。一個用於獲取主實體,另一個用於獲取關係實體。我必須將@Transactional放在兩種方法中,並且它可以工作 –

-5

嘗試使用fetch=FetchType.EAGER,它會工作

+6

這是一個快速但並不總是最佳的解決方案。 –

2

你的域集收集使用@Fetch(FetchMode.SELECT)@LazyCollection(LazyCollectionOption.FALSE),它會工作

+0

@LazyCollection(LazyCollectionOption.FALSE)只有這樣它才能工作,你有使用非Hibernate庫的解決方案嗎?謝謝 –

相關問題