Announcement Announcement Module
Collapse
No announcement yet.
Spring TransactionProxyFactoryBean & lazy initialization Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring TransactionProxyFactoryBean & lazy initialization

    The basic info:
    Dao classes (managers) which extend HibernateDaoSupport
    JUnit test that extends AbstractDependencyInjectionSpringContextTests to get my Dao classes.
    Group extends Principal

    I have wrapped a Dao class in TransactionProxyFactoryBean using Spring, which looks like this:

    Code:
    	<bean id="myGroupPersister" class="GroupHibernatePersister">
            <property name="sessionFactory"><ref local="mySessionFactory"/></property>    
    	</bean>
    	
    	<bean id="groupManagerTarget" class="GroupManager">
        	<property name="persister"><ref bean="myGroupPersister"/></property>
    	</bean>
        
    	<bean id="groupManager" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    		<property name="transactionManager"><ref local="myTransactionManager"/></property>
    		<property name="target"><ref local="groupManagerTarget"/></property>
    		<property name="transactionAttributes">
    			<props>
    				<prop key="*">PROPAGATION_REQUIRED</prop>
    			</props>
    		</property>
    	</bean>
    Now when I perform an operation using my Dao (manager) class, such as createGroup(), I have no problems and everything works fine. Now assume that I have multiple Group objects already created and stored. Now I try to:

    Code:
        Group g1 = loadGroup&#40;"group1"&#41;;
        Group g2 = loadGroup&#40;"group2"&#41;;
    
        g1.addMember&#40;g2&#41;;
    and I get:

    Code:
    org.hibernate.LazyInitializationException&#58; failed to lazily initialize a collection of role&#58; Principal.groupsSet - no session or session was closed
    Which I assume is because the transaction boundaries are on the Dao methods and a single session/transaction isn't wrapping all three operations. Maybe?

    My hibernate mapping is listed below and the groupSet is the collection in question that is having problems. The purpose of the groupSet being that I can determine the groups a principal is in and also add cascading to remove membership when the principal is removed.

    Code:
        <class name="Principal" table="security_principal">
            <id name="id" column="id" type="long">
                <generator class="native">
                    <param name="sequence">principal_id_sequence</param>
                </generator>
            </id>
            <property name="name" type="string">
                <column name="name" length="32" not-null="true" unique="true"/>
            </property>
            <property name="description" type="string">
                <column name="description" length="1024"/>
            </property>
    	<!-- inverse, so this is managed by groups, mapped here so we get a list of groups we belong to -->
            <set name="groupsSet" table="security_group_membership" inverse="true" >
                <key column="principal_id"/>
                <many-to-many class="Group" column="group_id"/>
            </set>
            
            <joined-subclass name="Person" table="security_person">
                <key column="id"/>
                <property name="personID" type="string">
                    <column name="person_id" length="32" unique="true" not-null="true"/>
                </property>
                <property name="userName" type="string">
                    <column name="name" length="32" unique="true" not-null="true"/>
                </property>
                <property name="firstName" type="string">
                    <column name="first_name" length="32" not-null="true"/>
                </property>
                <property name="middleName" type="string">
                    <column name="middle_name" length="32"/>
                </property>
                <property name="lastName" type="string">
                    <column name="last_name" length="32" not-null="true"/>
                </property>
                <property name="emailAddress" type="string">
                    <column name="email_address" length="64"/>
                </property>
                <property name="primaryPhoneNumber" type="string">
                    <column name="primary_phone_number" length="32" />
                </property>
                <property name="password" type="string">
                    <column name="password" length="32"/>
                </property>
                <property name="lastUpdated" type="timestamp">
                    <column name="last_updated" not-null="true"/>
                </property>
                <property name="passwordLastChanged" type="timestamp">
                    <column name="password_last_changed" />
                </property>
            </joined-subclass>
            
            <joined-subclass name="Group" table="security_group">
                <key column="id"/>
                <property name="description" type="string">
                    <column name="description" length="1024"/>
                </property>
                <set name="membersSet" table="security_group_membership">
                    <key column="group_id"/>
                    <many-to-many class="Principal" column="principal_id"/>
                </set>
             </joined-subclass>
         </class>
    So i'm not positive, but it appears my problem is in the fact that I don't have multiple Dao operations sharing the same session/transaction. If that is the case, what is the best way to do so? This operation was working fine when I was using the AbstractTransactionalSpringContextTests class. I want to avoid using that class though, because I have other problems with it (like not being able to use beans configured with TransactionProxyFactoryBean). If not, what other blunder might you good folks be able to deduce from the information provided?

    Thanks in advance[/code]

  • #2
    Why are you demarcating transactions at the DAO tier anyway? In general, you always want to demarcate at the service tier.

    You can use AbstractTransactionalDataSourceSpringContextTests with objects configured using TPFB, the problem I imagine you were having is related to the fact that you will have two top level beans of the same type. Try making the proxy target an inner bean inside your TPFB declaration. Doing this will allow you to have your DAOs as the poxies and still have the tests work provided the propagation is set appropriately.

    Rob

    Comment

    Working...
    X