Ho un'applicazione Spring che utilizza Hibernate su un database PostgreSQL. Sto cercando di memorizzare i file in una tabella del database. Sembra che memorizza la riga con il file (mi basta usare metodo su EntityManager persistono), ma quando l'oggetto viene caricato dal database ottengo la seguente eccezione:Non è possibile utilizzare oggetti grandi in modalità di commit automatico
org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode.
per caricare i dati che sto utilizzando un MultipartFile transient atribute e nel suo setter sto impostando l'informazione che voglio persistere (byte [], fileName, size). L'entità che sto persistente aspetto come questo (ho omesso il resto dei getter/setter):
@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());
}
}
}
posso vedere che quando è persistito ho i dati nella fila ma quando chiamo questo metodo non riesce:
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();
}
Questo metodo ha esito negativo solo quando il risultato contiene oggetti con file. Ho provato a impostare nel mio persistence.xml
<property name="hibernate.connection.autocommit" value="false" />
ma non risolve il problema.
In generale, l'applicazione funziona bene, si limita a impegnare i dati solo quando la transazione è terminata e esegue un rollback se qualcosa non funziona, quindi non capisco perché sta succedendo.
Qualche idea?
Grazie.
UPDATE
Guardando il link indicato da Shekhar si suggerisce di includere la chiamata in un transation, così ho impostato la chiamata di servizio all'interno di una transazione di un funziona (ho aggiunto @Transactional annotazione).
@Transactional
public List<myClass> find(String text) {
return myClassDAO.findByDescription(text);
}
il problema è che io non voglio a persistere i dati in modo da non capisco perché dovrebbe essere includere all'interno di una transazione. Ha senso fare un commit quando ho caricato solo alcuni dati dal database?
Grazie.
se non si desidera mantenere i dati perché si esegue il mapping di 'file'? Non dovrebbe essere '@ Transient'? –
@matt b Voglio mantenere i file ma solo nell'operazione di salvataggio non in quella di lettura. Questo è il motivo per cui non ho capito che la lettura dovrebbe essere in una transazione. – Javi
Non si utilizza @Transactional quando si desidera salvare oggetti. In genere è necessaria una transazione per accedere al database, sia che si tratti di leggere o scrivere. – Volksman