-->
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.  [ 18 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: Mapping a java bean
PostPosted: Fri Oct 21, 2005 12:03 pm 
Newbie

Joined: Fri Oct 21, 2005 11:14 am
Posts: 9
Location: San Jose, CA
I'm new to Hibernate and am having some difficulty understanding the relationship between my object, the mapping for that object , and the table for that object in the database.


The sample consists of a Superhero that has a Gadget and an Identity. They are simple and can be seen below.

My database tables for Gadget and Personal match their respective objects. The Superhero table is where I get stuck.
If I map the Superhero object to the Superhero table, I wind up with a table consisting of the following columns:
superheroID
superheroName
gadget (nonsense)
identity (nonsense)

It's nonsense because (a) the gadget & identity tables each have superheroID as a foreign key, (b) it's dumb, and (c) it's wrong.

What is the proper way to do this? Or, what am I missing?

Thank you very much.

Hibernate version: 3.0.5
Name and version of the database you are using: MySQL 5.0.11


Code:
public class Superhero
{
   private int superheroID;
   private String superheroName;
   
   // Every Superhero has a gadget!
   private Gadget gadget;
   
   // Every Superhero has a real Identity.
   private Identity identity;
   
   public Superhero() {
      gadget = new Gadget();
      identity = new Identity();
   }
// snipped getters and setters

Code:
public class Gadget{
   
   private int gadgetID;
   private int superheroID;
   
   private String name;
   
   public Gadget() {
      
   }
// snipped getters and setters

Code:
public class Identity
{
   private int identityID;
   private int superheroID;
   
   private String firstName;
   private String lastName;

   public Identity() {

   }
// snipped getters and setters


Code:
public class UseSuperhero
{
   private Superhero batman;   

   public UseSuperhero()
   {      
      batman = new Superhero();   
      batman.setSuperheroName( "Batman" );

      batman.getIdentity().setFirstName( "Bruce" );
      batman.getIdentity().setLastName( "Wayne" );   
      batman.getGadget().setName( "Bat-a-rang" );
   }
   public void saveSuperhero()
   {      
      //save batman to database
   }
   public void loadSuperhero()
   {      
      // load batman from database
   }
}


Top
 Profile  
 
 Post subject: Re: Mapping a java bean
PostPosted: Fri Oct 21, 2005 1:08 pm 
Expert
Expert

Joined: Fri Jul 22, 2005 2:42 pm
Posts: 670
Location: Seattle, WA
possum.pie wrote:
If I map the Superhero object to the Superhero table, I wind up with a table consisting of the following columns:
superheroID
superheroName
gadget (nonsense)
identity (nonsense)

It's nonsense because (a) the gadget & identity tables each have superheroID as a foreign key, (b) it's dumb, and (c) it's wrong.

What is the proper way to do this? Or, what am I missing?


Superhero table consisting of the following columns:
superheroID
superheroName

Then in the mapping file:
http://www.hibernate.org/hib_docs/v3/re ... n-onetoone

_________________
--------------
Konstantin

SourceLabs - dependable OpenSource systems


Top
 Profile  
 
 Post subject: Re: Mapping a java bean
PostPosted: Fri Oct 21, 2005 2:06 pm 
Newbie

Joined: Fri Oct 21, 2005 11:14 am
Posts: 9
Location: San Jose, CA
Quote:
Superhero table consisting of the following columns:
superheroID
superheroName

Then in the mapping file:
http://www.hibernate.org/hib_docs/v3/re ... n-onetoone


Thank you :)

Now that it's working (not throwing any exceptions) I have discovered a new problem. When I call
Code:
save(batman)
only the Superhero table is populated (superhero name and key). The Identity and Gadget tables remain empty.
Will Hibernate do this for me if I have things setup right or must I save each bean myself?

Thank you again!


Top
 Profile  
 
 Post subject: Re: Mapping a java bean
PostPosted: Fri Oct 21, 2005 2:16 pm 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
possum.pie wrote:

Now that it's working (not throwing any exceptions) I have discovered a new problem. When I call
Code:
save(batman)
only the Superhero table is populated (superhero name and key). The Identity and Gadget tables remain empty.
Will Hibernate do this for me if I have things setup right or must I save each bean myself?

Thank you again!


Check your cascade options on the Identity and Gadget associations in the Superhero mapping file.

_________________
Preston

Please don't forget to give credit if/when you get helpful information.


Top
 Profile  
 
 Post subject: Re: Mapping a java bean
PostPosted: Fri Oct 21, 2005 3:24 pm 
Newbie

Joined: Fri Oct 21, 2005 11:14 am
Posts: 9
Location: San Jose, CA
Quote:
Check your cascade options on the Identity and Gadget associations in the Superhero mapping file.


Ok, I'm almost there! However now I'm getting exceptions at every turn and I suspect it's because I can't get the mappings for Gadget and Identity right. I'll post them.

Superhero.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="com.xxxxxxxxxx">
   <class name="Superhero" table="Superhero" lazy="false">
      <id name="superheroID" type="integer" column="superheroID" unsaved-value="null">
         <generator class="native" />
      </id>
      <property name="superheroName" column="superheroName" />
      <one-to-one name="gadget" class="com.xxxxxxxxxx.Gadget" cascade="all" />
      <one-to-one name="identity" class="com.xxxxxxxxxx.Identity" cascade="all"/>
   </class>
</hibernate-mapping>

Gadget.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="com.xxxxxxxxxx">
   <class name="Gadget" table="Gadget" lazy="false" >
      <id name="gadgetID" type="integer" column="gadgetID" unsaved-value="null">
         <generator class="native" />
      </id>      
      <property name="name" column="name" />
      <many-to-one name="superheroID" class="com.xxxxxxxxxx.Superhero" foreign-key="superheroID"/>
   </class>
</hibernate-mapping>

Identity.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="com.xxxxxxxxxx">
   <class name="Identity" table="Identity" lazy="false">
      <id name="identityID" type="integer" column="identityID" unsaved-value="null">
         <generator class="native" />
      </id>
      <property name="lastName" column="lastName" />
      <property name="firstName" column="firstName" />
      <many-to-one name="superheroID" class="com.xxxxxxxxxx.Superhero" foreign-key="superheroID"/>
   </class>
</hibernate-mapping>


the exception
Code:
Hibernate: insert into Superhero (superheroName) values (?)
Hibernate: update Gadget set name=?, superheroID=? where gadgetID=?
****** save() has failed ******
org.hibernate.PropertyAccessException: IllegalArgumentException occurred calling getter of com.xxxxxxxxxx.Superhero.superheroID
   at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:119)
   at org.hibernate.tuple.AbstractTuplizer.getIdentifier(AbstractTuplizer.java:103)
   at org.hibernate.persister.entity.BasicEntityPersister.getIdentifier(BasicEntityPersister.java:2944)
   at org.hibernate.persister.entity.BasicEntityPersister.isTransient(BasicEntityPersister.java:2705)
   at org.hibernate.engine.ForeignKeys.isTransient(ForeignKeys.java:181)
   at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:215)
   at org.hibernate.type.EntityType.getIdentifier(EntityType.java:99)
   at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:63)
   at org.hibernate.persister.entity.BasicEntityPersister.dehydrate(BasicEntityPersister.java:1617)
   at org.hibernate.persister.entity.BasicEntityPersister.update(BasicEntityPersister.java:1963)
   at org.hibernate.persister.entity.BasicEntityPersister.updateOrInsert(BasicEntityPersister.java:1909)
   at org.hibernate.persister.entity.BasicEntityPersister.update(BasicEntityPersister.java:2149)
   at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:75)
   at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:239)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:223)
   at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:137)
   at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)
   at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
   at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)
   at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:324)
   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
   at com.xxxxxxxxxx.Bean.save(Bean.java:79)
   at com.xxxxxxxxxx.Bean.saveOrLoad(Bean.java:53)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
   at java.lang.reflect.Method.invoke(Unknown Source)
   at com.sun.faces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:126)
   at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:72)
   at javax.faces.component.UICommand.broadcast(UICommand.java:312)
   at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:267)
   at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:381)
   at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:75)
   at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:200)
   at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:90)
   at javax.faces.webapp.FacesServlet.service(FacesServlet.java:197)
   at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:252)
   at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:173)
   at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:213)
   at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:178)
   at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:126)
   at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:105)
   at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:107)
   at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:148)
   at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:856)
   at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.processConnection(Http11Protocol.java:744)
   at org.apache.tomcat.util.net.PoolTcpEndpoint.processSocket(PoolTcpEndpoint.java:527)
   at org.apache.tomcat.util.net.LeaderFollowerWorkerThread.runIt(LeaderFollowerWorkerThread.java:80)
   at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:684)
   at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalArgumentException: object is not an instance of declaring class
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
   at java.lang.reflect.Method.invoke(Unknown Source)
   at org.hibernate.property.BasicPropertyAccessor$BasicGetter.get(BasicPropertyAccessor.java:105)
   ... 49 more


Top
 Profile  
 
 Post subject: Re: Mapping a java bean
PostPosted: Fri Oct 21, 2005 5:10 pm 
Newbie

Joined: Fri Oct 21, 2005 11:14 am
Posts: 9
Location: San Jose, CA
I think I may have posted the wrong exception.
No matter. I'm pretty sure that I know what's happening just not why. Here's a snippet from the correct exception:

Code:
Hibernate: insert into Superhero (superheroName) values (?)
Hibernate: select identity_.identityID, identity_.lastName as lastName2_, identity_.firstName as firstName2_ from Identity identity_ where identity_.identityID=?
Hibernate: insert into Identity (lastName, firstName) values (?, ?)

The insert into Identity fails because it's missing the foreign key.
Unless I'm badly mistaken, it should look like this:
Code:
Hibernate: insert into Identity (superheroID, lastName, firstName) values (?, ?, ?)


Any clue why this is like this?


Top
 Profile  
 
 Post subject: Re: Mapping a java bean
PostPosted: Fri Oct 21, 2005 5:14 pm 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
Change the Identity and Gadget mapping files to use the "foriegn" ID Generator. (And you should name the fields on those classes superhero, not superheroID since they will hold the actual Object, not just an ID.

Code:
<generator class="foreign">
   <param name="property">superhero</param>
</generator>

_________________
Preston

Please don't forget to give credit if/when you get helpful information.


Top
 Profile  
 
 Post subject: Re: Mapping a java bean
PostPosted: Fri Oct 21, 2005 5:25 pm 
Newbie

Joined: Fri Oct 21, 2005 11:14 am
Posts: 9
Location: San Jose, CA
pksiv wrote:
Change the Identity and Gadget mapping files to use the "foriegn" ID Generator. (And you should name the fields on those classes superhero, not superheroID since they will hold the actual Object, not just an ID.

Code:
<generator class="foreign">
   <param name="property">superhero</param>
</generator>


Do you mean that instead of:
Code:
public class Gadget {
   
   private int gadgetID;
   private int superheroID;
...

I should have:
Code:
public class Gadget {
   
   private int gadgetID;
   private Superhero superheroID;
...


Sorry for the bold...
Thank you.


Top
 Profile  
 
 Post subject: yes
PostPosted: Fri Oct 21, 2005 5:28 pm 
Expert
Expert

Joined: Fri Jul 22, 2005 2:42 pm
Posts: 670
Location: Seattle, WA
Yes, he meant exactly that :)

_________________
--------------
Konstantin

SourceLabs - dependable OpenSource systems


Top
 Profile  
 
 Post subject: Re: yes
PostPosted: Fri Oct 21, 2005 6:32 pm 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
kgignatyev wrote:
Yes, he meant exactly that :)


Actually, I meant
Code:
public class Gadget {
   
   private int gadgetID;
   private Superhero superhero;
...
}


superhero not superheroID.

_________________
Preston

Please don't forget to give credit if/when you get helpful information.


Top
 Profile  
 
 Post subject: Oops!
PostPosted: Fri Oct 21, 2005 6:43 pm 
Expert
Expert

Joined: Fri Jul 22, 2005 2:42 pm
Posts: 670
Location: Seattle, WA
Oops, my bad :(

Preston, please accept my apologies

_________________
--------------
Konstantin

SourceLabs - dependable OpenSource systems


Top
 Profile  
 
 Post subject: Re: Oops!
PostPosted: Fri Oct 21, 2005 7:03 pm 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
kgignatyev wrote:
Oops, my bad :(

Preston, please accept my apologies


No worries. It's all good here in the forum.

_________________
Preston

Please don't forget to give credit if/when you get helpful information.


Top
 Profile  
 
 Post subject: Re: yes
PostPosted: Fri Oct 21, 2005 9:29 pm 
Newbie

Joined: Fri Oct 21, 2005 11:14 am
Posts: 9
Location: San Jose, CA
pksiv wrote:
kgignatyev wrote:
Yes, he meant exactly that :)


Actually, I meant
Code:
public class Gadget {
   
   private int gadgetID;
   private Superhero superhero;
...
}


superhero not superheroID.



Thank you Konstatin and Preston. I still can't get it to go.

Am I going about this wrong? If anyone has a better way to get my Superhero to persist I'm all ears.

Thanks.


Top
 Profile  
 
 Post subject: Re: yes
PostPosted: Sat Oct 22, 2005 1:15 am 
Newbie

Joined: Fri Oct 21, 2005 11:14 am
Posts: 9
Location: San Jose, CA
possum.pie wrote:
Thank you Konstatin and Preston. I still can't get it to go.

Am I going about this wrong? If anyone has a better way to get my Superhero to persist I'm all ears.

Thanks.


Well I did get it to work. Sort of. I had to remove the foreign key restraints on tables Gadget and Identity.
So now the foreign key 'superhero' in Gadget and Identity is always null. That's bad.
How do I get the value of the autogenerated primary key from Superhero to appear in the inserts for values in Gadget and Identity?


I hate to do this but I'm going to post (without the doctype) my updated mappings...again.

Superhero.hbm.xml
Code:
<hibernate-mapping>
   <class name="com.foo.Superhero" table="Superhero" >
      <id name="superheroID" type="integer" column="superheroID" unsaved-value="undefined">
         <generator class="native" />
      </id>
      <property name="superheroName" type="string" not-null="true"/>
      <one-to-one name="identity" class="com.foo.Identity" property-ref="superhero" cascade="all"/>
      <one-to-one name="gadget" class="com.foo.Gadget" property-ref="superhero" cascade="all"/>
   </class>
</hibernate-mapping>

Identity.hbm.xml
Code:
<hibernate-mapping>
   <class name="com.foo.Identity" table="Identity">
      <id name="identityID" type="integer" column="identityID"  unsaved-value="undefined">
         <generator class="native" />
      </id>
      <property name="firstName" type="string" not-null="true" />
      <property name="lastName" type="string" not-null="true" />
      <property name="superhero" type="integer" />
   </class>
</hibernate-mapping>

Gadget.hbm.xml
Code:
<hibernate-mapping package="com.gofastcash">
   <class name="com.foo.Gadget" table="Gadget" lazy="false" select-before-update="false">
      <id name="gadgetID" type="integer" column="gadgetID" unsaved-value="undefined" >
         <generator class="native" />
      </id>      
      <property name="name" type="string" not-null="true"/>
      <property name="superhero" type="integer" />
   </class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject: Re: yes
PostPosted: Sat Oct 22, 2005 6:58 am 
Expert
Expert

Joined: Mon Feb 14, 2005 12:32 pm
Posts: 609
Location: Atlanta, GA - USA
If these are true one-to-one relationships, and you use the "foreign" generator with the superhero property - and the property is the OBJECT Superhero, not the int superheroId - then you don't need a FK because all of the PK's are the same.

If the Gadget table has a COLUMN on it named SUPER_HERO_ID, then it's possible to have more than 1 Gadget per Superhero and it's not a true one-to-one.

_________________
Preston

Please don't forget to give credit if/when you get helpful information.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 18 posts ]  Go to page 1, 2  Next

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.