未能懒惰地初始化角色集合,..无法初始化代理 – 没有会话 – JPA + SPRING

我在Spring(3.2.2)中使用JPA(使用Hibernate 4.3.3作为持久性提供程序),我的所有字段都正常加载,但是当我尝试访问我的Collection时,它会抛出错误 –

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.

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

  @PersistenceContext(type=PersistenceContextType.EXTENDED) protected EntityManager em; 

这工作正常,但通过这个我发现他们将永远保持打开,现在spring将不会处理这个。 有没有办法用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 childCategoryRefs = new ArrayList(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 parentCategoryRefs = new ArrayList(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配置如下 –

     ....                    

Persitence.xml

     transaction-type="RESOURCE_LOCAL"> META-INF/category.orm.xml com.br.common.Category com.br.common.Categoryref com.br.common.CategoryrefPK  <property name="javax.persistence.jdbc.user" value="user"                  

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

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

问题是当此方法调用返回时:

 Category parentCategory=serviceCategory.findCategoryById(2l); 

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

需要注意的一点是,main方法在任何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()); } 

就像@Zeus所说的那样,很多次,很多次都回答过。 您在测试类中遇到此问题,因为您的事务在服务调用时开始和结束:

 Category parentCategory=serviceCategory.findCategoryById(2l); 

回想一下Hibernate文档,延迟加载仅适用于Hibernate会话(在这种情况下,hibernate会话以服务调用开始和结束)。 您无法重新连接到hibernate会话(简单地)来初始化集合。

当你想“在spring”解决它时,我不确定你的意思。 因为这不是Spring问题。 基本上解决这个问题的两种方法是在加载父进程的hibernate会话中加载集合,或者在原始hibernate会话之外执行单独的fetch。

在域集集合中使用@Fetch(FetchMode.SELECT)@LazyCollection(LazyCollectionOption.FALSE) ,它将起作用

尝试使用fetch=FetchType.EAGER ,它会工作