-->
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.  [ 2 posts ] 
Author Message
 Post subject: many-to-many problem (object A correct, object B not?!)
PostPosted: Mon Oct 29, 2007 1:31 pm 
Newbie

Joined: Sat Oct 15, 2005 5:45 pm
Posts: 18
Hi all,

This is for sure a newbie question, but I could do with some help. I have a Game class and a Category class with a many-to-many table used so that a game can have many categories and vice-versa.

When I store the game, it shows that the categories are populated (via the debug, plus the database tables are populate properly), but when I retrieve the categories they don't have the games populated.

I intend to always add the category information directly to the game object, but think it will be useful to iterate through categories to see what games are in that category. To achieve this I have determine that the category has the 'inverse' keyword (since I will not be adding entities to this directly) and therefore the game one doesn't have the inverse attribute.

Additionally, I have the cascade on both set to 'save-update', although I *think* maybe I only need it on Game?

What am I missing?! Any tips will be appreciated.

Here's the debug output
Code:
17:08:04,848 DEBUG Printer:83 - listing entities:
17:08:04,848 DEBUG Printer:90 - com.ciderbob.common.User{id=8, email=adminUser, administrator=true, dob=29 October 2007, name=null, password=null}
17:08:04,849 DEBUG Printer:90 - com.ciderbob.common.Category{id=2, games=[], name=Category1}
17:08:04,849 DEBUG Printer:90 - com.ciderbob.common.Game{id=1, visible=true, description=This is game 1, name=Game1, categories=[com.ciderbob.common.Category#1, com.ciderbob.common.Category#2], purchasePrice=9.99}
17:08:04,849 DEBUG Printer:90 - com.ciderbob.common.Category{id=1, games=[], name=Category2}


The Game mapping file
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 package="com.ciderbob.common">

  <class name="Game" table="game">
 
        <id name="id" column="game_id">
            <generator class="native"/>
        </id>
       
        <property name="name" type="string" column="name" unique="true"/>
        <property name="visible" type="boolean" column="visible"/>
        <property name="purchasePrice" type="double" column="price"/>
        <property name="description" type="string" column="description"/>

        <set name="categories" table="GAME_CATEGORY" cascade="save-update">
           <key column="game_id"/>
           <many-to-many column="category_id" unique="true" class="Category"/>
        </set>

  </class>
</hibernate-mapping>


The category mapping file
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 package="com.ciderbob.common">

  <class name="Category" table="category">
 
        <id name="id" column="category_id">
            <generator class="native"/>
        </id>
       
        <property name="name" type="string" column="name" unique="true"/>

        <set name="games" table="GAME_CATEGORY" inverse="true" cascade="save-update">
           <key column="category_id" />
           <many-to-many column="game_id" class="Game"/>
        </set>
       
  </class>
</hibernate-mapping>


Here's my test harness code...

Code:
Game game = new Game("Game1","This is game 1",true,new Double(9.99));
log.debug("game id before:"+game.getId());
session.save(game);
log.debug("game id after:"+game.getId());
game.getCategories().add(new Category("Category1"));
game.getCategories().add(new Category("Category2"));
session.save(game);

// Now check the game exists and that when
// retrieved back out of the database it contains
// the two categories
Criteria criteria = session.createCriteria(Game.class);
criteria.add(Expression.eq("name", "Game1"));
List results = criteria.list();
assertEquals(results.size(),1);
Game retrievedGame = (Game) results.get(0);
assertEquals("Game1", retrievedGame.getName());
assertEquals(2, retrievedGame.getCategories().size());

// Then perform a query for all categories, check that
// Category1 and Category2 exists.
criteria = session.createCriteria(Category.class);
criteria.add(Expression.eq("name", "Category1"));
results = criteria.list();
assertEquals(1, results.size());

criteria = session.createCriteria(Category.class);
criteria.add(Expression.eq("name", "Category2"));
results = criteria.list();
assertEquals(1, results.size());

// Now check that the category has restored the
// bi-directional reference to the game
Category restoredCategory = (Category) results.get(0);
Set<Game> games = restoredCategory.getGames();
assertEquals(1, games.size()); // << FAILS


Top
 Profile  
 
 Post subject: Sorted it!
PostPosted: Mon Oct 29, 2007 5:16 pm 
Newbie

Joined: Sat Oct 15, 2005 5:45 pm
Posts: 18
Ok, I'm obviously still learning, but I tracked it down to the JUnit test being wrong.

It appears that I was trying to create the game and two categories, followed by reading the 'categories' whilst in the same transaction block. I guess the 'category' entities in the database were not written until the commit had taken place?!

Here's what I changed it to...

(Can someone please explain why I couldn't do this in a single transaction block??!)

Cheers,
Rob.

Transaction part 1
Code:
Game game = new Game("Game1","This is game 1",true,new Double(9.99));
log.debug("game id after:"+game.getId());
game.getCategories().add(new Category("Category1"));
game.getCategories().add(new Category("Category2"));
session.save(game);

// Now check the game exists and that when
// retrieved back out of the database it contains
// the two categories
Criteria criteria = session.createCriteria(Game.class);
criteria.add(Expression.eq("name", "Game1"));
List results = criteria.list();
assertEquals(results.size(),1);
Game retrievedGame = (Game) results.get(0);
assertEquals("Game1", retrievedGame.getName());
assertEquals(2, retrievedGame.getCategories().size());

// Then perform a query for all categories, check that
// Category1 and Category2 exists.
criteria = session.createCriteria(Category.class);
criteria.add(Expression.eq("name", "Category1"));
results = criteria.list();
assertEquals(1, results.size());


Transaction part 2
Code:
Category category = (Category) session.createCriteria(Category.class)
   .add(Expression.eq("name", "Category2"))
   .uniqueResult();
assertNotNull(category);
Set<Game> games = category.getGames();
assertEquals(1, games.size());
Game restoredGame = games.iterator().next();
assertEquals("Game1",restoredGame.getName());


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