Hibernate + PostgreSQL + Network Address Type (inet, cdir)

I started my example with Hibernate 4.2.7 and PostgreSQL 9.3.1, and everything is going well.

At the moment, I would like to use the INET PostgreSQL type , but I cannot match it with Hibernate.

I got this hibernation error: Could not determine type for: inet, at table: DEVICE_IP_ADDRESS, for columns ...

I am using org.hibernate.dialect.PostgreSQLDialect and hbm.xml configuratiin files.

My hibernation mapping file:

<property name="ipAddress" type="inet"> <column name="IP_ADDRESS" not-null="true" /> </property> 

I asked google, but I could not find any usable solution. could you help me?

thanks!

EDIT: What do you think the ORM implementation I need to use if I want to use the "extra" postgresql types and PostGIS types?

Or do I need to use plain JDBC?

+6
source share
2 answers

I recently ran into a similar problem with Hibernate 3 and Postgres 9. Since hibernate did not have the built-in mapping provided for String Array, in postgres for Java String [], I ended up implementing a custom mapping class. You can try the following steps.

  • Create a custom class "PgInet" that implements "org.hibernate.usertype.UserType" (this UserType class corresponds to knowledge of sleep mode 3. Not sure if this has been changed in Hibernate 4).
  • The implementation of the method will be implemented below.

    • is equal to
    • nullSafeGet
    • nullSafeSet
    • returnedClass return InetAddress.class;
    • SQLTypes return new int [] {java.sql.Types.}

Once the above is done, we just need to set the property type in HBM.xml for this class, i.e. PgInet.

To implement a custom class, try accessing an implementation class of an existing type. You should be able to find class files. Use the link below as a link.

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

Hope this helps.

Thanks.

+2
source

I just solve a problem like yours.There is little information about this. As @ ms03 said ... the best way is to create a new type and class that implements this type and a java object handler for setting / receiving the database.

First on your entity you must declare types for your parameters.

 @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 } 

Second, create a new object processed for java, it should get the default construct, the constructor for processing data from the database, and be 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 } 

And at the last stage you should create a custom type

 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 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); } } 

This method works fine for me when I insert or retrieve a row from a DB.

+5
source

Source: https://habr.com/ru/post/958201/


All Articles