example entitymanagerfactory ejemplo java hibernate postgresql jpa jdbc

java - entitymanagerfactory - Corregir la anotación JPA para el tipo de texto de PostgreSQL sin anotaciones de Hibernate



java jpa example (3)

Como el tipo de text no forma parte del estándar SQL, no creo que haya una forma oficial de JPA.

Sin embargo, el tipo de text es bastante similar a varchar , pero sin el límite de longitud. Puede indicar la implementación de JPA con la propiedad de length de @Column :

@Column(length=10485760) private String description;

Actualización: 10 MiB parece ser la longitud máxima para varchar en postgresql. El text es casi ilimitado, según la documentation :

En cualquier caso, la cadena de caracteres más larga posible que se puede almacenar es de aproximadamente 1 GB.

Estoy desarrollando una aplicación usando:

  • Java 1.7
  • JPA (incluido en javaee-api 7.0)
  • Hibernate 4.3.8.Final
  • PostgreSQL-JDBC 9.4-1200-jdbc41
  • PostgreSQL 9.3.6

Y me gustaría utilizar el tipo de datos de texto PostgreSQL para algunos atributos de cadena. Por lo que sé, en JPA esta debería ser la anotación correcta, para usar texto en PostgreSQL:

@Entity public class Product{ ... @Lob private String description; .... }

Cuando anoto mi entidad de esta manera, me encuentro con errores que se ven así: http://www.shredzone.de/cilla/page/299/string-lobs-on-postgresql-with-hibernate-36.html

En resumen: parece que hibernate y jdbc no van de la mano para clob / text-types.

La solución descrita está funcionando:

@Entity public class Product{ ... @Lob @Type(type = "org.hibernate.type.TextType") private String description; ... }

Pero esto tiene un inconveniente importante: el código fuente necesita hibernación en tiempo de compilación, lo que debería ser innecesario (esa es una de las razones para usar JPA en primer lugar).

Otra forma es usar la anotación de columna como esta:

@Entity public class Product{ ... @Column(columnDefinition = "text") private String description; ... }

Lo cual funciona muy bien, PERO: ahora estoy atascado con bases de datos que tienen un tipo de texto (y también se llama texto;)) y si se usará otra base de datos en el futuro, las anotaciones se pueden pasar por alto fácilmente. Por lo tanto, el posible error puede ser difícil de encontrar, porque el tipo de datos se define en una Cadena y, por lo tanto, no se puede encontrar antes del tiempo de ejecución.

¿Hay una solución, que es tan fácil, simplemente no lo veo? Estoy muy seguro de que no soy el único que usa JPA en combinación con Hibernate y PostgreSQL. Así que estoy un poco confundido de que no puedo encontrar más preguntas como esta.

Solo para completar la pregunta, persistence.xml se ve así:

<?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="entityManager"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>com.app.model.Product</class> <properties> <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" /> <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost:5432/awesomedb" /> <property name="javax.persistence.jdbc.user" value="usr" /> <property name="javax.persistence.jdbc.password" value="pwd" /> <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" /> <property name="hibernate.jdbc.use_streams_for_binary" value="false" /> <property name="hibernate.hbm2ddl.auto" value="create-drop" /> <property name="show_sql" value="true" /> </properties> </persistence-unit> </persistence>

ACTUALIZAR:


Me gustaría ir con private String description; simple private String description; . El tipo de columna es solo un problema si está generando la base de datos desde su código, ya que se generará como varchar lugar de text .

Es genial codificar de manera independiente de la base de datos, y sin ningún proveedor específico de JPA, pero hay casos donde esto simplemente no es posible. Si la realidad es que tendrá que admitir múltiples tipos de bases de datos con todos sus detalles, entonces tiene que dar cuenta de esos detalles en alguna parte. Una opción es usar columnDefinition para definir el tipo de columna. Otra es dejar el código tal como está, y simplemente cambiar el tipo de columna en la base de datos. Yo prefiero el segundo.


Si desea utilizar JPA simple, puede remapear el tipo CLOB utilizado en el dialecto de esta manera:

public class PGSQLMapDialect extends PostgreSQL9Dialect { @Override public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) { if (Types.CLOB == sqlTypeDescriptor.getSqlType()) { return LongVarcharTypeDescriptor.INSTANCE; } return super.remapSqlTypeDescriptor(sqlTypeDescriptor); } }

Por lo tanto, no usará la asignación CLOB del controlador JDBC, que usa un OID para la columna y almacena / carga el texto mediante el manejo de objetos grandes. Esto solo daría como resultado llamadas setString y getString en la columna de texto createt en el Driver JDBC de Postgres a través de la clase VarcharTypeDescriptor.