-->
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.  [ 4 posts ] 
Author Message
 Post subject: Address Mapping Question
PostPosted: Thu Mar 16, 2006 3:08 pm 
Newbie

Joined: Thu Mar 16, 2006 2:56 pm
Posts: 4
I'm investigating using Hibernate 3 in an existing application with legacy database. Hibernate seems useful, but our database has many strange constructs that aren't obvious to me how to accommodate using Hibernate.

For instance, I have a MEMBER table with a MEMBER_ID PK and an ADDRESS table with a composite (MEMBER_ID, ADDRESS_TYPE) PK.

For any member, there may be a mailing address and/or billing address stored in MEMBER_ADDRESS. The ADDRESS_TYPE column will contain either "MAIL" or "BILL", and the MEMBER_ID column contains the id of the member whose address it is.

Ideally, I'd like to have a Member object and an Address object. On the Member object would be .getMailingAddress() and .getBillingAddress() methods which would return the respective Address if it exists.

ALSO ... I would ideally like to use this Address object for other addresses as well that don't use this table.

I'm not sure the best way to approach this. None of the examples I've seen deal with the complexity of the ADDRESS_TYPE column.

Any ideas?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 16, 2006 4:05 pm 
Newbie

Joined: Mon Mar 08, 2004 1:41 pm
Posts: 5
You have two problems here. First is getting the getMailingAddress & getBillingAddress into your Member object. The other is using the Address object to represent all Addresses in your database.

I'm assuming your app isn't read only -- if it is, making views to create a more sane data structure may be a good option.

First Problem:
I think the easiest way to accomplish this is to set up a class with composite id's. lets say MemberAddress.

Info on composite ID's:
http://www.hibernate.org/hib_docs/v3/re ... ompositeid

Then, set up a column and/or formula in the mapping file to specify exactly what you are looking for.

http://www.hibernate.org/hib_docs/v3/re ... ing-column

That would be part of your many-to-one mapping.

You could also try setting up an inheritence (Table-Per-Class-Heirarchy) structure in which the ADDRESS_TYPE is both the discriminator and part of the composite id. I don't know if hibernate would like that or not though.

Second problem:
Your best bet is Table-Per-Concrete-Class via unions.

http://www.hibernate.org/hib_docs/v3/re ... erconcrete

You would create a abstract class called Address, and then each table would have its own subclass. Note that any column defined in your Address superclass must have the same name in all tables (i.e. all the address tables will need to have the same column name for city, state, line1, line2, zip, etc. if you want them to be accessable at the superclass level).

You'd be able to keep performance up by references the subclasses where you can, but can still refer to all addresses using "Address" (it will union all the address tables together).

By the way -- avoid joined subclass (table per subclass) on large tables, the performance is awful.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 16, 2006 4:20 pm 
Newbie

Joined: Thu Mar 16, 2006 2:56 pm
Posts: 4
Thanks ... this is very helpful.

I didn't see this snippet in the document you linked before:

<many-to-one name="homeAddress" class="Address"
insert="false" update="false">
<column name="person_id" not-null="true" length="10"/>
<formula>'MAILING'</formula>
</many-to-one>

I think this solves exactly the problem I have. The nested column and formula elements were the solution here.

I'm going to get this working and then check out the second half of your post for the reusability part.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 16, 2006 5:35 pm 
Newbie

Joined: Thu Mar 16, 2006 2:56 pm
Posts: 4
An interesting thing I noticed while implementing this was that I had to put a ".trim()" in the setAddressType() in order to get the formula tag to work in the many-to-one mapping. (It was appending spaces to 'MAIL' and 'BILL' using Oracle.)

I also set not-found="ignore" on the billing address, since it is optional.

Anyway, here's the prototype which seems to be working:

Code:
package hibertest;

public class Person {
   private String id;

   private String firstName;

   private String middleInitial;

   private String lastName;
   
   private USAddress mailingAddress;

   private USAddress billingAddress;

   public String getFirstName() {
      return firstName;
   }

   public void setFirstName(String firstName) {
      this.firstName = firstName;
   }

   public String getID() {
      return id;
   }

   public void setID(String id) {
      this.id = id;
   }

   public String getLastName() {
      return lastName;
   }

   public void setLastName(String lastName) {
      this.lastName = lastName;
   }

   public String getMiddleInitial() {
      return middleInitial;
   }

   public void setMiddleInitial(String middleInitial) {
      this.middleInitial = middleInitial;
   }

   public USAddress getMailingAddress() {
      return mailingAddress;
   }

   public void setMailingAddress(USAddress address) {
      this.mailingAddress = address;
   }

   public USAddress getBillingAddress() {
      return billingAddress;
   }

   public void setBillingAddress(USAddress address) {
      this.billingAddress = address;
   }
}


Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hibertest">
   <class name="Person" table="MEMBER">
      <id   name="ID" column="MEMBER_ID"/>
      <property name="firstName" column="FIRST_NAME"/>
      <property name="middleInitial" column="MIDDLE_INITIAL"/>
      <property name="lastName" column="LAST_NAME"/>
      <many-to-one name="mailingAddress"
         class="PersonUSAddress"
         insert="false"
         update="false">
         <column name="MEMBER_ID"/>
         <formula>'MAIL'</formula>
      </many-to-one>
      <many-to-one name="billingAddress"
         class="PersonUSAddress"
         insert="false"
         update="false"
         not-found="ignore">
         <column name="MEMBER_ID"/>
         <formula>'BILL'</formula>
      </many-to-one>
   </class>
</hibernate-mapping>


Code:
package hibertest;

public abstract class USAddress {
   private String street1;

   private String street2;

   private String city;

   private String state;

   private String zip;

   public String getCity() {
      return city;
   }

   public String getStreet1() {
      return street1;
   }

   public String getStreet2() {
      return street2;
   }

   public String getState() {
      return state;
   }

   public String getZip() {
      return zip;
   }

   public void setCity(String city) {
      this.city = city;
   }

   public void setState(String state) {
      this.state = state;
   }

   public void setStreet1(String street1) {
      this.street1 = street1;
   }

   public void setStreet2(String street2) {
      this.street2 = street2;
   }

   public void setZip(String zip) {
      this.zip = zip;
   }
}


Code:
package hibertest;

import java.io.Serializable;

public class PersonUSAddress extends USAddress implements Serializable {
   private String memberID;

   private String addressType;

   public String getAddressType() {
      return addressType;
   }

   public void setAddressType(String addressType) {
      this.addressType = addressType.trim();
   }

   public String getMemberID() {
      return memberID;
   }

   public void setMemberID(String memberID) {
      this.memberID = memberID;
   }
}


Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hibertest">
   <class name="PersonUSAddress" table="MEMBER_LOCATION">
      <composite-id>
         <key-property name="memberID" column="MEMBER_ID"/>
         <key-property name="addressType" column="ADDRESS_TYPE"/>
      </composite-id>
      <property name="street1" column="ADDRESS_1"/>
      <property name="street2" column="ADDRESS_2"/>
      <property name="city" column="CITY"/>
      <property name="state" column="STATE"/>
      <property name="zip" column="ZIP"/>
   </class>
</hibernate-mapping>


It's not even too ugly. Thanks!


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