-->
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.  [ 8 posts ] 
Author Message
 Post subject: many-to-many problem: no entries saved in join table
PostPosted: Tue Oct 12, 2004 9:23 pm 
Newbie

Joined: Sun Sep 19, 2004 12:22 am
Posts: 6
I'm trying to write data to a three tables that form a many to many relationship: books, authors, and author_book (the join table). My problem is that hibernate is not writing to author_books. Thus loosing the association between the books and their authors.

SchemaExport creates the tables correctly (shown below). I create a few Book objects and assign Authors to them, then try calling session.saveOrUpdate(book); The book saves fine, the associated Authors save fine, but the join table remains empty. Hibernate does not attempt to write any rows to the join table, only the other two.

If I set values in the join table by hand, hibernate reads the books (and associated Authors) just fine.

Any idea as to what could cause this? Sorry if this is a clueless newbie question, but I'm getting totally frustrated. Any help would be appreciated! Even an RTFM if it said which part of the FM to R.

I started poking around in the source for SessionImpl, and confirmed that Cascades.cascade(...) is indeed being called (hence why the authors are written out OK). But I can't figure out which part of the code would write to a join table. Pointers to the method responsible for that would be appreciated.

Maybe I'm just expecting the wrong thing. Do I have to make an explicit association object in my object model and persist that?

Thanks,

-chris




Hibernate version: Hibernate 2.1.6

Mapping documents:

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping package="cbare.books">

   <class name="Book" table="books">
      <id name="id" unsaved-value="null">
         <generator class="native"/>
      </id>
      <property name="title" not-null="true"/>
      <property name="isbn"/>
      <set name="authors" table="author_book" cascade="save-update" inverse="false">
            <key>
                <column name="book_id" not-null="true"/>
            </key>
            <many-to-many class="Author">
                <column name="author_id" not-null="true"/>
            </many-to-many>
      </set>
   </class>

</hibernate-mapping>


Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping package="cbare.books">

   <class name="Author" table="authors">
      <id name="id" unsaved-value="null">
         <generator class="native"/>
      </id>
      <property name="firstName"/>
      <property name="lastName"/>
        <set name="books" table="author_book">
            <key column="author_id"/>
            <many-to-many class="Book" column="book_id"/>
        </set>
   </class>
      
</hibernate-mapping>


Name and version of the database you are using:
mySql 4.0.15-nt mysql-connector-java-3.0.9

Code:
mysql> show tables;
+-----------------+
| Tables_in_books |
+-----------------+
| author_book     |
| authors         |
| books           |
+-----------------+
3 rows in set (0.00 sec)

mysql> describe authors;
+-----------+--------------+------+-----+---------+----------------+
| Field     | Type         | Null | Key | Default | Extra          |
+-----------+--------------+------+-----+---------+----------------+
| id        | bigint(20)   |      | PRI | NULL    | auto_increment |
| firstName | varchar(255) | YES  |     | NULL    |                |
| lastName  | varchar(255) | YES  |     | NULL    |                |
+-----------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql> describe books;
+-------+--------------+------+-----+---------+----------------+
| Field | Type         | Null | Key | Default | Extra          |
+-------+--------------+------+-----+---------+----------------+
| id    | bigint(20)   |      | PRI | NULL    | auto_increment |
| title | varchar(255) |      |     |         |                |
| isbn  | varchar(255) | YES  |     | NULL    |                |
+-------+--------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)

mysql> describe author_book;
+-----------+------------+------+-----+---------+-------+
| Field     | Type       | Null | Key | Default | Extra |
+-----------+------------+------+-----+---------+-------+
| author_id | bigint(20) |      | PRI | 0       |       |
| book_id   | bigint(20) |      | PRI | 0       |       |
+-----------+------------+------+-----+---------+-------+
2 rows in set (0.01 sec)


The generated SQL (show_sql=true):

Code:
Hibernate: insert into books (title, isbn) values (?, ?)
Hibernate: insert into authors (firstName, lastName) values (?, ?)
Hibernate: insert into authors (firstName, lastName) values (?, ?)


I was expecting to see a 'insert into author_book (author_id, book_id) values(?, ?)' here.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 12, 2004 10:50 pm 
Regular
Regular

Joined: Tue Sep 09, 2003 9:37 pm
Posts: 56
Location: Ogden, Utah, USA
Well, you definitely don't have to make an explicit association object.

Here's what mine look like...

<set name="authors" table="author_book" lazy="true">
<key column="book_id"/>
<many-to-many column="author_id" class="Author"/>
</set>

(the tablenames have been changed to make it look more like your example. :) )

Good Luck!
Jenica


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 13, 2004 3:21 pm 
Beginner
Beginner

Joined: Tue Sep 21, 2004 1:49 pm
Posts: 33
Location: Bogota, Colombia
I'm having the same problem, hibernate is not inserting any records in the association table in the middle..

Have you been able to do it? what lines of code did you use?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 13, 2004 3:39 pm 
Newbie

Joined: Tue Jun 01, 2004 12:33 pm
Posts: 6
cbare --

It looks like you're trying to map a bi-directional relationship (A book has a set of authors, and an author has a set of books).

In the Book.hbm.xml file, you have the property inverse="false". I believe you want that to be inverse="true". One of the ends of the bi-directional relationship must be set to inverse="true".

I can't say if that will fix your problem or not, but that is definitely not want you want in your mapping file.

Let us know if you get it working.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 13, 2004 5:20 pm 
Newbie

Joined: Wed Jul 28, 2004 6:13 pm
Posts: 12
Just to add my 2 cents. I had a question related to many-to-many relationships and found this thread. I used it as an example to get me kick-started in the right direction.

Just to confirm.. after following this example I had the same problem. The data in the join table wasn't being saved. I modified my mapping like TealWren mentioned and BAM. I got data in the join table :)

Thanks TealWren!


Top
 Profile  
 
 Post subject: Still hosed
PostPosted: Wed Oct 13, 2004 5:36 pm 
Newbie

Joined: Sun Sep 19, 2004 12:22 am
Posts: 6
I tried just about every combinatoric possibility of inverse="true" and inverse="false" (which should be redundant as it is the default). No luck.

I actually don't think the problem is with the mapping files (although I'm a clueless newbie and could be wrong) because the mapping files are so similar to the examples. Also, SchemaExport correctly creates the tables, so they can't be that far off.

I think the problem might have something to do with how I'm using my POJOs. I think something is causing hibernate's interceptors to fail. For example check this code snippet out:

Code:
        Session session = null;
        try {
            session = factory.openSession();
           
           Author ha = new Author("Harold", "Abelson");
           Author gjs = new Author("Gerald Jay", "Sussman");
           Book sicp = new Book(
                   "Structure and Interpretation of Computer Programs - 2nd Ed.",
                   "0262011530");

           sicp.addAuthor(ha);
           sicp.addAuthor(gjs);

           session.saveOrUpdate(sicp);
        }
        finally {
            if (session!=null) session.close();
        }


This results in the book being written to the db, both authors being written and nothing in the join table, via the following SQL:

Code:
Hibernate: insert into books (title, isbn) values (?, ?)
Hibernate: insert into authors (firstName, lastName) values (?, ?)
Hibernate: insert into authors (firstName, lastName) values (?, ?)


Now, it gets more interesting when I try this:

Code:
        Session session = null;
        try {
            session = factory.openSession();
           
           Author ha = new Author("Harold", "Abelson");
           Author gjs = new Author("Gerald Jay", "Sussman");
           Book sicp = new Book(
                   "Structure and Interpretation of Computer Programs - 2nd Ed.",
                   "0262011530");
           session.saveOrUpdate(sicp);
           System.out.println("after first save!");

           sicp.addAuthor(ha);
           sicp.addAuthor(gjs);

           session.saveOrUpdate(sicp);
        }
        finally {
            if (session!=null) session.close();
        }


or even this:
Code:
        Session session = null;
        try {
            session = factory.openSession();
           
           Author ha = new Author("Harold", "Abelson");
           Author gjs = new Author("Gerald Jay", "Sussman");
           Book sicp = new Book(
                   "Structure and Interpretation of Computer Programs - 2nd Ed.",
                   "0262011530");
           session.saveOrUpdate(sicp);
           System.out.println("after first save!");

           sicp.addAuthor(ha);
           sicp.addAuthor(gjs);
           sicp.setTitle("Structure and Interpretation of Computer Programs - 2nd Edition");

           session.saveOrUpdate(sicp);
        }
        finally {
            if (session!=null) session.close();
        }


Both result in the following output, and situation in the DB:

Code:
Hibernate: insert into books (title, isbn) values (?, ?)
after first save!


Code:
mysql> select * from books; select * from authors; select * from book_author;
+---------+-------------------------------------------------------------+------------+
| book_id | title                                                       | isbn       |
+---------+-------------------------------------------------------------+------------+
|       1 | Structure and Interpretation of Computer Programs - 2nd Ed. | 0262011530 |
+---------+-------------------------------------------------------------+------------+
1 row in set (0.00 sec)

Empty set (0.00 sec)

Empty set (0.00 sec)



Note that there is just one write to the DB. Even the update to the title field is not persisted. So, maybe this is a clue about the root of the problem. It looks to me like the interceptors that do dirty checking are somehow not in place or are not working. And maybe those interceptors are also involved in persisting collection information.

I'm guessing that hibernate is supposed to do some byte-code mojo the first time a persistent object is written to the DB, but somehow its failing to do so in my situation.

This is driving me nutty! My kindom for a clue! Sadly my kingdom does not amount to very much, and I was hopelessly nutty to begin with, but still...

Thanks for the replies.

-chris


Top
 Profile  
 
 Post subject: Solution found
PostPosted: Thu Oct 14, 2004 3:17 am 
Newbie

Joined: Sun Sep 19, 2004 12:22 am
Posts: 6
Oh, laugh away, fat boy. Laugh all you want to.

The solution to my problem is this:

Code:
          session.flush();
          session.connection().commit();



The moral of the story? DON'T FORGET TO FLUSH!

See section "9.7.3. Closing the Session" of the reference docs.

Picture me jumping up and down cursing like a longshoreman while hitting myself on the head with a boot. Thanks to those that helped.


Top
 Profile  
 
 Post subject: One more question..
PostPosted: Thu Oct 14, 2004 7:53 pm 
Beginner
Beginner

Joined: Tue Sep 21, 2004 1:49 pm
Posts: 33
Location: Bogota, Colombia
Glad you made it work!

My simple question: Must the many-to-many relationship be mapped in both classes for it to work (insert records in the table at the middle)? I really dont need one of the associations (in my model it would be too heavy for the database at production time, since is a "constants" table that is referenced from everywhere in the model)..


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 8 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.