-->
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.  [ 14 posts ] 
Author Message
 Post subject: Cannot work out mapping.hbm.xml file for this relationship
PostPosted: Mon Jul 28, 2008 8:40 pm 
Newbie

Joined: Mon Jul 28, 2008 8:30 pm
Posts: 7
Hi,

I have an EmailMessage class which has its own unique key.
Each EmailMessage can be associated with TWO EmailAddress: emailAddressFrom and emailAddressTo

Each EmailAddress is associated with the owner's name.

Example table contents:

EmailMessage Table
---------------
id | email_address_from | email_address_to | message
1 | bob@test.com | sid@test.com | Hi Sid, See you at lunch, Bob
2 | sid@test.com | bob@test.com | Bob, See you at 12, Cheers Sid
3 | sid@test.com | sid@test.com | I'm emailing myself!

Each entry in email_address_from and email_address_to must exist in EmailAddress Table.

EmailAddress Table
---------------
email_address | name
bob@test.com | Bob
sid@test.com | Sid

Each entry in email_address column must be unique.

(I do not need to be able to get back from email_address in EmailAddress Table to EmailMessage).

I cannot work out the required mappings to get this to work... I've tried one-to-one and property-ref, many-to-one with unique="true" e.t.c., but I've not got anything working (so I've not posted my mapping file which is a mess!).

If anyone could help me write this mapping file for these two classes that'd be much appreciated.


Code:
public class EmailMessage {

   private long id;
   private EmailAddress emailAddressFrom;
   private EmailAddress emailAddressTo;
   private String message;

   public EmailMessage() {
   }

   public long getId() {
      return id;
   }

   public void setId(long id) {
      this.id = id;
   }

   public EmailAddress getEmailAddressFrom() {
      return emailAddressFrom;
   }

   public void setEmailAddressFrom(EmailAddress emailAddressFrom) {
      this.emailAddressFrom = emailAddressFrom;
   }

   public EmailAddress getEmailAddressTo() {
      return emailAddressTo;
   }

   public void setEmailAddressTo(EmailAddress emailAddressTo) {
      this.emailAddressTo = emailAddressTo;
   }

   public String getMessage() {
      return message;
   }

   public void setMessage(String message) {
      this.message = message;
   }
   
}


Code:

public class EmailAddress {

   private String emailAddress;
   private String name;
   private EmailMessage emailMessage;
   
   public EmailAddress() {
   }
   
   public String getEmailAddress() {
      return emailAddress;
   }
   public void setEmailAddress(String emailAddress) {
      this.emailAddress = emailAddress;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }

   public void setEmailMessage(EmailMessage emailMessage) {
      this.emailMessage = emailMessage;
   }

   public EmailMessage getEmailMessage() {
      return emailMessage;
   }
   
}


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 9:38 pm 
Newbie

Joined: Wed Jul 23, 2008 11:39 pm
Posts: 18
In the EmailAddress class, the mapping to Email Message should be one-to-many, which results in a Set[] (Eclipse generated default) of email Message like this :

private Set emailMessages = new HashSet(0);

and the mapping is something like :

<set name="emailMessages " inverse="true">
<key>
<column name="email_address" not-null="true" />
</key>
<one-to-many class="com.bbah.blah.model.EmailMessage" />
</set>

for the EmailMessage class :

the mapping to EmailAddress class is many-to-one relation, the object class seems to be alright, the mapping is :

<many-to-one name="emailAddressFrom" class="com.bbah.blah.model.EmailAddress" fetch="select">
<column name="email_address_from" not-null="true" />
</many-to-one>

<many-to-one name="emailAddressTo" class="com.bbah.blah.model.EmailAddress" fetch="select">
<column name="email_address_to" not-null="true" />
</many-to-one>


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 10:04 pm 
Newbie

Joined: Mon Jul 28, 2008 8:30 pm
Posts: 7
Thanks. I've added tp EmailAddress

Code:
private Set emailMessages = new HashSet(0);
   public Set getEmailMessages() {
      return emailMessages;
   }

   public void setEmailMessages(Set emailMessages) {
      this.emailMessages = emailMessages;
   }



and my mapping.hbm.xml file now reads:

Code:
<hibernate-mapping auto-import="true" default-lazy="false">

    <class name="EmailMessage" table="email_message">
   
       <id name="id">
         <generator class="native" />
      </id>
   
          <many-to-one name="emailAddressFrom" class="EmailAddress" fetch="select">
         <column name="email_address_from" not-null="true" />
      </many-to-one>

      <many-to-one name="emailAddressTo" class="EmailAddress" fetch="select">
         <column name="email_address_to" not-null="true" />
      </many-to-one>
      
      <property name="message" />
      
    </class>
   
   
    <class name="EmailAddress" table="email_address">
   
       <set name="emailMessages " inverse="true">
         <key>
            <column name="email_address" not-null="true" />
         </key>
         <one-to-many class="EmailMessage" />
      </set>
      
      <property name="name" />
   
   </class>
   

</hibernate-mapping>


What should I use as a pimary key for EmailAddress? I want the email_address itself to be the primary key. As there is no key when I run it I get the error:



Quote:
Initial SessionFactory creation failed.org.hibernate.InvalidMappingException: Could not parse mapping document from resource mapping.hbm.xml


Thanks for your help.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 10:10 pm 
Newbie

Joined: Wed Jul 23, 2008 11:39 pm
Posts: 18
You may want to modify it to :


<class name="EmailAddress" table="email_address">
<id name="emailAddress" type="java.lang.String">
<column name="email_address" />
<generator class="assigned" />
</id>

<set name="emailMessages " inverse="true">
<key>
<column name="email_address" not-null="true" />
</key>
<one-to-many class="EmailMessage" />
</set>
<property name="name" type="java.lang.String">
<column name="name" />
</property>
</class>


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 10:19 pm 
Newbie

Joined: Mon Jul 28, 2008 8:30 pm
Posts: 7
Thanks. I now get:

Quote:
Exception in thread "main" org.hibernate.PropertyValueException: not-null property references a null or transient value: EmailMessage.emailAddressFrom


from the test code:

Code:
      EmailMessage emailMessage = new EmailMessage();
      emailMessage.setMessage("Hello Sid, Bob here.");
      
      EmailAddress emailAddressFrom = new EmailAddress();
      emailAddressFrom.setEmailAddress("bob@test.com");
      emailAddressFrom.setName("Bob");

      EmailAddress emailAddressTo = new EmailAddress();
      emailAddressTo.setEmailAddress("sid@test.com");
      emailAddressTo.setName("Sid");
      
      emailMessage.setEmailAddressFrom(emailAddressFrom);
      emailMessage.setEmailAddressTo(emailAddressTo);
      
      Set emailMessagesSet = new HashSet();
      emailMessagesSet.add(emailMessage);
      
      emailAddressTo.setEmailMessages(emailMessagesSet);
      emailAddressFrom.setEmailMessages(emailMessagesSet);
       
        Session  session = HibernateUtil.getSession();
        Transaction  tx = session.beginTransaction();
        session.save(emailMessage);
        tx.commit();
        HibernateUtil.closeSession();


Also it has created an email_address column in email_message in addition to email_address_from and email_address_to columns. Is this expected?


Last edited by andytwiz on Mon Jul 28, 2008 10:29 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 10:29 pm 
Newbie

Joined: Wed Jul 23, 2008 11:39 pm
Posts: 18
Update the mapping "not-null" field if the emailAddressFrom is not a mandatory field.

And if it is a not-null field, you must set the value before creating a new instance.

Try also to "flush" the session if you are creating both a new Email Address and a EmailMessage in the same transaction, so that the newly created Email Address could be referenced by the new EmailMessage object.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 10:40 pm 
Newbie

Joined: Mon Jul 28, 2008 8:30 pm
Posts: 7
Its not null - I've set it using the test code above.

Where should the flush appear?

Thanks


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 10:44 pm 
Newbie

Joined: Wed Jul 23, 2008 11:39 pm
Posts: 18
After the creation of EmailAddress.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 11:13 pm 
Newbie

Joined: Mon Jul 28, 2008 8:30 pm
Posts: 7
Code:
EmailMessage emailMessage = new EmailMessage();
      emailMessage.setMessage("Hello Sid, Bob here.");
     
      EmailAddress emailAddressFrom = new EmailAddress();
      emailAddressFrom.setEmailAddress("bob@test.com");
      emailAddressFrom.setName("Bob");

      EmailAddress emailAddressTo = new EmailAddress();
      emailAddressTo.setEmailAddress("sid@test.com");
      emailAddressTo.setName("Sid");
     
      emailMessage.setEmailAddressFrom(emailAddressFrom);
      emailMessage.setEmailAddressTo(emailAddressTo);
     
      Set emailMessagesSet = new HashSet();
      emailMessagesSet.add(emailMessage);
     
      emailAddressTo.setEmailMessages(emailMessagesSet);
      emailAddressFrom.setEmailMessages(emailMessagesSet);
       
        Session  session = HibernateUtil.getSession();
        Transaction  tx = session.beginTransaction();
        session.save(emailMessage);
        tx.commit();
        HibernateUtil.closeSession();


Is my test code above correct? Inserting session.flush() doesn't seem to make a difference.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 11:21 pm 
Newbie

Joined: Wed Jul 23, 2008 11:39 pm
Posts: 18
<class name="EmailMessage" table="email_message">

<id name="id">
<generator class="native" />
</id>
<property name="emailAddressFromStr" type="java.lang.String">
<column name="email_address_from" not-null="true" />
</property>
<property name="emailAddressToStr" type="java.lang.String">
<column name="email_address_to" not-null="true" />
</property>
<many-to-one name="emailAddressFrom" class="EmailAddress" fetch="select" insert="false" update="false">
<column name="email_address_from" not-null="true" />
</many-to-one>

<many-to-one name="emailAddressTo" class="EmailAddress" fetch="select" insert="false" update="false">
<column name="email_address_to" not-null="true" />
</many-to-one>

<property name="message" />

</class>


Normally I do it this way (Actually I am not sure if it is appropriate), and add property in the object class

private String emailAddressFromStr;
private String emailAddressToStr;

and create the EmailMessage by these two properties.


EmailMessage could then be created by :

EmailMessage emailMessage = new EmailMessage();
emailMessage.setMessage("Hello Sid, Bob here.");

emailMessage.setEmailAddressFrom("bob@test.com");
emailMessage.setEmailAddressTo("sid@test.com");

Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
session.save(emailMessage);
tx.commit();
HibernateUtil.closeSession();


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 11:51 pm 
Newbie

Joined: Mon Jul 28, 2008 8:30 pm
Posts: 7
Thanks.

That seems I need to add the EmailAddress to email_address table manually?

Is there anyway it could be done automatically when saving EmailMessage?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Jul 28, 2008 11:56 pm 
Newbie

Joined: Wed Jul 23, 2008 11:39 pm
Posts: 18
I misunderstood your problem. I saw from your original post that you already had that records in the DB. If you are creating new records altogether, you may do this :

Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
EmailMessage emailMessage = new EmailMessage();
emailMessage.setMessage("Hello Sid, Bob here.");

EmailAddress emailAddressFrom = new EmailAddress();
emailAddressFrom.setEmailAddress("bob@test.com");
emailAddressFrom.setName("Bob");
session.save(emailAddressFrom );

EmailAddress emailAddressTo = new EmailAddress();
emailAddressTo.setEmailAddress("sid@test.com");
emailAddressTo.setName("Sid");
session.save(emailAddressTo );
session.flush();

//suppose you use original mapping
emailMessage.setEmailAddressFrom(emailAddressFrom);
emailMessage.setEmailAddressTo(emailAddressTo);

session.save(emailMessage);

tx.commit();
HibernateUtil.closeSession();


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 29, 2008 7:32 am 
Newbie

Joined: Mon Jul 28, 2008 8:30 pm
Posts: 7
Yes that works.

I was hoping to have the tables "linked" automatically e.g. Just setting up and saving EmailMessage would insert the data into email_address table.

And when you delete a record from email_message if the matching email_address entries no longer match any other email_message they get deleted to.

Is all this possible with Hibernate?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Jul 29, 2008 8:51 pm 
Newbie

Joined: Wed Jul 23, 2008 11:39 pm
Posts: 18
It is not possible for Hibernate to handle such "business logic" for you. You must do that by your own coding.


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