복붙노트

[SPRING] Hibernate와 PostgreSQL에서 UserType을 가진 배열 -> MappingException

SPRING

Hibernate와 PostgreSQL에서 UserType을 가진 배열 -> MappingException

Hibernate / JPA에서 배열을 처리하기 위해 UserType을 구현하는 클래스를 작성하려고합니다. 나는 다음의 게시물을 사용했다. hibernate와 Hibernate / JPA / HSQL로 postgres 배열을 매핑하는 방법 : 사용자 유형 ARRAY를위한 Dialect 매핑을 생성하여 솔루션을 빌드하는 방법. 나는 그것을 시험하기 위해 새로운 Spring Roo 프로젝트를 만들었다. 다음은 다른 파일입니다 (모든 Java 클래스는 패키지 테스트에 있습니다).

그리고 이제 stacktrace :

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.<init>(ClassPathXmlApplicationContext.java:139)
at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(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.<init>(SchemaExport.java:106)
at org.hibernate.impl.SessionFactoryImpl.<init>(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 파일은 정확한 dialect를 찾지 만 registerHibernateType (Types.ARRAY, "array")을 수행 한 후에 getTypeName (2003) 함수는 위의 에러를 던집니다. BTW, 최대 절전 모드 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

명백하게, 최대 절전 모드는 여전히 어레이가있는 테이블을 만드는 방법을 모릅니다 ...

편집 2 :

postgresql은 내 칼럼이 "array"라는 사실을 싫어하는 것 같습니다. 나는 그것을 바꾼다. 테이블은 정수 배열로 hibernate에 의해 생성됩니다.

하지만 UserType 구현 문제로 인해 최대 절전 모드로 배열을 저장할 수 없습니다. 분명히 배열의 생성은 createArrayOf와 함께 실패합니다. 래퍼 대신 기본 연결에 액세스하라는 내용의이 스레드에 대한 일부 스레드를 읽습니다. 나는이 문제가 상당히 다르기 때문에 이것에 연결되는 새로운 스레드를 열 것이라고 생각한다.

stacktrace :

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이 작동합니다.

그러나 테이블 blabla에서 모든 항목을 가져올 때 여전히 문제가 있습니다. findAllBlablas 함수가 제대로 작동하지 않고 첫 번째 항목 만 반환합니다 ...

편집 4 :

실제로, 그것은 좋았지 만 Eclipse 콘솔은 모든 데이터를 인쇄 할 수 없었습니다. 그게 다야!

해결법

  1. ==============================

    1.

    __________ HibernateSessionFactory.xml ___________________________
    
        <property name="hibernateProperties">
            <props>
                <!-- <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop> -->
                <prop key="hibernate.dialect">com.test.model.PostgreSQLDialectArray</prop>              
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.generate_statistics">false</prop>
                <prop key="hibernate.connection.pool_size">10</prop>
                <prop key="hibernate.archive.autodetection">class</prop>
                <prop key="hibernate.hbm2ddl.auto">create</prop>                
                <prop key="cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
            </props>
        </property>
    
    
    
        ______________ PostgreSQLDialectArray.java _______________________
    
    
    package com.test.model;
    
    import java.sql.Types;
    
    public class PostgreSQLDialectArray extends org.hibernate.dialect.PostgreSQL82Dialect{
    
        public PostgreSQLDialectArray() {
    
            super();    
    
            System.out.println("Register Hibernate Type ... ");
            registerHibernateType(Types.ARRAY, "array");
    
            System.out.println("Register Column Type ... ");
            registerColumnType(Types.ARRAY, "integer[]");
    
        }
    }
    
    
    
    _____________ CustomArrayType.java ______________________________
    
    
    package com.test.model;
    
    import java.io.Serializable;
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.sql.Types;
    import java.sql.Array;
    
    import org.hibernate.*;
    import org.hibernate.engine.spi.SessionImplementor;
    import org.hibernate.usertype.UserType;
    
     public class CustomArrayType 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, SessionImplementor session, 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, SessionImplementor session) 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 };
         }
    
    }
    
    
    
    ____________ MyClass.java ___________________________
    
    package com.test.model;
    
    import static javax.persistence.GenerationType.IDENTITY;
    
    import java.io.Serializable;
    import java.sql.Time;
    import java.sql.Timestamp;
    import java.sql.Types;
    import java.util.Date;
    import java.util.List;
    import java.util.Set;
    
    import javax.persistence.CascadeType;
    import javax.persistence.Column;
    import javax.persistence.Entity;
    import javax.persistence.EnumType;
    import javax.persistence.Enumerated;
    import javax.persistence.FetchType;
    import javax.persistence.GeneratedValue;
    import javax.persistence.Id;
    import javax.persistence.JoinColumn;
    import javax.persistence.JoinTable;
    import javax.persistence.ManyToMany;
    import javax.persistence.ManyToOne;
    import javax.persistence.OneToMany;
    import javax.persistence.Table;
    
    import org.hibernate.annotations.Type;
    
    @Entity
    @Table(name = "MyClass")
    public class MyClass implements Serializable {
    
        private static final long serialVersionUID = -2520209406925143850L;
    
        @Id
        @GeneratedValue(strategy = IDENTITY)
        private Long id;
    
        @Type(type = "com.test.model.CustomArrayType")
        @Column(name = "arrayDay", nullable = true)
        private int[] arrayDay;           
    
        public Long getId() {
        return id;
        }
    
        public void setId(Long id) {
        this.id = id;
        }
    
        public int[] getArrayDay() {
            return arrayDay;
        }
    
        public void setArrayDay(int[] arrayDay) {
            this.arrayDay = arrayDay;
        }  
    
    }
    
    
    
    ______________ ArrayTypeTests.java ___________________________
    
    
    
    package com.test;
    
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    
    import com.test.model.MyClass;
    import com.test.service.MyClassService;
    
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = { "classpath:application-context.xml" })
    public class ArrayTypeTests implements ApplicationContextAware {
    
        @Autowired
        private MyClassService myClassService;
    
        public static ApplicationContext ctx;
    
        @Test
        public void test_() {
           System.out.println("Test junit");
        }
    
        @Test
        public void test_arrayDays() {
    
        System.out.println("\n - Start test_array - ");
        MyClass myClass = myClassService.getMyClassById(1L);
        if (myClass != null) {
            int[] array = myClass.getArrayDay();
            System.out.println("\n valor1:" + array[0]);
            System.out.println("\n valor2:" + array[1]);
            System.out.println("\n\n test_array OK ");
        } else {
            System.out.println("\n ERROR");
        }
        System.out.println("\n - End test_array - ");
    
        }
    
        @Override
        public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ctx = applicationContext;
        }
    
    }
    
  2. ==============================

    2.편집 3의 솔루션 옆에 dbcp 또는 c3p0과 같은 연결 풀링을 사용하지 않을 때 완벽하게 작동합니다. - dbcp로 작업하고 있습니다.

    편집 3의 솔루션 옆에 dbcp 또는 c3p0과 같은 연결 풀링을 사용하지 않을 때 완벽하게 작동합니다. - dbcp로 작업하고 있습니다.

    가능한 해결책은 c3p0을 사용할 때 proxool을 사용하는 것입니다. proxool이 createArrayOf ()를 처리 할 수 ​​있으므로 문제가 없어야합니다.

    또 다른 방법은 다음과 같습니다.

        C3P0ProxyConnection connection = (C3P0ProxyConnection) _statement.getConnection();
        Method method = Connection.class.getMethod("createArrayOf", new Class[] { String.class, Object[].class });
        Array array = (Array) connection.rawConnectionOperation(
            method, C3P0ProxyConnection.RAW_CONNECTION, new Object[] {"integer", intArray});
        _statement.setArray(_i, array);
    

    jdbc 클래스에서 기본 함수를 가져와야합니다. 그러므로 getMethod로 가져 와서 리플렉션으로 사용하십시오.

  3. from https://stackoverflow.com/questions/14219498/array-with-usertype-in-hibernate-and-postgresql-mappingexception by cc-by-sa and MIT license