Avant de décrire le problème, permettez-moi d'expliquer quelques prémisses. Supposons que la transaction de base de données soit configurée dans le fichier de configuration Spring de la manière suivante :
<bean id="transactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driven transaction-manager="transactionManager" />
Il existe maintenant UserDao et SecurityService :
@Repository public class UserDao { public User getUser() { // interroge l'utilisateur à partir de la table utilisateur 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 user = userDao.getUser(); ()) { System.out.println("Tom est là"); break;
Pendant le processus d'appel de la méthode SecurityService#checkUserInfo(), les données obtenues via la méthode userDao#getUser() restent inchangées Même si une nouvelle donnée nommée Tom est insérée à ce moment, la boucle ne se terminera pas. De plus, la suppression de l'annotation @Transactional sur SecurityService n'aidera pas.
Tout d'abord, j'ai pensé qu'il pourrait s'agir d'un problème avec le pool de connexion à la base de données. La même chose est vraie lorsqu'il est remplacé par celui de Spring. Ensuite, j'ai appelé l'objet Connection directement depuis JdbcTemplate et j'ai utilisé la méthode JDBC d'origine pour faire fonctionner la base de données. À ce moment-là, les données changeaient en temps réel, j'ai donc pensé que la transaction de Spring devrait être liée au thread d'opération actuel. Après avoir vérifié le code source, j'ai trouvé dans la méthode DataSourceUtils#doGetConnection que Spring créait une connexion sur chaque DataSource de chaque thread et la liait à la transaction. Étant donné que le fichier de configuration basé sur les annotations effectue une liaison de transaction sur toutes les couches de service (classes annotées avec @Service), la même connexion est liée dans le même thread, que @Transactional soit utilisé ou non, mais elle n'est pas effectuée uniquement pour les opérations commerciales. .
Après de nombreuses expériences et recherches d'informations, j'ai finalement trouvé la solution parfaite : ajoutez simplement l'annotation @Transactional(propagation = Propagation.NOT_SUPPORTED) à la méthode checkUserInfo ci-dessus. Bien entendu, vous pouvez également obtenir la connexion et effectuer l'opération manuellement, ou vous pouvez utiliser le package DateUtils pour effectuer l'opération.