-->
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: Oracle Object, Foreign Key and UserType in Hibernate
PostPosted: Wed Feb 01, 2006 12:41 pm 
Newbie

Joined: Fri Sep 09, 2005 11:09 am
Posts: 7
Location: Clermont-Ferrand
Need help with Hibernate? Read this first:
http://www.hibernate.org/ForumMailingli ... AskForHelp

Hibernate version:Hibernate 3.1rc1

Mapping documents:<?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>
<class name="com.seryx.data.common.User" table="`USER`">
<id name="iduser" type="short">
<column name="IDUSER" precision="4" scale="0" />
<generator class="sequence">
<param name="sequence">SEQ_USER_ID</param>
</generator>
</id>

<property name="name" type="com.seryx.hibernate.custom.types.oracle.NameUserType">
<column name="NAME" sql-type="ONAME" />
</property>

<property name="businessPhone" type="com.seryx.hibernate.custom.types.oracle.PhoneUserType">
<column name="BUSINESSPHONE" sql-type="OPHONE" />
</property>
<property name="homePhone" type="com.seryx.hibernate.custom.types.oracle.PhoneUserType">
<column name="HOMEPHONE" sql-type="OPHONE" />
</property>

<property name="bussinessEmail" type="string">
<column name="BUSINESSEMAIL" length="50" not-null="false" />
</property>
<property name="homeEmail" type="string">
<column name="HOMEEMAIL" length="50" not-null="false" />
</property>

<property name="address" type="com.seryx.hibernate.custom.types.oracle.PhoneUserType">
<column name="ADDRESS" sql-type="OADDRESS" />
</property>
<!--
<set name="posts" inverse="true">
<key>
<column name="IDUSER" precision="4" scale="0" not-null="true" />
</key>
<one-to-many class="com.seryx.data.common.Post" />
</set>
-->
</class>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():

Full stack trace of any exception that occurs:

Name and version of the database you are using: RDBMS: Oracle, version: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0

The generated SQL (show_sql=true):

Debug level Hibernate log excerpt:
I'm using Oracle's Object in my table USER, there the declaration:
Code:
create or replace type oPhone as object
(
   phone          varchar2(50),
   extension      number(4)
);
/


Code:
create or replace type oAddress as object
(
   address       varchar2(200),
   city         varchar2(100),
   zipcode         varchar2(8),
   state          number(4),
   country         number(3)
);
/


Code:
create or replace type oName as object
(
   firstname       varchar2(50),
   middlename       varchar2(50),
   lastname       varchar2(50)
);
/


Code:
create table "USER"
(
   iduser         number(4)      constraint user_pk primary key,
   Name          oName         constraint user_nn_name not null,
   BusinessPhone    oPhone,
   HomePhone       oPhone,
   BusinessEmail   varchar2(50),
   HomeEmail      varchar2(50),
   Address         oAddress      constraint user_nn_address not null,
   constraint "USER_NN_CITY" check ("ADDRESS"."CITY" is not null),
   constraint "USER_REF_STATE" foreign key("ADDRESS"."STATE") references "STATE"("IDSTATE"),
   constraint "USER_REF_COUNTRY" foreign key("ADDRESS"."COUNTRY") references "COUNTRY"("IDCOUNTRY"),
   constraint "USER_NN_COUNTRY" check ("ADDRESS"."COUNTRY" is not null)
);

I've created my own UserType, it's a generic own and ha to be extended with the specific UserType:
Code:
public abstract class OracleObjectUserType<T> implements UserType {
   
   private static final int SQL_TYPE = Types.STRUCT;
   
   private String DB_OBJECT_TYPE = null;
   
   Class<T> clazz;
   
   public int[] sqlTypes() {
      return new int[] {SQL_TYPE};
   }

   public Class returnedClass() {
      return clazz;
   }

   public boolean equals(Object object1, Object object2) throws HibernateException {
      return ObjectUtils.equals(object1, object2);
   }

   public int hashCode(Object object) throws HibernateException {
      return object.hashCode();
   }

   public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) throws HibernateException, SQLException {
      
      final Struct struct = (Struct) resultSet.getObject(names[0]);
      
      if (resultSet.wasNull()) {
         return null;
      }
      T bean = getGeneric();
      final ResultSetMetaData meta=StructDescriptor.createDescriptor(DB_OBJECT_TYPE, resultSet.getStatement().getConnection()).getMetaData();
      
      for(int i=0;i<meta.getColumnCount();i++) {
         try {
            PropertyUtils.setProperty(bean,meta.getColumnName(i+1).toLowerCase(), struct.getAttributes()[i]);
         } catch (IllegalAccessException e) {
            e.printStackTrace();
         } catch (InvocationTargetException e) {
            e.printStackTrace();
         } catch (NoSuchMethodException e) {
            e.printStackTrace();
         } catch (SQLException e) {
            e.printStackTrace();
         }
      }
      
      return bean;
   }

   public void nullSafeSet(PreparedStatement statement, Object value, int index) throws HibernateException, SQLException {
      if (value == null) {
         statement.setNull(index, SQL_TYPE, DB_OBJECT_TYPE);
      } else {
         final T bean = clazz.cast(value);

         final Connection connection = statement.getConnection();
         final StructDescriptor descriptor=StructDescriptor.createDescriptor(DB_OBJECT_TYPE, connection);
         final ResultSetMetaData meta=descriptor.getMetaData();
         
         final Object[] values=new Object[meta.getColumnCount()];
         
         for(int i=0;i<meta.getColumnCount();i++) {
            try {
               values[i]=PropertyUtils.getProperty(bean,meta.getColumnName(i+1).toLowerCase());
            } catch (IllegalAccessException e) {
               e.printStackTrace();
            } catch (InvocationTargetException e) {
               e.printStackTrace();
            } catch (NoSuchMethodException e) {
               e.printStackTrace();
            } catch (SQLException e) {
               e.printStackTrace();
            }
         }
         final STRUCT struct = new STRUCT(descriptor, connection, values);
         
         
         statement.setObject(index, struct, SQL_TYPE);
      }
   }
   
   public Object deepCopy(Object object) throws HibernateException {
      if (object == null) {
         return null;
      }
      
      final T copy = getGeneric();
      
      try {
         PropertyUtils.copyProperties(copy,object);
      } catch (IllegalAccessException e) {
         e.printStackTrace();
      } catch (InvocationTargetException e) {
         e.printStackTrace();
      } catch (NoSuchMethodException e) {
         e.printStackTrace();
      }       
      return copy;
   }
   
   public boolean isMutable() {
      return true;
   }

   public Serializable disassemble(Object value) throws HibernateException {
      return (Serializable) deepCopy(value);
   }

   public Object assemble(Serializable cached, Object owner) throws HibernateException {
      return deepCopy(cached);
   }

   public Object replace(Object original, Object target, Object owner) throws HibernateException {
      return deepCopy(original);
   }
   
   public Class<T> getClazz() {
      return clazz;
   }

   public void setClazz(Class<T> clazz) {
      this.clazz = clazz;
   }

   public void setDB_OBJECT_TYPE(String db_object_type) {
      DB_OBJECT_TYPE = db_object_type;
   }
   
   public T getGeneric(){
      Constructor constructor;
      T clone=null;
      
      try {
         constructor = clazz.getConstructor();
         clone=clazz.cast(constructor.newInstance((Object[])null));
      } catch (SecurityException e) {
         e.printStackTrace();
      } catch (NoSuchMethodException e) {
         e.printStackTrace();
      }catch (IllegalArgumentException e) {
         e.printStackTrace();
      } catch (InstantiationException e) {
         e.printStackTrace();
      } catch (IllegalAccessException e) {
         e.printStackTrace();
      } catch (InvocationTargetException e) {
         e.printStackTrace();
      }
      return clone;
   }
}

This is the UserType for Name:
Code:
public class NameUserType extends OracleObjectUserType<Name> {
   
   public NameUserType() {
      super();
      setClazz(Name.class);
      setDB_OBJECT_TYPE("ONAME");
   }
}

and I've a bean for Name:
Code:
public class Name {
   private String firstname = null;

   private String middlename = null;

   private String lastname = null;
   
   public Name(){};
   
   public Name(String firstName, String middleName, String lastName) {
      setFirstname(firstName);
      setLastname(lastName);
      setMiddlename(middleName);
   }
   
   public String getFirstname() {
      return firstname;
   }

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

   public String getLastname() {
      return lastname;
   }

   public void setLastname(String lastname) {
      this.lastname = lastname;
   }

   public String getMiddlename() {
      return middlename;
   }

   public void setMiddlename(String middlename) {
      this.middlename = middlename;
   }
}


My probleme is that I'd like tio use an Address UserType:
Code:
public class AddressUserType extends OracleObjectUserType<Address> {
   
   public AddressUserType() {
      super();
      setClazz(Address.class);
      setDB_OBJECT_TYPE("OADDRESS");
   }
}

with an associated bean:
Code:
public class Address {
   private String address = null;

   private String city = null;

   private String zipcode = null;
   
   private Long state = null;
   
   private Long country = null;
   
   public Address(){}

   public Address(String address, String city, Long country, Long state, String zipcode) {
      this.address = address;
      this.city = city;
      this.country = country;
      this.state = state;
      this.zipcode = zipcode;
   }

   public String getAddress() {
      return address;
   }

   public void setAddress(String address) {
      this.address = address;
   }

   public String getCity() {
      return city;
   }

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

   public Long getCountry() {
      return country;
   }

   public void setCountry(Long country) {
      this.country = country;
   }

   public Long getState() {
      return state;
   }

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

   public String getZipcode() {
      return zipcode;
   }

   public void setZipcode(String zipcode) {
      this.zipcode = zipcode;
   };
   
}

but I don't know how to map the country property to the column country of my oracle's object.. It's possible to have a constraint on oracle but how to do it with hibernate?
thanks for your help
Mickael


Top
 Profile  
 
 Post subject: RE
PostPosted: Thu Feb 23, 2006 12:48 pm 
Newbie

Joined: Fri Sep 09, 2005 11:09 am
Posts: 7
Location: Clermont-Ferrand
Somebody has the same problem?
Thanks
Mickael


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.