PostgreSQL データベースで Hibernate を使用する Spring アプリケーションがあります。データベースのテーブルにファイルを保存しようとしています。行をファイルに格納しているようですが (EntityManager で persist メソッドを使用するだけです)、オブジェクトがデータベースから読み込まれると、次の例外が発生します。
org.postgresql.util.PSQLException: Large Objects may not be used in auto-commit mode.
データをロードするために MultipartFile 一時属性を使用し、そのセッターで永続化したい情報 (byte[]、fileName、size) を設定しています。私が永続化しているエンティティは次のようになります (残りのゲッター/セッターは省略しました)。
@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());
}
}
}
永続化すると行にデータがあることがわかりますが、このメソッドを呼び出すと失敗します。
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();
}
このメソッドは、結果にファイルを含むオブジェクトがある場合にのみ失敗します。persistence.xml に設定しようとしました
<property name="hibernate.connection.autocommit" value="false" />
しかし、それは問題を解決しません。
一般に、アプリケーションは正常に機能し、トランザクションが終了したときにのみデータをコミットし、何かが失敗した場合はロールバックを実行するため、なぜこれが起こっているのかわかりません。
何か案が?
ありがとう。
アップデート
Shekhar によって提供されたリンクを見ると、呼び出しをトランザクションに含めることが提案されているため、サービス呼び出しをトランザクション内に設定して動作させました (@Transactional アノテーションを追加しました)。
@Transactional
public List<myClass> find(String text) {
return myClassDAO.findByDescription(text);
}
問題は、データを保持したくないため、トランザクション内に含める必要がある理由がわかりません。データベースから一部のデータしかロードしていないときにコミットするのは意味がありますか?
ありがとう。