2016-02-05 180 views
-2

我試圖實現Hibernate映射到Oracle默認安裝提供的示例架構(Order Entry) orderentry架構有幾個表其中一個是Customer表,它具有很少的列作爲customTyped列,例如 自定義類型是使用以下語句創建的;實現自定義休眠類型

CREATE OR REPLACE TYPE "CUST_ADDRESS_TYP" AS OBJECT 
(street_address  VARCHAR2(40) 
, postal_code  VARCHAR2(10) 
, city    VARCHAR2(30) 
, state_province  VARCHAR2(10) 
, country_id   CHAR(2) 
); 

和客戶表與下面的語句

CREATE TABLE OE.CUSTOMERS 
( 
CUSTOMER_ID NUMBER (6) NOT NULL , 
CUST_FIRST_NAME VARCHAR2 (20 BYTE) 
CONSTRAINT CUST_FNAME_NN NOT NULL , 
CUST_LAST_NAME VARCHAR2 (20 BYTE) 
CONSTRAINT CUST_LNAME_NN NOT NULL , 
CUST_ADDRESS OE.CUST_ADDRESS_TYP , 
) 

創建我才知道,我們需要從here實現UserType接口,但是當我試圖找回它是給錯誤

org.hibernate.MappingException: property mapping has wrong number of columns: com.dto.oe.Customers.cust_addressData type: com.dto.oe.CustAddressType 
      at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:497) 
at org.hibernate.mapping.RootClass.validate(RootClass.java:270) 
at org.hibernate.cfg.Configuration.validate(Configuration.java:1360) 
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1851) 
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930) 
at com.test.connection.HibernateUtil.getSession(HibernateUtil.java:82) 
at com.test.connection.HibernateUtil.getCustomer(HibernateUtil.java:70) 
at com.test.connection.HibernateUtil.main(HibernateUtil.java:18) 

Wheras my Customtype對象pojo類是Cust_addressData和實現usert的類YPE接口是CustAddressType

import java.io.Serializable; 
    import java.sql.PreparedStatement; 
    import java.sql.ResultSet; 
    import java.sql.ResultSetMetaData; 
    import java.sql.SQLException; 
    import java.sql.Types; 

    import org.hibernate.HibernateException; 
    import org.hibernate.engine.spi.SessionImplementor; 
    import org.hibernate.usertype.UserType; 

    public class CustAddressType implements UserType { 
    /** 
    * Returns the object from the 2 level cache 
    */ 
    public Object assemble(Serializable cached, Object owner) 
      throws HibernateException { 
     return cached; 
    } 

    /** 
    * Used to create Snapshots of the object 
    */ 
    public Object deepCopy(Object value) throws HibernateException { 
     final Cust_addressData recievedParam = (Cust_addressData) value; 
     final Cust_addressData addressData = new Cust_addressData(recievedParam); 
     return addressData; 
    } 

    /** 
    * method called when Hibernate puts the data in a second level cache. The 
    * data is stored in a serializable form 
    */ 
    public Serializable disassemble(final Object value) 
      throws HibernateException { 
     return (Serializable) value; 
    } 

    public boolean equals(final Object o1, final Object o2) 
      throws HibernateException { 
     boolean isEqual = false; 
     if (o1 == o2) { 
      isEqual = true; 
     } 
     if (null == o1 || null == o2) { 
      isEqual = false; 
     } else { 
      isEqual = o1.equals(o2); 
     } 
     return isEqual; 
     // for this to work correctly the equals() 
     // method must be implemented correctly by Cust_addressData class 
    } 

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

    public boolean isMutable() { 
     return true; 
    } 

    public Object nullSafeGet(final ResultSet resultSet, final String[] names, 
      SessionImplementor sessionImp, final Object owner) 
      throws HibernateException, SQLException { 

     // owner here is class from where the call to retrieve data was made. 
     // In this case the Test class 

     Cust_addressData addresssData = new Cust_addressData(); 
     // Order of columns is given by sqlTypes() method 
     if (!resultSet.wasNull()) { 


      final String street_address = resultSet.getString(names[0]); 
      final String postal_code = resultSet.getString(names[1]); 
      final String city = resultSet.getString(names[2]); 
      final String state_province = resultSet.getString(names[3]); 
      final String country_id = resultSet.getString(names[4]); 

      addresssData.setCity(city); 
      addresssData.setCountry_id(country_id); 
      addresssData.setPostal_code(postal_code); 
      addresssData.setState_province(state_province); 
      addresssData.setStreet_address(street_address); 
      System.out.println("street_address "+street_address +" names "+names[0]); 
     } else { 
      System.err.println("resultSet is null in CustAddressType"); 
     } 
     return addresssData; 
    } 

    public void nullSafeSet(final PreparedStatement statement, final Object value, final int index, 
      SessionImplementor arg3) throws HibernateException, SQLException { 
     if (null == value) { 
      statement.setNull(index, Types.VARCHAR); 
      statement.setNull(index + 1, Types.VARCHAR); 
      statement.setNull(index + 2, Types.VARCHAR); 
      statement.setNull(index + 3,Types.VARCHAR); 
      statement.setNull(index + 4,Types.VARCHAR); 
     } else { 
      Cust_addressData addressData = (Cust_addressData) value; 

      if (null != addressData.getStreet_address()) { 
       String street_address = new String(addressData.getStreet_address()); 
       statement.setString(index , street_address); 
      } else { 
       statement.setNull(index , Types.VARCHAR); 
      } 

      if (null != addressData.getPostal_code()) { 
       String postal_Code = new String(addressData.getPostal_code()); 
       statement.setString(index+1 , postal_Code); 
      } else { 
       statement.setNull(index +1, Types.VARCHAR); 
      } 

      if (null != addressData.getCity()) { 
      String city = new String(addressData.getCity()); 
       statement.setString(index+2 , city); 
      } else { 
       statement.setNull(index +2, Types.VARCHAR); 
      } 

      if (null != addressData.getState_province()) { 
      String postal_Code = new String(addressData.getState_province()); 
       statement.setString(index+3 , postal_Code); 
      } else { 
       statement.setNull(index +3, Types.VARCHAR); 
      } 


      if (null != addressData.getCountry_id()) { 
      String postal_Code = new String(addressData.getCountry_id()); 
       statement.setString(index+4 , postal_Code); 
      } else { 
       statement.setNull(index +4, Types.VARCHAR); 
      } 

     } 

    } 

    public Object replace(final Object original, final Object target, 
      final Object owner) throws HibernateException { 
     return this.deepCopy(original); 
    } 

    @SuppressWarnings("rawtypes") 
    public Class returnedClass() { 
     return Cust_addressData.class; 
    } 

    public int[] sqlTypes() { 
     return new int[] { Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, 
       Types.VARCHAR, Types.VARCHAR }; 
    } 
} 
 import java.io.Serializable; 
    import javax.persistence.Column; 
    import javax.persistence.Entity; 
    import javax.persistence.Table; 
    @SuppressWarnings("serial") 
    @Entity 
    @Table(name="CUST_ADDRESS_TYP") 
    public class Cust_addressData implements Serializable { 
    /** 
    * 
    */ 
private static final long serialVersionUID = 1L; 
    @Column(name = "street_address") 
    private String street_address; 
    @Column(name = "postal_code") 
    private String postal_code; 
    @Column(name = "city") 
    private String city; 
    @Column(name = "state_province") 
    private String state_province; 
    @Column(name = "country_id") 
    private String country_id; 

    public Cust_addressData() { 
    } 

    public Cust_addressData(Cust_addressData other) { 
     this.setCity(other.getCity()); 
     this.setCountry_id(other.getCountry_id()); 
     this.setPostal_code(other.getPostal_code()); 
     this.setStreet_address(other.getStreet_address()); 
     this.setState_province(other.getState_province()); 

    } 

    public String getStreet_address() { 
     return street_address; 
    } 

    public void setStreet_address(String street_address) { 
     this.street_address = street_address; 
    } 

    public String getPostal_code() { 
     return postal_code; 
    } 

    public void setPostal_code(String postal_code) { 
     this.postal_code = postal_code; 
    } 

    public String getCity() { 
     return city; 
    } 

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

    public String getState_province() { 
     return state_province; 
    } 

    public void setState_province(String state_province) { 
     this.state_province = state_province; 
    } 

    public String getCountry_id() { 
     return country_id; 
    } 

    public void setCountry_id(String country_id) { 
     this.country_id = country_id; 
    } 

    @Override 
    public boolean equals(Object obj) { 

     boolean isEqual = false; 
     if (obj instanceof Cust_addressData) { 
      Cust_addressData addressData = (Cust_addressData) obj; 

      isEqual = addressData.getCity().equals(this.getCity()) 
        && addressData.getState_province().equals(this.getState_province()) 
        && addressData.getCountry_id().equals(this.getCountry_id()) 
        && addressData.getPostal_code().equals(this.getPostal_code()) 
        && addressData.getStreet_address().equals(this.getStreet_address()) 
        ; 
     } 
     return isEqual; 
    } 

    @Override 
    public int hashCode() { 
     int hash = this.getCountry_id().hashCode(); 
     hash = hash * 17 + this.getPostal_code().hashCode(); 
     hash = hash * 31 + this.getStreet_address().hashCode(); 
     hash = hash * 13 + this.getState_province().hashCode(); 
     hash = hash * 14 + this.getCity().hashCode(); 
     return hash; 
    } 

    @Override 
    public String toString() { 

     return "[ " + this.getClass() + " { city : " + city 
       + ", street_address: " + street_address + ", postal_code: " 
       + postal_code + ", state_province: " + state_province + "" 
         + ",country_id :"+country_id+"}]"; 
    } 
} 

全來源:

還有一個觀察是的SQLType方法是在CustAddressType類

 public int[] sqlTypes() { 
      return new int[] { Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, 
        Types.VARCHAR, Types.VARCHAR }; 
     } 

是正在返回的列數的一個,如果我讓它返回只有一列,我發現了列值作爲空。

不知道什麼是布萊恩錯了,我哪裏做錯了或任何線索將

+0

可能:http://stackoverflow.com/questions/23942960/hibernate-compositeusertype-mapping-has-wrong-列數 – 2016-02-08 06:26:07

+0

我已經實現了UserType接口而不是CompositeUserType ..此外我也嘗試過使用CompositeUserType,但問題依然存在。 –

+0

你有沒有試過[這篇博文](http://dinukaroshan.blogspot.co。uk/2009/08/hibernate-and-oracle-user-defined-types.html)儘可能接近? –

回答

5

在我的CustAddressType類中使用STRUCT類已解決了CustAddressType類的源代碼問題,如下所示。

import java.io.Serializable; 
import java.sql.Connection; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Struct; 
import java.sql.Types; 

import oracle.sql.STRUCT; 
import oracle.sql.StructDescriptor; 

import org.hibernate.HibernateException; 
    import org.hibernate.engine.spi.SessionImplementor; 
    import org.hibernate.usertype.UserType; 

public class CustAddressType implements UserType { 
    private static final int SQL_TYPE = Types.STRUCT; 
    private static final String OBJECT_TYPE = "CUST_ADDRESS_TYP"; 
    /** 
    * Returns the object from the 2 level cache 
    */ 
    public Object assemble(Serializable cached, Object owner) 
     throws HibernateException { 
    return cached; 
} 

/** 
* Used to create Snapshots of the object 
*/ 
public Object deepCopy(Object value) throws HibernateException { 

    if (value == null) { 

     return null; 

    } 
    final Cust_addressData recievedParam = (Cust_addressData) value; 
    final Cust_addressData addressData = new Cust_addressData(recievedParam); 

    return addressData; 
} 

/** 
* method called when Hibernate puts the data in a second level cache. The 
* data is stored in a serializable form 
*/ 
public Serializable disassemble(final Object value) 
     throws HibernateException { 
    return (Serializable) value; 
} 

public boolean equals(final Object o1, final Object o2) 
     throws HibernateException { 
    boolean isEqual = false; 
    if (o1 == o2) { 
     isEqual = true; 
    } 
    if (null == o1 || null == o2) { 
     isEqual = false; 
    } else { 
     isEqual = o1.equals(o2); 
    } 
    return isEqual; 
    // for this to work correctly the equals() 
    // method must be implemented correctly by Cust_addressData class 
} 

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

public boolean isMutable() { 
    return true; 
} 

public Object nullSafeGet(final ResultSet resultSet, final String[] names, 
     SessionImplementor sessionImp, final Object owner) 
     throws HibernateException, SQLException { 

    // owner here is class from where the call to retrieve data was made. 
    // In this case the Test class 

    final Cust_addressData addresssData = new Cust_addressData(); 

    final Struct struct = (Struct) resultSet.getObject(names[0]); 

    if (resultSet.wasNull()) { 

     return null; 

    } 
    addresssData.setCity((String)struct.getAttributes()[0]); 
    addresssData.setCountry_id((String)struct.getAttributes()[1]); 
    addresssData.setPostal_code((String)struct.getAttributes()[2]); 
    addresssData.setState_province((String)struct.getAttributes()[3]); 
    addresssData.setStreet_address((String)struct.getAttributes()[4]); 

    return addresssData; 
} 

public void nullSafeSet(final PreparedStatement statement, final Object value, final int index, 
     SessionImplementor arg3) throws HibernateException, SQLException { 
    if (value == null) { 

     statement.setNull(index, SQL_TYPE, OBJECT_TYPE); 

    } 
    else 
    { 
     final Cust_addressData addresssData = (Cust_addressData) value; 
     final Object[] values = new Object[] { addresssData.getCity(),addresssData.getCountry_id(), addresssData.getPostal_code(), 
       addresssData.getState_province(),addresssData.getStreet_address() }; 
     final Connection connection = statement.getConnection(); 
     final STRUCT struct = new STRUCT(StructDescriptor.createDescriptor(OBJECT_TYPE,connection), connection, values); 
     statement.setObject(index, struct, SQL_TYPE); 

    } 

} 

public Object replace(final Object original, final Object target, 
     final Object owner) throws HibernateException { 
    return this.deepCopy(original); 
} 

@SuppressWarnings("rawtypes") 
public Class returnedClass() { 
    return Cust_addressData.class; 
} 

public int[] sqlTypes() { 
    return new int[] {SQL_TYPE}; 
} 

}

由於@SteveChambers指點出來,

0

我的朋友認識到哪裏都是在Hibernate標註任何建議?你要清楚的名稱,包括你的表名定義每個字段...

import java.io.Serializable; 
@Entity 
@Table(name = "CUST_ADDRESS_TYP") 
public class Cust_addressData implements Serializable { 
/** 
* 
*/ 
private static final long serialVersionUID = 1L; 
    @Column(name ="column_name") 
private String street_address; 
    @Column(name ="column_name") 
private String postal_code; 
    @Column(name ="column_name") 
private String city; 
    @Column(name ="column_name") 
private String state_province; 
    @Column(name ="column_name") 
private String country_id; 

public Cust_addressData() { 
} 

public Cust_addressData(Cust_addressData other) { 
    this.setCity(other.getCity()); 
    this.setCountry_id(other.getCountry_id()); 
    this.setPostal_code(other.getPostal_code()); 
    this.setStreet_address(other.getStreet_address()); 
    this.setState_province(other.getState_province()); 

} 

public String getStreet_address() { 
    return street_address; 
} 

public void setStreet_address(String street_address) { 
    this.street_address = street_address; 
} 

public String getPostal_code() { 
    return postal_code; 
} 

public void setPostal_code(String postal_code) { 
    this.postal_code = postal_code; 
} 

public String getCity() { 
    return city; 
} 

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

public String getState_province() { 
    return state_province; 
} 

public void setState_province(String state_province) { 
    this.state_province = state_province; 
} 

public String getCountry_id() { 
    return country_id; 
} 

public void setCountry_id(String country_id) { 
    this.country_id = country_id; 
} 

@Override 
public boolean equals(Object obj) { 

    boolean isEqual = false; 
    if (obj instanceof Cust_addressData) { 
     Cust_addressData addressData = (Cust_addressData) obj; 

     isEqual = addressData.getCity().equals(this.getCity()) 
       && addressData.getState_province().equals(this.getState_province()) 
       && addressData.getCountry_id().equals(this.getCountry_id()) 
       && addressData.getPostal_code().equals(this.getPostal_code()) 
       && addressData.getStreet_address().equals(this.getStreet_address()) 
       ; 
    } 
    return isEqual; 
} 

@Override 
public int hashCode() { 
    int hash = this.getCountry_id().hashCode(); 
    hash = hash * 17 + this.getPostal_code().hashCode(); 
    hash = hash * 31 + this.getStreet_address().hashCode(); 
    hash = hash * 13 + this.getState_province().hashCode(); 
    hash = hash * 14 + this.getCity().hashCode(); 
    return hash; 
} 

@Override 
public String toString() { 

    return "[ " + this.getClass() + " { city : " + city 
      + ", street_address: " + street_address + ", postal_code: " 
      + postal_code + ", state_province: " + state_province + "" 
        + ",country_id :"+country_id+"}]"; 
} 

嘗試把正確的名稱爲每列上的每個變量的頂部,不要把它公開..好運

+0

我試着實現你的改變仍然問題仍然是一樣的...通過查看堆棧跟蹤任何想法出了什麼問題? –

+0

您能否在這裏把堆棧跟蹤的結果放在這裏? – Faisal

+0

你確定你把正確的列名稱的地方,我提到「column_name」? @Column(name =「column_name」)完成後顯示控制檯結果,我可以幫助你進一步.. – Faisal