Announcement Announcement Module
Collapse
No announcement yet.
JPA, Spring 2.0, Hibernate 3.2 and Lazy Fetching of collections Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JPA, Spring 2.0, Hibernate 3.2 and Lazy Fetching of collections

    I started this discussion as part of another thread, but I feel it deserves its own.

    I'm trying to use Hibernate Entity Manager, Annotations and Core version 3.2 with Spring version 2.0. I'd like to mark some of my collections with FetchType.LAZY. My problem is my JSP's blow up when trying to access these collections. I dug through some docs and found the OpenEntityManagerInView filter and thought it would be perfect. However it doesn't work, or at least it doesn't work how I expected it to.

    Here is how I have things going so far:

    Spring Config for persistence stuff:
    Code:
    <?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:tx="http://www.springframework.org/schema/tx"
    	   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" default-autowire="no">
    
        <!-- JPA annotations bean post processor -->
        <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
    
        <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    		<property name="persistenceUnitName" value="em1"/>
        </bean>
    
        <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    		<property name="entityManagerFactory" ref="entityManagerFactory" />
        </bean>
    
        <tx:annotation-driven/>
    
    </beans>
    Here is my persistence.xml
    Code:
    <persistence 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_1_0.xsd"
                 version="1.0">
        <persistence-unit name="em1" transaction-type="RESOURCE_LOCAL">
            <properties>
                <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
                <property name="hibernate.hbm2ddl.auto" value="update"/>
                <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/>
                <property name="hibernate.connection.url" value="jdbc:mysql://localhost:3306/mydatabase"/>
                <property name="hibernate.connection.username" value="username"/>
                <property name="hibernate.connection.password" value="password"/>
                <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider"/>
            </properties>
        </persistence-unit>
    </persistence>
    An example domain object getter for a collection:
    Code:
    @ManyToMany(targetEntity = Match.class, mappedBy = "teams", cascade = {CascadeType.REMOVE}, fetch = FetchType.LAZY)
        public List<Match> getMatches()
        {
            return matches;
        }
    I have a parent class that all DAO's extend, it has the following code snippet:
    Code:
    @PersistenceContext
        public void setEntityManager(EntityManager entityManager)
        {
            this.entityManager = entityManager;
        }
    My web.xml config for the filter:
    Code:
    <filter>
            <filter-name>oemiv</filter-name>
            <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
            <init-param>
                <param-name>entityManagerFactoryBeanName</param-name>
                <param-value>entityManagerFactory</param-value>
            </init-param>
        </filter>
    
    <filter-mapping>
            <filter-name>oemiv</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>

    Am I missing something? The view always blows up on lazy collections

  • #2
    Here's an interesting hack.

    Create your own TransactionManager extending JpaTransactionManager
    and override this method. Here the manager will use the entity manager bound to the ThreadLocal instead of creating its own.

    protected EntityManager createEntityManagerForTransaction()
    {
    Map map = TransactionSynchronizationManager.getResourceMap() ;
    Iterator it=map.keySet().iterator();
    while( it.hasNext() )
    {
    Object o = it.next();
    if(o instanceof EntityManagerFactory )
    {
    return (( EntityManagerHolder )map.get( o )).getEntityManager();
    }
    }


    return super.createEntityManagerForTransaction();
    }

    Comment


    • #3
      The custom TransactionManager seems like something that could do the trick but as that seem to be exactly what the OpenEntityManagerInView(Filter|Interceptor) should be doing. I'm still in the "it must be a small matter of configuring"-state of mind.

      jefmsmit: If you raise the logging level to max, can you also see several entitymanagers or factories being used?

      It would be nice if the original author of the OEMIVF could show the test he/she has used to conclude that the component is working because currently it seems that noone has seen a working example of this, regardless of MVC/View technology used.

      Comment

      Working...
      X