-->
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.  [ 6 posts ] 
Author Message
 Post subject: Need Understanding : one class - many tables
PostPosted: Tue Aug 07, 2007 2:33 pm 
Newbie

Joined: Tue Aug 07, 2007 12:00 pm
Posts: 3
Trying to understand how to apply what I need with Hibernate.

I have four tables that are related (one-to-many, many-to-many). Is it best practice to have a class per table then have a class that inherits from all of them? Can/Should I just create a class that reads/writes to all tables and somehow define this kluge into a mapping?

For the most part, I am trying to access four tables from a Session Bean and do not want to have to access four classes (i.e., four tables) from the SessionFactory. Is this doable? More specifically, does this make sense?

I have read the docs and I do apologize if the information is in there but I just can't seem to find it.

Thanks for any help provided


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 07, 2007 3:49 pm 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
Depends on the tables and how they relate to your java classes/domain model. Can you provide a more detailed description.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 07, 2007 4:56 pm 
Newbie

Joined: Tue Aug 07, 2007 12:00 pm
Posts: 3
Sure.

Cannot talk about my specific case due to sensitivity, but an example might be:

Task table with an id and name
DoTHis table with task_id, doThis_id, and doThis_name
DoThat table with task_id, doThat_id, and doThat_name

I would like to get a Task Object when requested from a Session Bean (i.e. getTask(id)) that would return all Tasks with the id passed WITH all the DoThis and DoThat related data to the task.

As far as the tables are concerned, there will be at most a few results on the Task and upto a thousand results on the DoThis and DoThat tables.

Thanks again for the help.

BTW, the example in the Chapter 1 Introduction to Hibernate is close to what I imaged would be the solution but it looks like (at least in my case) I would be creating the desired Object from within my Session Bean. Again, I would rather have a getTask(id) method from the Session Bean if logical. If it doesn't make sense that's fine. I just need someone to tell me it doesn't.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Aug 07, 2007 8:01 pm 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
So a Task has both DoThis and DoThat items associated with it. Are they as similar in real life as in your example? It would affect how you mapped them. Lets assume that they are different enough to warrant 2 unrelated classes and 2 separate tables.

For now I'll also assume the relationship between Task and DoThis/DoThat is one to many (you don't specify). Here's some example code and mappings... DoThisCollection and DoThatCollection will be lazy loaded by default.

DoThat.java
Code:
package test.thisthat;

public class DoThat {
   private Long id;
   private String name;
   public Long getId() {
      return id;
   }
   protected DoThat() {}
   public DoThat(String name) {
      super();
      this.name = name;
   }
   public void setId(Long id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}


DoThat.hbm.xml
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test.thisthat">

<class name="DoThat" table="thisthat_do_that">
   <id name="id">
      <generator class="native" />
   </id>
   <property name="name"/>
</class>
</hibernate-mapping>


DoThis.java
Code:
package test.thisthat;

public class DoThis {
   private Long id;
   private String name;
   
   protected DoThis() {}
   public DoThis(String name) {
      super();
      this.name = name;
   }
   public Long getId() {
      return id;
   }
   public void setId(Long id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
}


DoThis.hbm.xml
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test.thisthat">

<class name="DoThis" table="thisthat_do_this">
   <id name="id">
      <generator class="native" />
   </id>
   <property name="name"/>
</class>
</hibernate-mapping>


Task.java
Code:
package test.thisthat;

import java.util.HashSet;
import java.util.Set;

public class Task {
   private Long id;
   private String name;
   private Set<DoThat> doThatCollection;
   private Set<DoThis> doThisCollection;

   protected Task() {}
   public Task(String name) {
      super();
      this.name = name;
   }
   public Long getId() {
      return id;
   }
   public void setId(Long id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   protected Set<DoThat> getDoThatCollection() {
      return doThatCollection;
   }
   protected void setDoThatCollection(Set<DoThat> doThatCollection) {
      this.doThatCollection = doThatCollection;
   }
   protected Set<DoThis> getDoThisCollection() {
      return doThisCollection;
   }
   protected void setDoThisCollection(Set<DoThis> doThisCollection) {
      this.doThisCollection = doThisCollection;
   }
   public void addDoThis(DoThis doThis) {
      if (doThisCollection == null) {
         doThisCollection = new HashSet<DoThis>();
      }
      doThisCollection.add(doThis);
   }
   public void addDoThat(DoThat doThat) {
      if (doThatCollection == null) {
         doThatCollection = new HashSet<DoThat>();
      }
      doThatCollection.add(doThat);
   }
}


Task.hbm.xml
Code:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
  "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="test.thisthat">

<class name="Task" table="thisthat_task">
   <id name="id">
      <generator class="native" />
   </id>
   <property name="name"/>
   <set name="doThatCollection" cascade="all">
      <key column="task_id"/>
      <one-to-many class="DoThat"/>
   </set>
   <set name="doThisCollection" cascade="all">
      <key column="task_id"/>
      <one-to-many class="DoThis"/>
   </set>
</class>
</hibernate-mapping>


Test.java
Code:
package test.thisthat;

import org.hibernate.Session;

import junit.framework.TestCase;

public class Test extends TestCase {

   public void testCreate() {
      Long taskId = createObjects();
      Session s = HibernateUtil.getSession();
      s.beginTransaction();
      Task task = (Task)s.load(Task.class, taskId);
      assertEquals("task1", task.getName());
      assertEquals(2, task.getDoThisCollection().size());
      assertEquals(2, task.getDoThatCollection().size());
      assertTrue(task.getDoThisCollection().iterator().next().getName().startsWith("DoThis"));
      assertTrue(task.getDoThatCollection().iterator().next().getName().startsWith("DoThat"));
      s.getTransaction().commit();
      s.close();
   }

   private Long createObjects() {
      Session s = HibernateUtil.getSession();
      s.beginTransaction();
      Task task = new Task("task1");
      task.addDoThis(new DoThis("DoThis1"));
      task.addDoThis(new DoThis("DoThis2"));
      task.addDoThat(new DoThat("DoThat1"));
      task.addDoThat(new DoThat("DoThat2"));
      Long taskId = (Long)s.save(task);
      s.getTransaction().commit();
      s.close();
      return taskId;
   }
   
}


HibernateUtil.java
Code:
package test.thisthat;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static SessionFactory factory;

    static {
       Configuration config = new Configuration()
          .addClass(Task.class)
          .addClass(DoThis.class)
          .addClass(DoThat.class)
          .setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect")
         .setProperty("hibernate.connection.driver_class", "org.hsqldb.jdbcDriver")
         .setProperty("hibernate.connection.url", "jdbc:hsqldb:mem:test")
          .setProperty("hibernate.connection.username", "sa")
          .setProperty("hibernate.connection.password", "")
          
          .setProperty("hibernate.hbm2ddl.auto", "create-drop")                  
         .setProperty("hibernate.cache.provider_class", "org.hibernate.cache.NoCacheProvider")
         .setProperty("hibernate.show_sql", "true");



        HibernateUtil.setSessionFactory(config.buildSessionFactory());
    }

    public static synchronized Session getSession() {
        if (factory == null) {
            factory = new Configuration().configure().buildSessionFactory();
        }
        return factory.openSession();
    }

    public static void setSessionFactory(SessionFactory factory) {
        HibernateUtil.factory = factory;
    }
}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 08, 2007 11:38 am 
Newbie

Joined: Tue Aug 07, 2007 12:00 pm
Posts: 3
Thanks for the help Mike.

One last thing, lets say I have another class that I want to call from the session bean (Schedule). I noticed from the HibernateUtil class you loaded the various classes required by executing on the Task class (Task, DoThis, and DoThat).

How would I go about adding the Schedule class to the HibernateUtil class?

As of now, to create the Session from the Test class you invoke the Session s = HibernateUtil.getSession();. How could this be more specific to create a Task session OR a Schedule session?

I think the answer might be to cast the class I need by Reflection, as in:

Schedule schedule = (Schedule)s.load(Schedule.class, scheduleId);

as well as adding the line:

.addClass(Schedule.class)

to the HibernateUtil


Thanks again.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Aug 08, 2007 12:10 pm 
Expert
Expert

Joined: Fri Jul 13, 2007 8:18 am
Posts: 370
Location: london
You're correct about both. The session is not specific to a class, its used to manage all your hibernate classes.

You can add the Schedule.class to the list of mapped classes but normally the configuration would be inside a hibernate.cfg.xml file rather than in code.

My hibernate util class isn't really suitable for use inside an app server. There are better versions around which use a thread-local to return the same session object for all operations inside a transaction (getCurrentSession()). I just use this for testing so I can exlicitly create a new session.


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