Antes de describir el problema, permítanme explicar algunas premisas. Supongamos que la transacción de la base de datos está configurada en el archivo de configuración de Spring de la siguiente manera:
<bean id="transactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driven transaction-manager="transactionManager" />
Ahora existen UserDao y SecurityService:
@Repository public class UserDao { public User getUser() { // consulta al usuario desde la tabla de usuarios 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) { Usuario usuario = userDao.getUser() if(user != null && "Tom".equals(user.getName); ()) { System.out.println("Tom está aquí"); descanso;
Durante el proceso de llamar al método SecurityService#checkUserInfo(), los datos obtenidos a través del método userDao#getUser() permanecen sin cambios. Incluso si se insertan nuevos datos llamados Tom en este momento, el ciclo no finalizará. Además, eliminar la anotación @Transactional en SecurityService no ayudará.
En primer lugar, pensé que podría ser un problema con el grupo de conexiones de la base de datos. Lo mismo ocurre cuando se reemplaza por el propio Spring. Luego llamé al objeto Connection directamente desde JdbcTemplate y utilicé el método JDBC original para operar la base de datos. En este momento, los datos estaban cambiando en tiempo real, así que pensé. Debería ser que la transacción de Spring esté vinculada al hilo de operación actual. Después de verificar el código fuente, encontré en el método DataSourceUtils#doGetConnection que Spring creó una conexión en cada fuente de datos de cada hilo y la vinculó a la transacción. Debido a que el archivo de configuración basado en anotaciones tx: realiza el enlace de transacciones en todas las capas de Servicio (clases anotadas con @Service), la misma Conexión está vinculada en el mismo hilo independientemente de si se usa @Transactional, pero no se realiza solo operaciones comerciales. .
Después de muchos experimentos y búsqueda de información, finalmente encontré la solución perfecta: simplemente agregue la anotación @Transactional(propagation = Propagation.NOT_SUPPORTED) al método checkUserInfo anterior. Por supuesto, también puede obtener Connection y realizar la operación manualmente, o puede utilizar el paquete DateUtils para realizar la operación.