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