問題を説明する前に、データベース トランザクションが Spring 構成ファイルで次のように構成されていると仮定します。
<bean id="transactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driventransaction-manager="transactionManager" />
これで、UserDao と SecurityService が追加されました。
@Repository public class UserDao { public User getUser() { // ユーザー テーブルからユーザーをクエリ return queryObject("select * from user order by id desc limit 1"); } }
@Service @Transactional public class SecurityService { @Autowired private UserDao userDao; public void checkUserInfo() { while(true) { ユーザー user = userDao.getUser() if(user != null && "Tom".equals(user.getName) ()) { System.out.println("トムはここにいます");
SecurityService#checkUserInfo() メソッドを呼び出すプロセスでは、userDao#getUser() メソッドによって取得されたデータは変更されず、この時点で Tom という名前の新しいデータが挿入されても、ループは終了しません。さらに、SecurityService の @Transactional アノテーションを削除しても役に立ちません。
まず、データベースの接続プールに問題があるのではないかと考え、Spring 独自の接続プールに置き換えた場合も同様で、JdbcTemplate から直接 Connection オブジェクトを呼び出し、独自の JDBC メソッドを使用してデータベースを操作しました。このとき、データはリアルタイムで変化していたので、Spring のトランザクションは現在の操作スレッドにバインドされているはずだと思いました。ソース コードを確認したところ、DataSourceUtils#doGetConnection メソッドで Spring が各スレッドの各 DataSource に Connection を作成し、トランザクションにバインドしていることがわかりました。 tx:annotation 駆動の設定ファイルはすべてのサービス層 (@Service でアノテーションが付けられたクラス) でトランザクション バインディングを実行するため、@Transactional が使用されているかどうかに関係なく、同じ Connection が同じスレッドにバインドされますが、ビジネス操作だけが実行されるわけではありません。 。
多くの実験と情報の検索を行った結果、最終的に完璧な解決策を見つけました。 @Transactional(propagation = Propagation.NOT_SUPPORTED) アノテーションを上記の checkUserInfo メソッドに追加するだけです。もちろん、Connection を取得して操作を手動で実行することも、DateUtils パッケージを使用して操作を実行することもできます。