Hi,
I am trying to write a class implementing UserType to deal with integer arrays in Hibernate/JPA but I cannot get it to work. I am using Hibernate 3.6.4.Final and postgresql 8.4-702.jdbc3.
I created a new Spring Roo project just to test it. Here are the different files (all java classes are located in the package test):
persistence.xml
Code:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="persistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<properties>
<!-- <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> -->
<property name="hibernate.dialect" value="test.PostgreSQLDialectArray"/>
<!-- value="create" to build a new database on each run; value="update" to modify an existing database; value="create-drop" means the same as "create" but also drops tables when Hibernate closes; value="validate" makes no changes to the database -->
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="hibernate.ejb.naming_strategy" value="org.hibernate.cfg.ImprovedNamingStrategy"/>
<property name="hibernate.connection.charSet" value="UTF-8"/>
<!-- Uncomment the following two properties for JBoss only -->
<!-- property name="hibernate.validator.apply_to_ddl" value="false" /-->
<!-- property name="hibernate.validator.autoregister_listeners" value="false" /-->
</properties>
</persistence-unit>
</persistence>
TestArray.java
Code:
package test;
import java.math.BigInteger;
import java.security.SecureRandom;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.serializable.RooSerializable;
import org.springframework.roo.addon.tostring.RooToString;
@RooJavaBean
@RooToString
@RooSerializable
public class TestArray {
private static final long serialVersionUID = 1L;
private SecureRandom random = new SecureRandom();
public String nextSessionId()
{
return new BigInteger(130, random).toString(32);
}
public static void main(String[] args) {
ApplicationContext context;
context = new ClassPathXmlApplicationContext("classpath:META-INF/spring/applicationContext.xml");
int[] array = new int[1428];
TestArray test = new TestArray();
Blabla blabla = new Blabla();
int nb = 1428;
for(int i = 0 ; i < nb ; i++)
array[i] = test.random.nextInt();
//blabla.setArray(array);
//blabla.persist();
System.out.println("Done");
}
}
Blabla.java
Code:
package test;
import org.hibernate.annotations.Type;
import org.springframework.roo.addon.entity.RooEntity;
import org.springframework.roo.addon.javabean.RooJavaBean;
import org.springframework.roo.addon.tostring.RooToString;
@RooJavaBean
@RooToString
@RooEntity
public class Blabla {
@Type(type = "test.IntArrayUserType")
@Column(length = 1428)
private int[] array;
}
PostgreSQLDialectArray
Code:
package test;
import java.sql.Types;
public class PostgreSQLDialectArray extends org.hibernate.dialect.PostgreSQLDialect{
public PostgreSQLDialectArray() {
super();
registerHibernateType(Types.ARRAY, "array");
registerColumnType(Types.ARRAY, "int[$l]" );
}
}
IntArrayUserType.java (basically the same than in http://stackoverflow.com/questions/1647583/mapping-a-postgres-array-with-hibernate/1647660#1647660)
Code:
package test;
import java.io.Serializable;
import java.sql.Array;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;
public class IntArrayUserType implements UserType {
protected static final int SQLTYPE = java.sql.Types.ARRAY;
private int[] toPrimitive(Integer[] array){
int[] a = new int[array.length];
for(int i = 0 ; i < array.length ; i++)
a[i] = array[i];
return a;
}
private Integer[] toObject(int[] array){
Integer[] a = new Integer[array.length];
for(int i = 0 ; i < array.length ; i++)
a[i] = array[i];
return a;
}
@Override
public Object nullSafeGet(final ResultSet rs, final String[] names, final Object owner) throws HibernateException, SQLException {
Array array = rs.getArray(names[0]);
Integer[] javaArray = (Integer[]) array.getArray();
return toPrimitive(javaArray);
}
@Override
public void nullSafeSet(final PreparedStatement statement, final Object object, final int i) throws HibernateException, SQLException {
System.out.println("test null safe set...");
Connection connection = statement.getConnection();
int[] castObject = (int[]) object;
Integer[] integers = toObject(castObject);
Array array = connection.createArrayOf("integer", integers);
statement.setArray(i, array);
System.out.println("test null safe set...");
}
@Override
public Object assemble(final Serializable cached, final Object owner) throws HibernateException {
return cached;
}
@Override
public Object deepCopy(final Object o) throws HibernateException {
return o == null ? null : ((int[]) o).clone();
}
@Override
public Serializable disassemble(final Object o) throws HibernateException {
return (Serializable) o;
}
@Override
public boolean equals(final Object x, final Object y) throws HibernateException {
return x == null ? y == null : x.equals(y);
}
@Override
public int hashCode(final Object o) throws HibernateException {
return o == null ? 0 : o.hashCode();
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Object replace(final Object original, final Object target, final Object owner) throws HibernateException {
return original;
}
@Override
public Class<int[]> returnedClass() {
return int[].class;
}
@Override
public int[] sqlTypes() {
return new int[] { SQLTYPE };
}
}
Finally, the error that I get is the following:
Code:
2013-01-09 12:14:40,963 [main] ERROR org.hibernate.tool.hbm2ddl.SchemaExport - Unsuccessful: create table blabla (id int8 not null, array int[1428], version int4, primary key (id))
2013-01-09 12:14:40,963 [main] ERROR org.hibernate.tool.hbm2ddl.SchemaExport - ERREUR: erreur de syntaxe sur ou près de « array »
Position: 40
Hibernate cannot create the table with the array of integers but I do not know what I did wrong.
Could you help me please?
Thank you in advance.