JPAコンテキストにロードされたエンティティへの変更は、エンティティがデタッチされない限り自動的にコミットされるという印象を受けているようです。これは、実際にどのように機能するかということではありません。ただし、アタッチされたエンティティを変更してフラッシュしたり、デタッチされたエンティティをマージしたりしてもrollback
、変更1が他のトランザクションに表示されないようにします。
読み取り専用操作を実行するときにトランザクションを開いたままにしておくことは無害であり、多くの場合、一貫性を保つために良い考えです2。データが書き込まれないことを保証したい場合で、JTAを使用している場合は、を使用setRollbackOnly()
してデータSessionContext
を確認してください。手動のJPAトランザクション管理の場合は、コミットするのではなく、完了時に必ず呼び出しrollback()
てください。EntityTransaction
個人的には、「getLob」メソッドで新しいトランザクションを使用し、メソッドの最後でロールバックすることをお勧めします。DBがネストされたトランザクションをサポートしていない場合(ほとんどサポートしていません)、これにより通常、この作業を実行するためにプールから新しい接続がフェッチされます。
JTAおよびコンテナー管理トランザクションを使用している場合は、以下を試してください。
@Stateless
@TransactionManagement(TransactionManagementType.CONTAINER)
public class LobTest {
@PersistenceContext
private EntityManager em;
@Resource
private SessionContext sctx;
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public byte[] getLob() {
// Get your LOB content by fetching a new copy of the entity from the DB
// by ID, avoiding the need to split the LOB out. Note that you lose
// tx consistency guarantees between the LOB and the rest of the entity by
// doing this.
// then after loading the LOB:
sctx.setRollbackOnly();
}
}
または、周囲のトランザクションを中止するLOBの読み取りエラーを気にしない場合は、のTransactionAttributeType.REQUIRES
代わりにを使用REQUIRES_NEW
してくださいsetRollbackOnly()
。何も変更できないので、何もコミットされません。まだ開いていない場合は新しいトランザクションを開き、それ以外の場合は既存のトランザクションに参加するため、LOBの一貫した読み取りが可能になります。唯一の欠点は、一部のデータベースエラーがJTAトランザクション全体を中止することです。
非JTA環境でユーザー管理トランザクションを使用している場合は、新しいEntityManagerを取得し、EntityTransactionを取得し、em.find(...)
エンティティを含むLOBの新しいコピーをロードするために使用します。
1。SEQUENCE
さて、ほとんどのデータベースには、PostgreSQLや関連するSERIAL
疑似タイプ、アドバイザリロックなど、ロールバックするトランザクションの影響を受けるトランザクション免除オブジェクトタイプがいくつかあります。トランザクションは、他の操作を妨げる可能性のあるリソースのロックを保持するという意味で、データベースに「書き込む」こともできます。実際のデータについては、安全です。
2。実行時間の長いトランザクションは一部のデータベースでパフォーマンスの問題を引き起こし、接続プールを拘束するため、可能であれば、txを数秒以上開いたままにしないでください。「ユーザーの思考時間」(ユーザーが何かをするのを待っている時間)にトランザクションを開いたままにしないでください。空想にふけったり、昼食をとったり、休日に、月に行ったりする可能性があります。データベースと接続プールが返されるのを待っています。