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