Announcement Announcement Module
Collapse
No announcement yet.
Sping 1.1rc-1, Hibernate 2.1.5 1:1 entity saving problem Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Sping 1.1rc-1, Hibernate 2.1.5 1:1 entity saving problem

    Hi,

    I'm wondering if anyone can help with a problem I'm seeing with Spring 1.1rc-1 and Hibernate 2.1.5. I'm seeing an error when persisting an object (User) that has a 1:1 relationship with another object (UserSecurity).

    The code in the DAO class looks like:

    UserSecurity security = new UserSecurity();
    security.setPasswordType(passwordType);
    security.setPassword(password);
    security.setUser(user);
    user.setSecurity(security);
    getHibernateTemplate().save(user);

    After the .save() call, I can see a couple of debug messages which are output using the onSave() LifeCycle method for both objects, indicating that the primary key for the User is generated OK and assigned to the UserSecurity OK also. But an error then is thrown stating that the UserSecurity's user property is null, and I'm not sure how's thats possible.

    In the application context, I setup an XA datasource, and use the JTA transaction strategy along with JOTM - I think all the infrastructure bits and pieces are wired up correctly, but I can send more details if required.

    Any suggestions appreciated, hopefully I'm not doing something stupid, its my first Spring foray (which by the way I'm liking a lot, especially the AOP transaction stuff).

    Cheers,
    Joe

    The log messages are:

    ...
    2004-08-13 12:29:30,099 INFO Using dialect: net.sf.hibernate.dialect.SQLServerDialect
    2004-08-13 12:29:30,099 INFO Use outer join fetching: true
    2004-08-13 12:29:30,109 INFO Initializing connection provider: org.springframework.orm.hibernate.LocalDataSourceC onnectionProvider
    2004-08-13 12:29:30,109 INFO Transaction strategy: net.sf.hibernate.transaction.JTATransactionFactory
    2004-08-13 12:29:30,119 INFO JNDI InitialContext properties:{}
    2004-08-13 12:29:30,129 INFO instantiating TransactionManagerLookup: net.sf.hibernate.transaction.JOTMTransactionManage rLookup
    2004-08-13 12:29:30,129 INFO instantiated TransactionManagerLookup
    2004-08-13 12:29:30,129 INFO instantiating TransactionManagerLookup: net.sf.hibernate.transaction.JOTMTransactionManage rLookup
    2004-08-13 12:29:30,129 INFO instantiated TransactionManagerLookup
    2004-08-13 12:29:30,139 DEBUG StandardDataSource:getConnection a new driver instance is created
    2004-08-13 12:29:30,139 DEBUG StandardDataSource:getConnection Connection from DriverManager is returned
    2004-08-13 12:29:30,330 INFO Use scrollable result sets: true
    2004-08-13 12:29:30,330 INFO Use JDBC3 getGeneratedKeys(): true
    2004-08-13 12:29:30,330 INFO Optimize cache for minimal puts: false
    2004-08-13 12:29:30,330 INFO echoing all SQL to stdout
    2004-08-13 12:29:30,340 INFO Query language substitutions: {}
    2004-08-13 12:29:30,340 INFO cache provider: net.sf.hibernate.cache.OSCacheProvider
    2004-08-13 12:29:30,550 INFO query cache factory: net.sf.hibernate.cache.StandardQueryCacheFactory
    2004-08-13 12:29:30,560 INFO instantiating and configuring caches
    2004-08-13 12:29:30,901 INFO building session factory
    2004-08-13 12:29:32,333 INFO Not binding factory to JNDI, no JNDI name configured
    2004-08-13 12:29:32,333 INFO starting update timestamps cache at region: net.sf.hibernate.cache.UpdateTimestampsCache
    2004-08-13 12:29:32,343 INFO starting query cache at region: net.sf.hibernate.cache.StandardQueryCache
    2004-08-13 12:29:32,543 DEBUG StandardDataSource:getConnection Connection from DriverManager is returned
    2004-08-13 12:29:32,843 DEBUG Publishing event in context [x.y.z.EncryptedXmlContext;hashCode=29997514]: org.springframework.context.event.ContextRefreshed Event[source=x.y.z.EncryptedXmlContext: displayName=[x.y.z.EncryptedXmlContext;hashCode=29997514]; startup date=[Fri Aug 13 02:29:16 UTC 2004]; root of ApplicationContext hierarchy]
    2004-08-13 12:29:32,853 DEBUG StandardDataSource:getConnection Connection from DriverManager is returned
    2004-08-13 12:29:33,034 DEBUG StandardDataSource:getConnection Connection from DriverManager is returned
    [junit] Hibernate: select usr.id as id, usr.rid as rid, usr.username as username, usr.firstname as firstname, usr.lastname as
    usr.accenabled as accenabled, usr.objcreated as objcreated, usr.objcreatedby as objcreat8_, usr.objupdated as objupdated, usr.obju
    s objupda10_ from fcso_user usr where (usr.username=? )
    2004-08-13 12:29:33,264 DEBUG LOAD -> x.y.z.user.User PK:1
    2004-08-13 12:29:33,765 DEBUG SAVE -> x.y.z.user.User PK:28
    2004-08-13 12:29:33,775 DEBUG SAVE -> x.y.z.user.UserSecurity PK:28
    2004-08-13 12:29:33,785 ERROR Application exception overridden by rollback exception
    org.springframework.orm.hibernate.HibernateSystemE xception: not-null property references a null or transient value: x.y.z.user.UserSecurity.user; nested exception is net.sf.hibernate.PropertyValueException: not-null property references a null or transient value: x.y.z.user.UserSecurity.user
    net.sf.hibernate.PropertyValueException: not-null property references a null or transient value: x.y.z.user.UserSecurity.user
    at net.sf.hibernate.impl.SessionImpl.checkNullability (SessionImpl.java:1277)
    at net.sf.hibernate.impl.SessionImpl.doSave(SessionIm pl.java:928)
    at net.sf.hibernate.impl.SessionImpl.doSave(SessionIm pl.java:857)
    at net.sf.hibernate.impl.SessionImpl.saveWithGenerate dIdentifier(SessionImpl.java:779)
    at net.sf.hibernate.impl.SessionImpl.save(SessionImpl .java:738)
    at net.sf.hibernate.impl.SessionImpl.saveOrUpdate(Ses sionImpl.java:1388)
    at net.sf.hibernate.engine.Cascades$4.cascade(Cascade s.java:114)
    at net.sf.hibernate.engine.Cascades.cascade(Cascades. java:436)
    at net.sf.hibernate.engine.Cascades.cascade(Cascades. java:503)
    at net.sf.hibernate.impl.SessionImpl.doSave(SessionIm pl.java:890)
    at net.sf.hibernate.impl.SessionImpl.doSave(SessionIm pl.java:857)
    at net.sf.hibernate.impl.SessionImpl.saveWithGenerate dIdentifier(SessionImpl.java:779)
    at net.sf.hibernate.impl.SessionImpl.save(SessionImpl .java:738)
    at org.springframework.orm.hibernate.HibernateTemplat e$11.doInHibernate(HibernateTemplate.java:296)
    at org.springframework.orm.hibernate.HibernateTemplat e.execute(HibernateTemplate.java:176)
    at org.springframework.orm.hibernate.HibernateTemplat e.save(HibernateTemplate.java:293)
    at x.y.z.user.UserDaoImpl.addUser(UserDaoImpl.java:39 )
    at x.y.z.user.UserManager.addUser(UserManager.java:32 )
    at x.y.z.user.UserManager$$FastClassByCGLIB$$c0c27833 .invoke(<generated>)
    at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy. java:149)
    at org.springframework.aop.framework.Cglib2AopProxy$M ethodInvocationImpl.invokeJoinpoint(Cglib2AopProxy .java:913)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :120)
    at org.springframework.transaction.interceptor.Transa ctionInterceptor.invoke(TransactionInterceptor.jav a:57)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :140)
    at org.springframework.aop.framework.Cglib2AopProxy$D ynamicAdvisedInterceptor.intercept(Cglib2AopProxy. java:628)
    at x.y.z.user.UserManager$$EnhancerByCGLIB$$c7b71a93. addUser(<generated>)
    at x.y.z.data.test.UserVMTest.testUserCreate(UserVMTe st.java:76)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:324)
    at junit.framework.TestCase.runTest(TestCase.java:154 )
    ...

    And the relevant context definition is:

    <?xml version="1.0" encoding="UTF-8"?>

    <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

    <beans>
    <bean id="dataTransactionManager"
    class="org.springframework.transaction.jta.JtaTran sactionManager">
    <property name="transactionManager"><ref bean="transactionManager"/></property>
    <property name="userTransactionName"><value>java:comp/UserTransaction</value></property>
    </bean>

    <bean id="userDao" class="x.y.z.user.UserDaoImpl">
    <property name="sessionFactory">
    <ref bean="sf-system"/>
    </property>
    </bean>

    <bean id="userManagerTarget" class="x.y.z.user.UserManager">
    <property name="userDao">
    <ref bean="userDao"/>
    </property>
    </bean>

    <bean id="userManager"
    class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
    <property name="transactionManager">
    <ref bean="dataTransactionManager"/>
    </property>
    <property name="target">
    <ref bean="userManagerTarget"/>
    </property>
    <property name="transactionAttributes">
    <props>
    <prop key="addUser">PROPAGATION_REQUIRED</prop>
    <prop key="saveUser">PROPAGATION_REQUIRED</prop>
    <prop key="deleteUser">PROPAGATION_REQUIRED</prop>
    </props>
    </property>
    </bean>
    </beans>

  • #2
    smokinjoe,

    Could you provide the Hibernate mapping for your classes?

    Comment


    • #3
      Sure, included below, though I've snipped out basic properties and queries. They both use the 2.0 DTD. I wasn't sure if it'd be the Hibernate mappings as they'd previously worked OK pre-Spring, but admittedly I've fiddled since also to enable lazy loading of the 1:1.

      Cheers,
      Joe

      <hibernate-mapping>
      <class name="x.y.z.user.User" table="fcso_user" proxy="x.y.z.user.User"
      dynamic-update="true" dynamic-insert="true">
      <cache usage="read-write" />
      <id name="id" type="java.lang.Integer" unsaved-value="null">
      <column name="id"/>
      <generator class="x.y.z.data.GeneratorIID"><param name="sequence">fcso_user</param></generator>
      </id>
      <version name="versionID" type="java.lang.Long" column="rid" access="property" unsaved-value="undefined"/>
      ... other properties ...
      <one-to-one name="security" class="x.y.z.user.UserSecurity" cascade="all" outer-join="false" constrained="true"/>
      </class>
      ... queries ...
      </hibernate-mapping>

      <hibernate-mapping>
      <class name="x.y.z.user.UserSecurity" table="fcso_user_sec" proxy="x.y.z.user.UserSecurity"
      dynamic-update="true" dynamic-insert="true">
      <cache usage="read-write"/>
      <id name="id" type="java.lang.Integer" unsaved-value="null">
      <column name="id"/>
      <generator class="foreign"><param name="property">user</param></generator>
      </id>
      <version name="versionID" type="java.lang.Long" column="rid" access="property" unsaved-value="undefined"/>
      <one-to-one name="user" class="x.y.z.user.User" cascade="none" outer-join="false" constrained="true"/>
      ... other basic properties ...
      </class>
      </hibernate-mapping>

      Comment


      • #4
        smokinjoe,

        I think you should remove the attribute constrained="true" from User reference to UserSecurity. The mapping should read:

        Code:
         <hibernate-mapping>
            <class name="x.y.z.user.User" table="fcso_user" proxy="x.y.z.user.User" dynamic-update="true" dynamic-insert="true"> 
              <cache usage="read-write" /> 
              <id name="id" type="java.lang.Integer" unsaved-value="null"> 
                <column name="id"/> 
                <generator class="x.y.z.data.GeneratorIID"><param name="sequence">fcso_user</param></generator> 
              </id> 
              <version name="versionID" type="java.lang.Long" column="rid" access="property" unsaved-value="undefined"/> 
        ... other properties ... 
              <!-- change this line -->
              <one-to-one name="security" class="x.y.z.user.UserSecurity" cascade="all" outer-join="false" />
            </class> 
        ... queries ... 
        </hibernate-mapping>
        I already tried this mapping with Spring Framework 1.1 from CVS and Hibernate 2.1.7 (from CVS too) and it worked perfectly (saveOrUpdate, get, load and delete).

        For more information, please take a look at Hibernate Documentation
        For a primary key association, add the following mappings to Employee and Person, respectively.

        Code:
        <one-to-one name="person" class="Person"/>
        <one-to-one name="employee" class="Employee" constrained="true"/>

        Comment


        • #5
          Hibernate in CVS btw is the current 2.1.6, which fixes some bugs introduced with 2.1.5.

          Regards,

          Comment


          • #6
            Colin,

            I am sorry for the confusion. I mean by CVS the Hibernate CVS not the Spring FrameWork one's.
            I also think smokinjoe code would run as well on Spring 1.1 RC1 and Hibernate 2.1.6. I didn't test it with these versions however.

            Comment


            • #7
              OK, thanks very much guys, the constrained="true" on the 'parent' side of the 1:1 was exactly the problem, sorry for the noise, its working very well now 8). It was a long day, I'll check my Hibernate mappings more closely before assuming its a Spring thing in future.

              Cheers,
              Joe

              Comment

              Working...
              X