tutorial resolucion pantalla interfaz grafica español ejemplos aplicacion adaptar java hibernate postgresql jpa autocommit

resolucion - swing java



Los objetos grandes no se pueden usar en el modo de confirmación automática (4)

Tengo una aplicación Spring que utiliza Hibernate en una base de datos PostgreSQL. Estoy tratando de almacenar archivos en una tabla de la base de datos. Parece que almacena la fila con el archivo (solo uso el método de persistencia en EntityManager), pero cuando el objeto se carga desde la base de datos obtengo la siguiente excepción:

org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode.

Para cargar los datos, estoy usando un atributo transitorio MultipartFile y en su configurador, estoy configurando la información que deseo conservar (byte [], fileName, tamaño). La entidad en la que estoy persistiendo se parece a esta (omití el resto de captadores / definidores):

@Entity @Table(name="myobjects") public class MyClass { @Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="sequence") @SequenceGenerator(name="sequence", sequenceName="myobjects_pk_seq", allocationSize=1) @Column(name="id") private Integer id; @Lob private String description; @Temporal(TemporalType.TIMESTAMP) private Date creationDate; @Transient private MultipartFile multipartFile; @Lob @Basic(fetch=FetchType.LAZY, optional=true) byte[] file; String fileName; String fileContentType; Integer fileSize; public void setMultipartFile(MultipartFile multipartFile) { this.multipartFile = multipartFile; try { this.file = this.multipartFile.getBytes(); this.fileName = this.multipartFile.getOriginalFilename(); this.fileContentType = this.multipartFile.getContentType(); this.fileSize = ((Long) this.multipartFile.getSize()).intValue(); } catch (IOException e) { logger.error(e.getStackTrace()); } } }

Puedo ver que cuando persiste tengo los datos en la fila pero cuando llamo a este método falla:

public List<MyClass> findByDescription(String text) { Query query = getEntityManager().createQuery("from MyClass WHERE UPPER(description) like :query ORDER BY creationDate DESC"); query.setParameter("query", "%" + text.toUpperCase() + "%"); return query.getResultList(); }

Este método solo falla cuando el resultado tiene objetos con archivos. He intentado establecer en mi persistence.xml

<property name="hibernate.connection.autocommit" value="false" />

Pero no resuelve el problema.

En general, la aplicación funciona bien, solo confirma los datos cuando finaliza la transacción y realiza una reversión si algo falla, por lo que no entiendo por qué sucede esto.

¿Alguna idea?

Gracias.

ACTUALIZAR

Mirando el enlace dado por Shekhar, se sugiere incluir la llamada en una transacción, así que establezco la llamada de servicio dentro de una transacción y funciona (he agregado la anotación @Transactional).

@Transactional public List<myClass> find(String text) { return myClassDAO.findByDescription(text); }

el problema es que no quiero conservar ningún dato, por lo que no entiendo por qué debería incluirse dentro de una transacción. ¿Tiene algún sentido hacer un compromiso cuando solo he cargado algunos datos de la base de datos?

Gracias.


A menos que necesite almacenar archivos de más de 1 GB, le sugiero que use bytea como tipo de datos en lugar de objetos grandes.

bytea es básicamente lo que BLOB es en otras bases de datos (por ejemplo, Oracle) y su manejo es mucho más compatible con JDBC.


En lugar de usar @Transactional , todo lo que hice para este problema fue actualizar esta columna en PostgreSQL DB del tipo oid tipo bytea y agregar @Type para el campo @Lob .

es decir

ALTER TABLE person DROP COLUMN image; ALTER TABLE person ADD COLUMN image bytea;

Y cambiado

@Lob private byte[] image;

A

@Lob @Type(type = "org.hibernate.type.ImageType") private byte[] image;


Si puede, cree una Entidad intermedia entre MyClass y propiedad de archivo, por ejemplo. Algo como:

@Entity @Table(name="myobjects") public class MyClass { @OneToOne(cascade = ALL, fetch = LAZY) private File file; } @Entity @Table(name="file") public class File { @Lob byte[] file; }

No puedes usar @Lob y buscar el tipo Lazy. No funciona. Debes tener una clase intermedia.