Массив с UserType в Hibernate и PostgreSQL -> MappingException

Я пытаюсь написать класс, реализующий UserType для работы с массивами в Hibernate / JPA. Я использовал следующие постыотображение массива postgres с помощью hibernate а такжеHibernate / JPA / HSQL: как создать отображение диалекта для типа пользователя ARRAY построить решение, но я не могу заставить его работать. Я создал новый проект Spring Roo, чтобы проверить его. Вот разные файлы (все классы Java находятся в тесте пакета):

persistence.xml



  
    org.hibernate.ejb.HibernatePersistence
    
    
    
    
    
    
    
    
    
    
    
  

TestArray.java

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.setTest(array);
          //         blabla.persist();
          //        System.out.println(Arrays.toString(blabla.getTest()));

         System.out.println(java.sql.Types.ARRAY);
         System.out.println("Done");
     }
}

Blabla.java

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")
    private int[] array;
}

PostgreSQLDialectArray

package test;

import java.sql.Types;


public class PostgreSQLDialectArray extends org.hibernate.dialect.PostgreSQLDialect{

    public PostgreSQLDialectArray() { 
        super(); 
        registerHibernateType(Types.ARRAY, "array"); 
    }
 }

IntArrayUserType.java (в основном то же, что и вотображение массива postgres с помощью hibernate)

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 returnedClass() {
        return int[].class;
    }

    @Override
    public int[] sqlTypes() {
        return new int[] { SQLTYPE };
    }
}

А теперь трассировка стека:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [META-INF/spring/applicationContext.xml]: Cannot resolve reference to bean 'entityManagerFactory' while setting bean property 'entityManagerFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [META-INF/spring/applicationContext.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: persistenceUnit] Unable to build EntityManagerFactory
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1325)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1086)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:580)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.(ClassPathXmlApplicationContext.java:83)
at test.TestArray.main(TestArray.java:29)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [META-INF/spring/applicationContext.xml]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: persistenceUnit] Unable to build EntityManagerFactory
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1420)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:322)
... 15 more
Caused by: javax.persistence.PersistenceException: [PersistenceUnit: persistenceUnit] Unable to build EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:915)
at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:74)
at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:225)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:308)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1477)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1417)
... 22 more
Caused by: org.hibernate.MappingException: No Dialect mapping for JDBC type: 2003
at org.hibernate.dialect.TypeNames.get(TypeNames.java:77)
at org.hibernate.dialect.TypeNames.get(TypeNames.java:100)
at org.hibernate.dialect.Dialect.getTypeName(Dialect.java:296)
at org.hibernate.mapping.Column.getSqlType(Column.java:208)
at org.hibernate.mapping.Table.sqlCreateString(Table.java:418)
at org.hibernate.cfg.Configuration.generateSchemaCreationScript(Configuration.java:1099)
at org.hibernate.tool.hbm2ddl.SchemaExport.(SchemaExport.java:106)
at org.hibernate.impl.SessionFactoryImpl.(SessionFactoryImpl.java:372)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1872)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:906)
... 27 more

Поэтому я полагаю, что созданный мной диалект не используется вообще или является неправильным, но я нене знаю почему. Я думаю, что аннотация @Type должна выполнять сопоставление, но я видел некоторые теги, но я не знаю, нужны ли они в этом примере, и если они есть, где они у меня были? Это'Прошло уже два дня, как я застрял с этой проблемой, и я впадаю в отчаяние. Не могли бы вы помочь мне отладить эту программу? Пожалуйста. Заранее большое спасибо.

Изменить 0:

Файл persistence.xml, похоже, находит правильный диалект, но функция getTypeName (2003) выдает ошибки выше после выполнения registerHibernateType (Types.ARRAY, "массив»). Кстати, я использую Hibernate 3.6.4.Final и postgresql 8.4-702.jdbc3.

Изменить 1:

Я добавил следующую строку в конструктор PostgreSQLDialectArray:

registerColumnType(Types.ARRAY, "integer[$l]" ); 

который, кажется, частично решает проблему. Однако теперь я получаю еще одну ошибку:

2013-01-09 11:14:30,281 [main] ERROR org.hibernate.tool.hbm2ddl.SchemaExport - Unsuccessful: create table blabla (id int8 not null, array int[255], name varchar(255), test int4 not null, version int4, primary key (id))
2013-01-09 11:14:30,282 [main] ERROR org.hibernate.tool.hbm2ddl.SchemaExport - ERREUR: erreur de syntaxe sur ou près de « array »
  Position: 40

Судя по всему, hibernate до сих пор не знает, как создать таблицу с массивом в нем ...

Изменить 2:

Похоже, что postgresql не сделалне нравится тот факт, что моя колонка называласьмассив», Я изменил это, и это сработало. Таблица создана в спящем режиме с массивом целых чисел.

НО я не могу сохранить в нем какой-либо массив с помощью Hibernate из-за проблемы в реализации UserType. По-видимому, создание массива завершается неудачно с помощью createArrayOf. Я читаю некоторые темы по этому вопросу, рассказывающие о доступе к базовому соединению вместо оболочки. Я думаю, что я собираюсь открыть новый поток, ссылающийся на этот, потому что эта проблема совершенно другая.

Трассировка стека:

Exception in thread "main" java.lang.AbstractMethodError: org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.createArrayOf(Ljava/lang/String;[Ljava/lang/Object;)Ljava/sql/Array;
at test.IntArrayUserType.nullSafeSet(IntArrayUserType.java:59)
at org.hibernate.type.CustomType.nullSafeSet(CustomType.java:140)
at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2184)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2430)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2874)
at org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:79)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:184)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:76)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:467)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
at org.springframework.transaction.aspectj.AbstractTransactionAspect.ajc$afterReturning$org_springframework_transaction_aspectj_AbstractTransactionAspect$3$2a73e96c(AbstractTransactionAspect.aj:78)
at test.Blabla_Roo_Entity.ajc$interMethod$test_Blabla_Roo_Entity$test_Blabla$persist(Blabla_Roo_Entity.aj:56)
at test.Blabla.persist(Blabla.java:1)
at test.Blabla_Roo_Entity.ajc$interMethodDispatch1$test_Blabla_Roo_Entity$test_Blabla$persist(Blabla_Roo_Entity.aj)
at test.TestArray.main(TestArray.java:39)

Изменить 3:

Наконец, после следующих изменений, UserType для целочисленных массивов работает:

Добавьте эту строку в applicationContext.xml в:



....





Изменить nullSafeSet из IntArrayUserType

    @Override
    public void nullSafeSet(final PreparedStatement statement, final Object object, final int i) throws HibernateException, SQLException {
        Connection connection = statement.getConnection();
        int[] castObject = (int[]) object;
        Integer[] integers = toObject(castObject);
        Connection conn = ((DelegatingConnection) connection).getInnermostDelegate();
        Array array = conn.createArrayOf("integer", integers);
        statement.setArray(i, array);
    }

НО все еще существует проблема при получении всех записей из таблицы blabla: функция findAllBlablas не работает должным образом и возвращает только первую запись ...

Изменить 4:

На самом деле, он работал отлично, но консоль eclipse не смогла распечатать все данные. Тот'все!

Ответы на вопрос(2)

Ваш ответ на вопрос