我已经使用Hibernate 4.2.7和PostgreSQL 9.3.1启动了我的示例项目,一切进展顺利。
目前我想使用INET PostgreSQL type,但我无法使用Hibernate进行映射。
我遇到了这个休眠错误:无法确定类型:inet,在表:DEVICE_IP_ADDRESS,列...
我使用 org.hibernate.dialect.PostgreSQLDialect 和hbm.xml配置文件。
我的hibernate映射文件:
<property name="ipAddress" type="inet">
<column name="IP_ADDRESS" not-null="true" />
</property>
我问谷歌,但我找不到任何有用的解决方案。 你能帮帮我吗?
THX!
编辑: 如果我想使用'额外'postgresql类型和PostGIS类型,我认为我需要使用什么样的ORM实现?
或者我需要使用简单的JDBC?
答案 0 :(得分:5)
我只是解决了像你这样的问题。关于此事的信息很少。正如@ ms03所说...更好的方法是创建一个新类型和一个实现此类型的类,并处理java对象以设置/获取数据库。
首先在您的实体上,您必须为您的实体声明类型。
@Entity
@Table(name="user_app")
@TypeDefs(value={@TypeDef(name="convertInet",typeClass=PgInetType.class),
@TypeDef(name="convertMacaddr",typeClass=PgMacaddrType.class)})
public class User implements Serializable {
//some parameters
@Type(type="convertMacaddr")
private PgMacaddr mac;
@Type(type="convertInet")
private PgInet ip;
//getters and setters, equals, hashcode, toString
}
第二个创建为java处理的新对象,它必须有一个默认构造,一个从DB处理数据的构造,并且是Seriarizable。
public class PgInet implements Serializable {
private static final long serialVersionUID = 1L;
private String address;
public PgInet(String address){
this.address=address;
}
public PgInet(){
this.address=null;
}
//Getters,setters,hashcode, equal and toString
}
最后一步你必须创建一个自定义类型
public class PgInetType implements UserType{
@Override
public int[] sqlTypes() {
//Because inet,macaddr,cdir...and unkwon type for java, yo must
// define Types.OTHER
return new int[] { Types.OTHER };
}
@Override
public Class returnedClass() {
//Object created to be handled for java
return PgInet.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return ObjectUtils.nullSafeEquals(x, y);
}
@Override
public int hashCode(Object x) throws HibernateException {
if(x!=null)
return x.hashCode();
else
return 0;
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names,
SessionImplementor session, Object owner)
throws HibernateException, SQLException {
//Translation from DB to Java
PgInet address=null;
String ip=rs.getString(names[0]);
if(ip!=null){
address=new PgInet(ip);
}
return address;
}
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index,
SessionImplementor session) throws HibernateException, SQLException {
//Translation from java to DB
if(value==null){
st.setNull(index, Types.VARCHAR);
}else{
//As inet,macaddr,cdir...are new types object on Postgresql you must
//create the specific postgresql object and to insert it
//I created 2 new cast on postgresql: inet As varchar, varchar AS inet
//but I think it's not neccesary because macaddr type works fine without
//postgresl casting
st.setObject(index, getInet(value, st.getConnection()));
}
}
private Object getInet(Object value, Connection connection) {
//Expected object on postgresql
Object tempInet = null;
ClassLoader connectionClassLoader = connection.getClass().getClassLoader();
try {
//Class which will create the postgresql
Class aPGObjectClass =connectionClassLoader.loadClass("org.postgresql.util.PGobject");
Constructor ct = aPGObjectClass.getConstructor(null);
try {
tempInet = ct.newInstance(null);
} catch (InstantiationException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException e2) {
// TODO Auto-generated catch block
e2.printStackTrace();
}
Method setTypeMethod = aPGObjectClass.getMethod("setType", new Class[]{String.class});
try {
//Setting postgresql type, inet in this case
setTypeMethod.invoke(tempInet, new Object[]{"inet"});
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Method setValueMethod = aPGObjectClass.getMethod("setValue", new Class[]{String.class});
try {
setValueMethod.invoke(tempInet, new Object[]{value.toString()});
} catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (ClassNotFoundException e) {
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return tempInet;
}
@Override
public Object deepCopy(Object value) throws HibernateException {
if(value==null)
return null;
else{
PgInet PgInetNew=new PgInet();
PgInet PgInetOriginal=(PgInet)value;
PgInetNew.setAddress(PgInetOriginal.getAddress());
return PgInetNew;
}
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
Object deepCopy=deepCopy(value);
if(!(deepCopy instanceof Serializable))
return (Serializable)deepCopy;
return null;
}
@Override
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return deepCopy(cached);
}
@Override
public Object replace(Object original, Object target, Object owner)
throws HibernateException {
return deepCopy(original);
}
}
当我插入或从DB获取一行时,这种方式对我来说很好。
答案 1 :(得分:2)
我最近遇到了类似的问题,Hibernate 3&amp; Postgres 9.由于hibernate没有为post String中的String Array提供内置映射到Java String [],我最终实现了一个自定义映射类。您可以尝试以下步骤。
以下方法实施至关重要。
完成上述操作后,我们只需要将HBM.xml中的属性类型设置为此类,即PgInet。
对于自定义类实现,请尝试引用现有的类型实现类。您应该能够找到类文件。使用以下链接作为参考。
希望这有帮助。
感谢。