-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 
Author Message
 Post subject: why can't someone answer this question?
PostPosted: Mon Aug 13, 2007 2:53 pm 
Newbie

Joined: Wed May 30, 2007 4:14 pm
Posts: 15
PROBLEM: I have a struts form. Once the request is sent, I take the form and break it down into two classes. Soldier and Address. Each soldier has 1 to many addresses. The database has one table for Soldiers and one table for Addresses. The Soldier PK is the FK in the Addresses table. The Soldier POJO has a Set of Address Objects. I want to persist the Soldier, but the FK does not get set the Address object. So.....

SOLDIER
-soldierID
-firstName
-lastName
-Addresses (Set)

ADDRESS
-addressID
-soldierID
-line1
-line2
..etc

I want to take the Soldier object (with its set of addresses) and persist it to the db. In my mind, the FK should be populated automatically when the Soldier is entered. Please, any help at all or at least a comment would be nice. Thanks in advance for any time spent looking at this.


Hibernate version:3.2

Mapping documents:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.ourdomain.user.Soldier" table="USERNAME">
        <id name="soldierId" type="long" column="USERNAME_ID">
            <generator class="com.ourdomain.dao.hibernate.TriggerAssignedIdentityGenerator"/>
        </id>
        <property name="akoEmail" type="string" column="EMAIL_TX"/>
        <property name="firstName" type="string" column="FIRST_NAME_TX"/>
        <property name="lastName" type="string" column="LAST_NAME_TX"/>
        <property name="dateOfBirth" type="date" column="DOB_DT"/>
        <property name="status" type="string" column="STATUS_CD"/>
        <property name="createdBy" type="string" column="CREATE_BY"/>
        <property name="createdDate" type="date" column="CREATE_DT"/>
        <property name="modifiedDate" type="date" column="MOD_DT"/>
        <property name="modBy" type="string" column="MOD_BY"/>
        <property name="password" type="string" column="PASSWORD_TX"/>
        <set name="addresses" lazy="true" inverse="true" cascade="save-update">
            <key column="soldierId" not-null="true"/>
            <one-to-many class="com.ourdomain.user.Address"/>
        </set>
    </class>
    <class name="com.ourdomain.user.Address" table="ADDRESS">
        <id name="addressId" type="long" column="ADDRESS_ID">
            <generator class="com.ourdomain.dao.hibernate.TriggerAssignedIdentityGenerator"/>
        </id>
        <many-to-one name="soldierId" class="com.ourdomain.user.Soldier" column="USERNAME_ID" insert="true" update="true"/>
        <property name="address1" type="string" column="ADDRESS1_TX"/>
        <property name="address2" type="string" column="ADDRESS2_TX"/>
        <property name="city" type="string" column="CITY_TX"/>
        <property name="state" type="string" column="STATE_CD"/>
        <property name="zipCode" type="string" column="ZIP_CD"/>
        <property name="phoneNumber" type="string" column="PHONE_NUMBER_TX"/>
        <property name="createdBy" type="string" column="CREATE_BY"/>
        <property name="createdDate" type="date" column="CREATE_DT"/>
        <property name="modifiedDate" type="date" column="MOD_DT"/>
        <property name="modifiedBy" type="string" column="MOD_BY"/>
    </class>
</hibernate-mapping>


breaking form into two objects and calling DAO
Code:
Soldier newSoldier = new Soldier(regForm.getFirstName().trim(),regForm.getLastName().trim(),
                regForm.getEmailAddress().trim(),DOB,regForm.getPhoneNumber().trim());
        Address newAddress = new Address(regForm.getAddress1().trim(),regForm.getAddress2().trim(),
                regForm.getCity().trim(),regForm.getState().trim(),regForm.getZipCode().trim(),regForm.getPhoneNumber());

        Set<Address> addressSet = new HashSet<Address>();
        addressSet.add(newAddress);
        newSoldier.setAddresses(addressSet);
        dao.addPerson(newSoldier);

DAO Class:
Code:
public void addPerson(Soldier soldier) {
        Session session = getSession();
        try {
            logger.log(Level.SEVERE,"Pass #1" + soldier.toString());
            session.save(soldier);
            logger.log(Level.SEVERE,"Pass #2" + soldier.toString());

        } catch (HibernateException he) {
            he.printStackTrace();
            logger.log(Level.SEVERE, "Error upon insert: " + he.getMessage(), he);

        }
        finally {
            if (session != null) {
                try {
                    session.close();
                } catch (HibernateException e) {
                    e.printStackTrace();
                }
            }
        }
    }

Full stack trace of any exception that occurs:
Aug 13, 2007 12:53:00 PM - SEVERE - com.ourdomain.dao.hibernate.HibernateTempRegistrationDao.addPerson(): Pass #1My Soldiers Primary Key: 0
My Soldier's Name: John Doe
My Soldier's DOB: Wed Jan 01 00:00:00 EST 1964
My Soldier's Password: password
My Soldier's CreateDate: Wed Dec 31 19:00:01 EST 1969
My Soldier's ModifiedDate: Wed Dec 31 19:00:01 EST 1969
My Soldier was created by: me
My Soldier was modifiedby: me
My Soldier's status: A
My Soldier's Address: 123 Paradise Ln
My Soldier's Address PK: 0
My Soldier's City: Long Beach
My Soldier's State: MS
My Soldier's Zip: 39560
My Soldier's Phone Number: 555-555-5555

Aug 13, 2007 12:53:01 PM - SEVERE - com.ourdomain.dao.hibernate.HibernateTempRegistrationDao.addPerson(): Error upon insert: IllegalArgumentException occurred calling getter of com.ourdomain.user.Soldier.soldierId
org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of com.ourdomain.user.Soldier.soldierId
at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:171)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.getIdentifier(AbstractEntityTuplizer.java:183)
at org.hibernate.persister.entity.AbstractEntityPersister.getIdentifier(AbstractEntityPersister.java:3589)
at org.hibernate.persister.entity.AbstractEntityPersister.isTransient(AbstractEntityPersister.java:3305)
at org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:181)
at org.hibernate.engine.ForeignKeys$Nullifier.isNullifiable(ForeignKeys.java:137)
at org.hibernate.engine.ForeignKeys$Nullifier.nullifyTransientReferences(ForeignKeys.java:69)
at org.hibernate.engine.ForeignKeys$Nullifier.nullifyTransientReferences(ForeignKeys.java:47)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:288)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:94)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSaveOrUpdate(SessionImpl.java:507)
at org.hibernate.impl.SessionImpl.saveOrUpdate(SessionImpl.java:499)
at org.hibernate.engine.CascadingAction$1.cascade(CascadingAction.java:218)
at org.hibernate.engine.Cascade.cascadeToOne(Cascade.java:268)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:216)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascadeCollectionElements(Cascade.java:296)
at org.hibernate.engine.Cascade.cascadeCollection(Cascade.java:242)
at org.hibernate.engine.Cascade.cascadeAssociation(Cascade.java:219)
at org.hibernate.engine.Cascade.cascadeProperty(Cascade.java:169)
at org.hibernate.engine.Cascade.cascade(Cascade.java:130)
at org.hibernate.event.def.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:456)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:334)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:107)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:27)
at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:535)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:523)
at org.hibernate.impl.SessionImpl.save(SessionImpl.java:519)
at com.ourdomain.dao.hibernate.HibernateTempRegistrationDao.addPerson(HibernateTempRegistrationDao.java:50)
at com.ourdomain.struts.action.TempRegistrationAction.execute(TempRegistrationAction.java:76)
at org.springframework.web.struts.DelegatingActionProxy.execute(DelegatingActionProxy.java:106)

Name and version of the database you are using:
Oracle 10G
[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 13, 2007 3:15 pm 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
You've defined a bi-directional relationship between soldier and address. Hibernate only uses one end of the relationship to persist the soldier id in the address table. Your mapping files indicate that the address object is the master of this relationship (soldier.addresses has inverse="true" making it the slave end). So you need to set the soldier field of the address objects for this to work. Or, change the master end by swapping the inverse="true" from soldier to address.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 13, 2007 3:24 pm 
Newbie

Joined: Wed May 30, 2007 4:14 pm
Posts: 15
I only created a bi-directional because someone on another forum told me I had to. I simply want to persist the soldier object and have the set of addresses associated with it.

I removed the inverse="true" to no avail. Any other suggestions?

Thanks for the reply!!! ;)


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 13, 2007 3:55 pm 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
If you never navigate from address to soldier then remove the many-to-one mapping from address. Otherwise, set the many-to-one mapping to inverse="true" or call address.setSoldier(soldier) before you save.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 13, 2007 4:08 pm 
Newbie

Joined: Wed May 30, 2007 4:14 pm
Posts: 15
My new mapping doc look like:
Code:
<hibernate-mapping>
    <class name="com.ourdomain.user.Soldier" table="USERNAME">
        <id name="soldierId" type="long" column="USERNAME_ID">
            <generator class="com.ourdomain.dao.hibernate.TriggerAssignedIdentityGenerator"/>
        </id>
        <property name="akoEmail" type="string" column="EMAIL_TX"/>
        <property name="firstName" type="string" column="FIRST_NAME_TX"/>
        <property name="lastName" type="string" column="LAST_NAME_TX"/>
        <property name="dateOfBirth" type="date" column="DOB_DT"/>
        <property name="status" type="string" column="STATUS_CD"/>
        <property name="createdBy" type="string" column="CREATE_BY"/>
        <property name="createdDate" type="date" column="CREATE_DT"/>
        <property name="modifiedDate" type="date" column="MOD_DT"/>
        <property name="modBy" type="string" column="MOD_BY"/>
        <property name="password" type="string" column="PASSWORD_TX"/>
        <set name="addresses" table="ADDRESS">
            <key column="soldierId" not-null="true"/>
            <one-to-many class="com.ourdomain.user.Address"/>
        </set>
    </class>
    <class name="com.ourdomain.user.Address" table="ADDRESS">
        <id name="addressId" type="long" column="ADDRESS_ID">
            <generator class="com.ourdomain.dao.hibernate.TriggerAssignedIdentityGenerator"/>
        </id>
        <property name="address1" type="string" column="ADDRESS1_TX"/>
        <property name="address2" type="string" column="ADDRESS2_TX"/>
        <property name="city" type="string" column="CITY_TX"/>
        <property name="state" type="string" column="STATE_CD"/>
        <property name="zipCode" type="string" column="ZIP_CD"/>
        <property name="phoneNumber" type="string" column="PHONE_NUMBER_TX"/>
        <property name="createdBy" type="string" column="CREATE_BY"/>
        <property name="createdDate" type="date" column="CREATE_DT"/>
        <property name="modifiedDate" type="date" column="MOD_DT"/>
        <property name="modifiedBy" type="string" column="MOD_BY"/>
    </class>
</hibernate-mapping>


Still to no avail. Here is my code calling session.save();

Code:
session.save(soldier);
            Set<Address> addressSet = new HashSet<Address>();
            address.setSoldierId(soldier.getSoldierId());
            addressSet.add(address);
            soldier.setAddresses(addressSet);
            session.save(soldier);


Nasty I know, but, I'm saving the soldier first so I can get the PK ID - which is driven by a trigger on the Soldier table calling a sequence. Then I add the soldierID to the address....add the address to the set, add the set to the soldier. All of those are steps I would think the mappings should take care of...but this still does not work.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Aug 13, 2007 5:13 pm 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
With this uni-directional relationship you don't need to set the soldierId on address in java. Infact, you don't need the get/set for soldier id at all - hibernate will do the work for you.

I don't know how to setup trigger based ids on mysql. Using increment ids though it works fine as long as I specify cascade="save-update" on the addresses set. If I don't I get an error about references to an unsaved transient. Try adding this and see if it works.

If not, post the generated sql.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 14, 2007 9:37 am 
Newbie

Joined: Wed May 30, 2007 4:14 pm
Posts: 15
I added <set name="addresses" table="ADDRESS" cascade="save-update"> and still the same thing. My log entry was the following:
Code:
Aug 14, 2007 9:41:11 AM - SEVERE - com.ourdomain.dao.hibernate.HibernateTempRegistrationDao.addPerson(): Error upon insert: not-null property references a null or transient value: com.ourdomain.user.Address._addressesBackref
org.hibernate.PropertyValueException: not-null property references a null or transient value: com.ourdomain.user.Address._addressesBackref
        at org.hibernate.engine.Nullability.checkNullability(Nullability.java:72)
        at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:290)


I don't have any generated SQL because apparently there is a problem generating SQL with Oracle inserts with the current drivers?! I dunno.... But, the trigger assigned id had to be handled by a new class I found online. I do verify in debug that once the soldier is persisted, it does have a valid ID that was generated by the db.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 14, 2007 9:47 am 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
Try setting not-null="true" on the key column of the addresses set.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 14, 2007 9:51 am 
Newbie

Joined: Wed May 30, 2007 4:14 pm
Posts: 15
it already was, looked like this:

<set name="addresses" table="ADDRESS" cascade="save-update">
<key column="soldierId" not-null="true"/>
<one-to-many class="com.futuresoldiers.user.Address"/>
</set>


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.