aspose file tools*
The moose likes Object Relational Mapping and the fly likes Save objects problem Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of EJB 3 in Action this week in the EJB and other Java EE Technologies forum!
JavaRanch » Java Forums » Databases » Object Relational Mapping
Bookmark "Save objects problem" Watch "Save objects problem" New topic
Author

Save objects problem

Lilly Miaqa
Greenhorn

Joined: Jan 25, 2005
Posts: 8
I have a parent class (classA) which has a set of associated objects (classB) in it. classA maps to table A, and classB maps to table B. Table B has Table A's foreign key. In the mapping file, I set the <generator> for the id in both classA and classB as 'identity' (for Microsoft Sql Server).

I've instantiated several classB objects in memory, add them to a set, and add the set to classA object. Now I want to save them to the Database. Here comes the dilemma, how will Hibernate know that it needs to save classA to table A first, so a primary key can be created (the key should be created by database because I set the generator type as 'identity'), and later can be inserted into table B as the foreign key when classB objects are saved? I did set the cascading property. It still didn't work.

Thanks.
pascal betz
Ranch Hand

Joined: Jun 19, 2001
Posts: 547
can you post your mapping files and relevant code ?

pascal
pascal betz
Ranch Hand

Joined: Jun 19, 2001
Posts: 547
oh and dont forget to read

the faq
and parent child example

pascal
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
Are you using the inverse property? If so, how is it set? Also, what's your cascade property on the <set>? Do the Bs have a reference to their owning A?. As to how Hibernate knows to save the A before the Bs, it's coded to know.

As I've set up mine (see below), I save just the A and Hibernate saves the new and modified Bs for me. Also, if you load the A, make sure that you don't replace the Set with your own. Instead, grab the Set from A and add Bs to it. This is best put into a method on A addB(B b) -- that takes a B and adds it to the internal Set.

Here's how one of my relationships is set up.
Lilly Wiesie
Greenhorn

Joined: Jan 20, 2005
Posts: 26
Hi,

Thanks for your reply. I tried several more things, still not working...
Here is the mapping files and code I used.

table1 mapping
-----------------
<class
name="com.tietronix.hibernateTest.dal.Table1"
table="Table1"
>

<id
name="table1pk"
type="java.lang.Integer"
column="table1pk"
unsaved-value="0"
>
<generator class="identity" />
</id>

<property
name="table1desc"
type="java.lang.String"
column="table1desc"
length="10"
/>

<!-- Associations -->

<!-- bi-directional one-to-many association to Table2 -->
<set
name="table2s"
lazy="true"
inverse="true"
cascade="all"
>
<key>
<column name="table1pk" />
</key>
<one-to-many
class="com.tietronix.hibernateTest.dal.Table2"
/>
</set>

</class>


table2 mapping
-----------------

<class
name="com.tietronix.hibernateTest.dal.Table2"
table="Table2"
>

<id
name="table2pk"
type="java.lang.Integer"
column="table2pk"
unsaved-value="0"
>
<generator class="identity" />
</id>

<property
name="table2desc"
type="java.lang.String"
column="table2desc"
length="10"
/>

<!-- Associations -->

<!-- bi-directional many-to-one association to Table1 -->
<many-to-one
name="table1"
class="com.tietronix.hibernateTest.dal.Table1"
not-null="true"
cascade="save-update"
>
<column name="table1pk" />
</many-to-one>

</class>


code that im running
------------------------

org.hibernate.Session session2 = HibernateUtil.currentSession();

Transaction tx = session2.beginTransaction();



Table2 tbl2_1 = new Table2();
tbl2_1.setTable2desc("GOOGLE");
Set mySet = new HashSet();
mySet.add(tbl2_1);


Table1 tbl1_1 = new Table1();
tbl1_1.setTable1desc("MSN");
tbl1_1.setTable2s(mySet);



session2.save(tbl1_1);
tx.commit();

HibernateUtil.closeSession();

error message that comes up
----------------------------------

22:10:56,471 ERROR [JDBCExceptionReporter] Cannot insert the value NULL into column 'table1pk', table 'hibernateTest.dbo.Table2'; column does not allow nulls. INSERT fails.
22:10:56,502 ERROR [Engine] StandardWrapperValve[jsp]: Servlet.service() for servlet jsp threw exception
org.hibernate.exception.ConstraintViolationException: could not insert: [com.tietronix.hibernateTest.dal.Table2]


Please help.

Lilly
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
Ah, okay. Since you are using the inverse attribute, you must set the "table1" reference from the Table2 to its owning Table1.As I recommended before, you might want to create methods like these in Table1 (in keeping with your most excellent variable-naming scheme ):One more thing, though you probably haven't hit it yet: you need to override hashCode() and equals() in Table2 since you're putting them into a HashSet. You can get away without them for a little while, depending on object identity for now, but sooner or later you'll need them.
Lilly Miaqa
Greenhorn

Joined: Jan 25, 2005
Posts: 8
Hi Dave,

Thanks for helping out.

It works. But for some reason the data won't be saved to database until I shut down the JBoss server. Do you have any idea what could happen?

Thanks,

Lilly
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
Originally posted by Lilly Miaqa:
But for some reason the data won't be saved to database until I shut down the JBoss server. Do you have any idea what could happen?
You're welcome; I'm glad to help. With this one, however, I'm stumped. I've never used JBoss, but your code looks good. You're committing the transaction (which should flush the Session) and then closing the Session. All I can think to recommend is to flush the Session explicitely.

To track it down better, I'd drop the logging level of Hibernate to DEBUG so you can check that the transaction is indeed flushing the session. You might also want to try the JBoss forum to benefit from the expertise of the people hanging out there.
Lilly Wiesie
Greenhorn

Joined: Jan 20, 2005
Posts: 26
Hi Dave,

It works after I added the session.flush(). Thanks!

Lilly
David Harkness
Ranch Hand

Joined: Aug 07, 2003
Posts: 1646
Originally posted by Lilly WS:
It works after I added the session.flush(). Thanks!
I'm very glad I could help, but that's a little scary. The Transaction should be responsible for flushing the Session since that's part of commiting ... oh wait, no I guess that makes sense. Just make sure you flush before you commit.

I use the Spring Framework in combination with Hibernate, and it supplies its own HibernateTransaction wrapper that performs the flush when you commit. I just assumed Hibernate's did the same thing.
Lilly Miaqa
Greenhorn

Joined: Jan 25, 2005
Posts: 8
Evidentaily it's not. I'll make sure I'll flush the session from now on ).

Thanks,

Lilly
 
I agree. Here's the link: http://aspose.com/file-tools
 
subject: Save objects problem
 
Similar Threads
Regarding constructors
Vectors from class to class
Object is null
one - one mapping is being enforced with unique="true"
Scope and array questions