Batch-AW06

Task to do

读样例代码+看课程其他讲解样例视频

作业思路: 把aw04中的product来源换成batch任务写入的数据库

aw04的数据结构可能需要重构 如product

More: Faster!——Parallel!

Read Example Code

Service——batch流程工作流程用到的基本服务

ItemReader,ItemProcessor,ItemWriter是模板,有类型参数可供自定义,可以通过重载自定义前后预处理的流程

JsonFilerReader

  • ObjectMapper:json和Plain Old Java Object互相转换

  • JsonNode: json的数据被组织成树状,树的节点,样例中实现的ItemReader类型参数是JsonNode

(Reader的原理?)

JsonReader

和JsonFileReader的区别?

限定了filename

todo: 因为至少有两个文件 所以需要正则表达式来写读取文件

ClassPathResource(“data/xxx”)

ProductProcessor

利用objectMapper的treeToValue函数转换成Product类,注意Product类的成员应该和json的格式对应

ProductWriter

重载write方法——todo:写入到数据库中,或许可以参考aw04

官方Spring Batch入门文档,writer有一些与数据库相关的接口。

写入数据库 样例:spring-guides/gs-batch-processing

该样例用的hsqldb 是用于模拟、测试的位于内存的数据库

Config

BatchConfig

@EnableBatchProcessing

使用了线程池来管理step级别的工作;整个任务是一个job,job中读入/处理/写入是step

todo: 可以尝试更多加速的并行方式

PartitionJob

数据分割成并行的块,有masterStep负责同步,masterStep履行了PartitionHandler的职责,设定了gridSize(?)

Partitioner是示意图中的StepExecutionSplitter,负责

Partitioner 负责分割资源,此处因为要读取的文件不止一个所以用了MultiResourcePartitioner,并且通过正则表达式来指定文件(PathMatchingResourcePatternResolver)

ItemReader要接收的文件格式不是原本的文件,而是经过分割的,所以用Value注解进行了注释说明

Tech Solution

设计

原有的product和amazon导入的AmazonProduct分离,repository之上套一层posDB服务进行类型转换

对aw06(Batch):

确认使用何种数据库

找到写入数据库的方式

对aw04原有代码(Amazon-webpos):

  • 单机模式下运行 redis和jdbc的关系?能写入redis吗 不能切换成jdbc
    • cache原本是用于存储从网上拉取的product信息的,原本使用的redis是用于存session的,因此redis部分并不干扰

aw04中的db 新写一个posDB的实现代替原本的JD-PosDB

具体实现

跑起来就花了很多时间

看样例代码的时候需要关注说明!有一些环境需要配置的,如添加建立数据库的脚本

数据库写入的数据具有原子性,而product结构中有list,因此被迫放弃使用jdbc+sql硬编码语句,转向抽象程度更高的CrudRepository+h2db,但是依旧要解决写入list的问题。

仔细看报错,分析原因;搜索提问的时候问题描述需要准确,可以更快的解决问题

How to persist a List of String in Hibernate

jsonType推荐 A Guide to the Hibernate Types Library

检查是否写入数据库——下载一个h2客户端来独立检查,因为没有spring-boot web无法用浏览器打开

bad SQL grammar [SELECT JOB_INSTANCE_ID, JOB_NAME from BATCH_JOB_INSTANCE where JOB_NAME = ? and JOB_KEY = ?]

  • 成功连上数据库 可以用持久化文件来检查 暂时用jdbc:h2:mem:testdb来确认是否写入

    • 直接h2客户端查看更快
    • testdb没有写入,直接用文件来持久化。还可以看到dbtrace,方便调试
    • 下载解压后进入h2文件夹运行./h2.sh脚本即可
  • 但是没有能写入数据——果然问号是因为是空值 为什么会是空值呢

    • 控制台问号不是空值 是h2数据库需要重启脚本来刷新 才能读取到正确的文件

数据存储的方式

对于简单的非list的部分,直接存在指定的表amazon_product中;对于List<String>部分,新建表格存储,一对多的关系转换成多个一对一关系

List<String>在代码中如何配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Data
@JsonIgnoreProperties(ignoreUnknown = true)//写表时如果无法识别就填null 是兜底的操作
@Entity
@Table(name = "amazon_products")//简单属性会直接存入这张表 list属性会在同层生成其他表 实际可以用join来获取信息
@TypeDefs({
@TypeDef(name = "json", typeClass = JsonStringType.class)//使用hibernate扩展的属性来写入List<String> 定义别名
//@TypeDef(name = "json", typeClass = JsonType.class)
})
public class Product implements Serializable{
@ElementCollection
@Column(name = "imageURL",columnDefinition = "json")//指明列名和类型
@Type(type = "json")//该类型需要引入hibernate的扩展包并且用注解定义别名才能使用
@Getter//不能省略 供外界调用
@Setter
private List<String> imageURLHighRes;
}

参考资料:

https://howtodoinjava.com/hibernate/hibernate-insert-query-tutorial/

https://stackoverflow.com/questions/32765893/storing-a-listsomeclass-as-json-in-a-text-field-with-hibernate

https://www.baeldung.com/hibernate-persist-json-object

https://www.concretepage.com/spring-5/spring-data-crudrepository-example

Amazon-webpos读取数据

命名并指定注入的组件

Amazon-webpos读取失败:

原来是设置了

1
spring.batch.jdbc.initialize-schema=never/always

h2每次连接都会刷新(照搬了batch的配置),在batch中应当刷新,但是读取的时候不应该改动。

crudRepository是很方便可靠的架构,出问题应该先检查数据是否有问题——发现持久化文件被清空了。

Reflection

大部分时间花在了接入数据库上,batch工作的原理只是大概了解了流程,学会了重载writer,更多的parallel的性质还没有探索。