Hibernate + PostgreSQL +网络地址类型(inet,cdir)

我已经用Hibernate 4.2.7和PostgreSQL 9.3.1开始了我的示例项目,一切进展顺利。

目前我想使用INET PostgreSQL类型,但我无法使用Hibernate进行映射。

我得到了这个hibernate错误: 无法确定类型:inet,在表:DEVICE_IP_ADDRESS,对于列…

我使用org.hibernate.dialect.PostgreSQLDialect和hbm.xml配置文件。

我的hibernate映射文件:

   

我问谷歌,但我找不到任何有用的解决方案。 你可以帮帮我吗?

谢谢!

编辑:如果我想使用’额外’postgresql类型和PostGIS类型,你认为我需要使用什么样的ORM实现?

或者我需要使用简单的JDBC?

我最近遇到了与Hibernate 3和Postgres 9类似的问题。由于hibernate没有为post String中的字符串数组提供内置映射到Java String [],我最终实现了一个自定义映射类。 您可以尝试以下步骤。

  1. 创建实现“org.hibernate.usertype.UserType”的自定义类“PgInet”(这个UserType类是根据我的hibernate 3知识。不确定在Hibernate 4中是否已经更改)。
  2. 下面的方法实现是至关重要的。

    • 等于
    • nullSafeGet
    • nullSafeSet
    • returnedClass返回InetAddress.class;
    • sqlTypes返回new int [] {java.sql.Types。}

完成上述操作后,我们只需要将HBM.xml中的属性类型设置为此类即PgInet。

对于自定义类实现,请尝试引用现有的类型实现类。 您应该能够找到类文件。 使用以下链接作为参考。

http://grepcode.com/file/repo1.maven.org/maven2/hibernate/hibernate/2.1.8/net/sf/hibernate/type/ArrayType.java

希望这可以帮助。

谢谢。

我只是解决了像你这样的问题。关于此事的信息很少。 正如@ 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插入或获取一行时,这种方式对我来说很好。