Spring中DAO被循环调用的时候数据不实时更新的解决方法
2023-06-13 09:15:44 时间
在描述问题之前先说明几个前提,假设在Spring的配置文件中使用下面的方式配置了数据库的事务:
<beanid="transactionManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <propertyname="dataSource"ref="dataSource"/> </bean> <tx:annotation-driventransaction-manager="transactionManager"/>
现在有UserDao和SecurityService:
@Repository publicclassUserDao{ publicUsergetUser(){ //queryuserfromusertable returnqueryObject("select*fromuserorderbyiddesclimit1"); } }
@Service @Transactional publicclassSecurityService{ @Autowired privateUserDaouserDao; publicvoidcheckUserInfo(){ while(true){ Useruser=userDao.getUser(); if(user!=null&&"Tom".equals(user.getName()){ System.out.println("Tomishere"); break; } } } }
在调用SecurityService#checkUserInfo()方法的过程中,通过userDao#getUser()方法获取到的数据是不变的,即使这个时候新插入了一条name为Tom的数据循环也不会结束。另外将SecurityService上面的@Transactional注解去掉也无济于事。
首先想到会不会是数据库连接池的问题,换成了Spring自带的也是如此;然后从JdbcTemplate里面直接调用了Connection对象,使用原始的JDBC方式操作数据库,这个时候数据是实时变化的,于是想到应该是Spring的事务和当前操作线程进行绑定了。查看源代码进入之后果然在DataSourceUtils#doGetConnection方法里面发现了Spring在每个线程的每个DataSource上创建了一个Connection并且与事务进行了绑定。因为tx:annotation-driven配置文件对所有的Service层(加了@Service注解的类)进行了事务绑定,所以无论是否使用@Transactional都在同一个线程中绑定了同一个Connection,只是不进行事务操作而已。
经过多次实验和查找资料,最后终于找到了完美的解决方法:只要在上述的checkUserInfo方法中加上@Transactional(propagation=Propagation.NOT_SUPPORTED)注解就可以了。当然也可以获取到Connection然后手工进行操作,也可以使用DateUtils包进行操作。
相关文章
- Spring 全家桶之 Spring Framework 5.3(一)
- 惊呆了,spring中竟然有12种定义bean的方法
- 后端必读《Spring Boot实战》,企业级真实应用案例
- 斗转星移,无人能及——Spring MVC
- Spring(一)-初识 + DI+scope
- Spring中使用模板方法模式(接上文)
- spring之view-controller
- Spring Cloud Ribbon
- Spring源码学习方法
- 对话 Spring 大神:Spring 生态系统的新时代来了!
- Spring Boot中使用MongoDB数据库的方法
- spring+spring mvc+mybatis详解编程语言
- Spring Boot(三):Spring Boot中Redis的使用详解编程语言
- Spring 自动装配;方法注入详解编程语言
- spring 整合junit进行测试详解编程语言
- Spring getBeanNamesForType方法:通过类型获取Bean名称
- Spring isSingleton方法:判断是否定义Singleton模式
- Spring setUsername方法:设置访问数据库的用户名
- Spring get方法:获取指定ID编号的实体对象
- Spring Boot 如何快速集成 Redis 哨兵?