Ale*_*lex 15 java arrays postgresql spring hibernate
我正在尝试编写一个实现UserType的类来处理Hibernate/JPA中的数组.我使用以下帖子 使用hibernate和Hibernate/JPA/HSQL 映射postgres数组:如何为用户类型ARRAY创建Dialect映射以构建解决方案,但我无法使其工作.我创建了一个新的Spring Roo项目来测试它.以下是不同的文件(所有java类都位于包测试中):
persistence.xml中
<?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>
Run Code Online (Sandbox Code Playgroud)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");
}
}
Run Code Online (Sandbox Code Playgroud)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;
}
Run Code Online (Sandbox Code Playgroud)PostgreSQLDialectArray
package test;
import java.sql.Types;
public class PostgreSQLDialectArray extends org.hibernate.dialect.PostgreSQLDialect{
public PostgreSQLDialectArray() {
super();
registerHibernateType(Types.ARRAY, "array");
}
}
Run Code Online (Sandbox Code Playgroud)IntArrayUserType.java(基本上与使用hibernate映射postgres数组时相同)
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 };
}
}
Run Code Online (Sandbox Code Playgroud)现在堆栈跟踪:
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
Run Code Online (Sandbox Code Playgroud)
所以我想我创造的方言根本没用或者错了,但我不知道为什么.我认为@Type注释应该进行映射,但是我已经看到了一些标签,但我不知道它们是否在这个例子中是否需要,如果它们是,我在哪里有它们?已经有两天我遇到了这个问题而且我变得绝望了.你能帮我调试这个程序吗?请.非常感谢你提前.
编辑0:
persistence.xml文件似乎找到了正确的方言,但函数getTypeName(2003)在执行registerHibernateType(Types.ARRAY,"array")之后抛出上述错误.顺便说一下,我正在使用Hibernate 3.6.4.Final和postgresql 8.4-702.jdbc3.
编辑1:
我将以下行添加到PostgreSQLDialectArray构造函数中:
registerColumnType(Types.ARRAY, "integer[$l]" );
Run Code Online (Sandbox Code Playgroud)
这似乎部分解决了这个问题.但是,现在我又收到了另一个错误:
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
Run Code Online (Sandbox Code Playgroud)
显然,hibernate仍然不知道如何创建一个包含数组的表...
编辑2:
似乎postgresql不喜欢我的专栏被称为"数组"的事实.我改变它,它的工作原理.该表由hibernate创建,带有一个整数数组.
但由于UserType实现中存在问题,我无法使用hibernate保存任何数组.显然,使用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)
Run Code Online (Sandbox Code Playgroud)
编辑3:
最后,经过以下修改后,整数数组的UserType可以工作:
在applicationContext.xml中添加以下行:
<bean class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" id="dataSource">
....
<property name="accessToUnderlyingConnectionAllowed" value="true" />
</bean>
从IntArrayUserType修改nullSafeSet
@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);
}
Run Code Online (Sandbox Code Playgroud)但是从表blabla获取所有条目时仍然存在问题:函数findAllBlablas无法正常工作,只返回第一个条目...
编辑4:
事实上,它工作得很好但是eclipse控制台无法打印所有数据.就这样!
除了编辑 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);
Run Code Online (Sandbox Code Playgroud)
您需要从 jdbc 类获取底层函数。因此,通过反射来获取它getMethod并使用它。
| 归档时间: |
|
| 查看次数: |
11353 次 |
| 最近记录: |