数据库使用DB2 V9.7
spring配置文件:
<tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="login*" propagation="REQUIRED" /> <tx:method name="regist*" propagation="REQUIRED" /> <tx:method name="*" read-only="true" /> </tx:attributes> </tx:advice> <!-- 配置那些类的方法进行事务管理 --> <aop:config> <aop:pointcut id="allManagerMethod" expression="execution (public * com.tf.zjjg..*.service.*.*(..))" /> <aop:advisor advice-ref="txAdvice" pointcut-ref="allManagerMethod" /> </aop:config>
理论上除了save/delete/update/login/regist方法开启事务外,其他方法应该是只读事务,在只读事务中进行写操作应该是会报错的,可实际不是。
service方法:
com.tf.zjjg.quartz.service.impl.WeatherReadServiceImpl.readWeatherWithHttpUrl
com.tf.zjjg.quartz.service.impl.WeatherReadServiceImpl.readWeather
/** * 读取保存实时天气信息 */ @SuppressWarnings("rawtypes") public void readWeather() throws Exception { List allList = this.weatherReadDao.loadAllWeatherCityCode(); int len = allList.size(); List<WeatherAdminRelational> list = new ArrayList<WeatherAdminRelational>(len); for(int i=0; i<len; i++){ list.add((WeatherAdminRelational)SQLUtils.coverMapToBean((Map)allList.get(i), WeatherAdminRelational.class)); } readWeatherWithHttpUrl(list); } /** * 读取xml并保存,遇到出错进行异常的处理 * @param list * @throws Exception */ @Async private void readWeatherWithHttpUrl(List<WeatherAdminRelational> list){ int index = 0; for(WeatherAdminRelational bean : list){ index++; if(index>1){ int k = 1/0; } try{ this.qsaveOneCityWeather(bean); }catch (Exception e) { this.qsaveErrorCode(bean.getWeatherCode(), e); } } }
上面的代码我把以save开头的方法都加了一个字母q来防止可能的事务,并且在循环执行一次后加了代码1/0使其报错,报错信息如下:
1 15:56:49,572 DEBUG JobRunShell:198 - Calling execute on job DEFAULT.weatherTaskJob 2 15:56:49,604 DEBUG DataSourceTransactionManager:365 - Creating new transaction with name [com.tf.zjjg.quartz.service.impl.WeatherReadServiceImpl.readWeather]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,readOnly 3 15:56:49,604 DEBUG DriverManagerDataSource:162 - Creating new JDBC DriverManager Connection to [jdbc:db2://10.10.62.179:50000/mysdedb] 4 15:56:49,635 DEBUG DataSourceTransactionManager:204 - Acquired Connection [com.ibm.db2.jcc.c.b@1e8bcd60] for JDBC transaction 5 15:56:49,635 DEBUG DataSourceUtils:153 - Setting JDBC Connection [com.ibm.db2.jcc.c.b@1e8bcd60] read-only 6 15:56:49,635 DEBUG DataSourceTransactionManager:221 - Switching JDBC Connection [com.ibm.db2.jcc.c.b@1e8bcd60] to manual commit 7 15:56:49,651 DEBUG SQLUtils:40 - select sql is:select * from T_WEATHER_ADMIN_RELATIONAL 8 15:56:49,651 DEBUG JdbcTemplate:435 - Executing SQL query [select * from T_WEATHER_ADMIN_RELATIONAL] 9 15:56:49,885 WARN WeatherReadServiceImpl:154 - 获取城市:101220102 10 15:56:49,900 DEBUG SQLUtils:54 - insert sql is:insert into T_WEATHER_READ(id,code,p_time,h,wd,fx,fl,js,sd,update_time,data_date) values (:id,:code,:pTime,:h,:wd,:fx,:fl,:js,:sd,:updateTime,:dataDate) 11 15:56:49,916 DEBUG JdbcTemplate:881 - Executing SQL batch update [insert into T_WEATHER_READ(id,code,p_time,h,wd,fx,fl,js,sd,update_time,data_date) values (?,?,?,?,?,?,?,?,?,?,?)] 12 15:56:49,916 DEBUG JdbcTemplate:570 - Executing prepared SQL statement [insert into T_WEATHER_READ(id,code,p_time,h,wd,fx,fl,js,sd,update_time,data_date) values (?,?,?,?,?,?,?,?,?,?,?)] 13 15:56:49,916 DEBUG JdbcUtils:362 - JDBC driver supports batch updates 14 15:56:49,947 DEBUG DataSourceTransactionManager:843 - Initiating transaction rollback 15 15:56:49,947 DEBUG DataSourceTransactionManager:279 - Rolling back JDBC transaction on Connection [com.ibm.db2.jcc.c.b@1e8bcd60] 16 15:56:49,947 DEBUG DataSourceUtils:222 - Resetting read-only flag of JDBC Connection [com.ibm.db2.jcc.c.b@1e8bcd60] 17 15:56:49,947 DEBUG DataSourceTransactionManager:322 - Releasing JDBC Connection [com.ibm.db2.jcc.c.b@1e8bcd60] after transaction 18 15:56:49,947 DEBUG DataSourceUtils:332 - Returning JDBC Connection to DataSource 19 15:56:49,963 ERROR JobRunShell:208 - Job DEFAULT.weatherTaskJob threw an unhandled Exception: 20 org.springframework.scheduling.quartz.JobMethodInvocationFailedException: Invocation of method 'read' on target class [class com.tf.zjjg.quartz.task.WeatherReadTask] failed; nested exception is java.lang.ArithmeticException: / by zero 21 at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:320) 22 at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:113) 23 at org.quartz.core.JobRunShell.run(JobRunShell.java:199) 24 at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:546) 25 Caused by: java.lang.ArithmeticException: / by zero 26 at com.tf.zjjg.quartz.service.impl.WeatherReadServiceImpl.readWeatherWithHttpUrl(WeatherReadServiceImpl.java:70) 27 at com.tf.zjjg.quartz.service.impl.WeatherReadServiceImpl.readWeather(WeatherReadServiceImpl.java:56) 28 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 29 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 30 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 31 at java.lang.reflect.Method.invoke(Method.java:606) 32 at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:319) 33 at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 34 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 35 at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 36 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 37 at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:90) 38 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 39 at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 40 at com.sun.proxy.$Proxy11.readWeather(Unknown Source) 41 at com.tf.zjjg.quartz.task.WeatherReadTask.read(WeatherReadTask.java:17) 42 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 43 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 44 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 45 at java.lang.reflect.Method.invoke(Method.java:606) 46 at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273) 47 at org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean$MethodInvokingJob.executeInternal(MethodInvokingJobDetailFactoryBean.java:311) 48 ... 3 more
翻阅了该帖子:http://www.myexception.cn/software-architecture-design/922822.html
只读事务需要数据库来支持,但是我没对指定方法设置事务那spring也不应该帮我自动设置事务吧
修改
<tx:method name="*" read-only="true" />
为
<tx:method name="*" propagation="NOT_SUPPORTED" read-only="true" />
问题解决!!
修改
<tx:method name="*" read-only="true" />
为
<tx:method name="*" propagation="NOT_SUPPORTED" read-only="true" />
问题解决!!