spring batch连接数据库
- 配置数据库
- 注意
github地址:
https://github.com/a18792721831/studybatch.git
文章列表:
spring batch itemProcess详解
创建项目
选择数据库和spring batch
下载完依赖后,目录结构如下
创建配置
在resources目录下创建application.yaml配置文件
接着配置数据库
创建job
创建job配置类
创建ItemReader
我们不使用spring batch提供的已经实现的包装好的数据读取器,而是直接实现接口。
创建ItemProcess
创建ItemWriter
组装Step
配置Job
配置数据库
到目前为止,我们已经创建了一个标准的job。创建job的过程中,需要使用到jobBuilderFactory和stepBuilderFactory.
我们使用的jobBuilderFactory和stepBuilderFactory是spring batch注入的。
spring batch注入的这两个接口,使用的是默认的配置。
而我们在application.yaml中配置的oracle数据库,却没有被用到。
所以,还需要配置数据库。
我们在容器中注入了相关的配置,没有注入使用我们想要的配置的接口。
覆盖接口jobRepository
注意
这里面有一个很大坑。
在spring batch的quick start中 ,并没有需要我们自己去执行job,而是只需要将job注入容器,然后就会执行。
理所当然的,我们配置了oracle数据库后,也会认为,我们只需要将job注入容器,然后将使用了数据库配置的jobRepository注入容器,就可以了。
当然,我也是这么想的,所以,我将这一切配置好后,启动,发现了一个很有意思的事情:
就像这样,什么都没有。
提示Running default command line with: []
什么鬼,我们不是已经将job注入容器了吗,为什么不执行?
数据库驱动问题吗
网上有很多的资料说,数据库的驱动,版本问题,很容易出现问题。
于是,我就创建了另外一个项目:mysql的。
相比来说,oracle数据库驱动,因为不容易下载等原因,问题总是比mysql多些。
可惜的是,换成了mysql数据库后,还是相同的。
我更换了网上常见的ojdbc8,12,14等等,各种版本。
发现还是不行。
开启debug级别
想着开启debug之后,打印的信息更多,可能会看出问题的原因来:
开启debug级别的日志后,确实打印的信息更多了
从日志中可以看出来,我们的job配置是没有任何问题的。
容器扫描到了job,但是却被spring batch跳过了。
原因是从注册元数据中没有找到这个job。
什么情况,我们使用jobBuilderFactory.get(“hello-job”)不就是想注册这个job么。
是不是数据库就没有连上?
于是,我创建了一个新的oracle数据库用户,接着配置了oracle用户,在其他数据不修改的情况下,启动。
发现还是这样。
而且,数据库中,根本就没有执行init-schema脚本。
数据库真的没有连上。(还是太年轻)
但是数据库连接就是这样配置啊,驱动,配置等等都有了。还需要怎么做呢?
重新阅读quick start
确实不甘心,我要学习spring batch,怎么在第一步上就放弃呢。
重新阅读quick start。没有发现什么有用的信息。
我强迫自己忘记现在已经做的全部事情,从头开始。
避免惯性思维。
于是从头开始,重新按照教程做了一遍。
发现和我的项目的区别就是数据库不同。
于是我将我之前的oracle数据库在换回hsql数据库。
神奇的一幕出现了:
在hsql中,我们将job注入容器就可以了,启动项目,spring batch中会默认调度我们的job。
在oracle中,我们将job注入容器,一点屁用都没有,甚至,初始化脚本都不会执行。
破局
我发现这个差异,就去github,stackoverflow中搜索spring batch oracle。发现没有什么有用的回答。
继续回想看到的资料,说pring batch是一个批处理的框架,需要配合其他调度框架使用。
我可能明白了,需要我们自己调度。
于是,我在job的配置类中,写了调度方法
接着启动
成功
另一个坑
在spring batch的配置中,还有一个地方有坑。
在数据库初始化策略中,有三种模式:
从不初始化,每次都初始化,根据需要初始化。
所以,配置的是embedded.
结果,并不会初始化,oracle数据库。或许,是我自己理解有误,只有切入式的数据库,才使用embedded。
所以,第一次启动oracle数据库,我们需要将初始化策略配置为always,或者将初始化脚本手动执行。
然后将初始化策略配置为never。
这部分在github的issus中也得到了侧面验证。初始化脚本和数据库用户的权限问题。配置的数据库用户只有数据的读写权限,没有数据表操作权限。
也就是,dml和ddl是分离的。
如果使用oracle数据库,那么使用embedded和never是一样的效果。
另一种不执行的情况
job instance执行成功后,就不在重复执行。
刚开始,我启动job的时候,配置的jobParameter是空的。
第一次执行没有问题,第二次执行,就是跳过这个job instance了。
因为在spring batch中,识别一个job instance = job name + job parameter
我们两次执行的parameter是相同的,也就是同一个job instance,因为job instance已经执行成功了,就不在重复执行了。
所以,最好是job parameter中传入时间,即使我们不会用到。
这样保证可以重复执行。
这个问题,耗费了我好几天的学习时间才解决,希望可以帮到你。