mysql - 在springbatch中连接到数据库时表不存在
问题描述
我有一个 user.csv 文件。我想将 csv 文件的数据存储到 sql 数据库中。我在 yml 文件中提供了正确的 sql 连接,但它会引发运行时异常
Caused by: java.sql.SQLSyntaxErrorException: Table 'login.batch_job_instance' doesn't exist
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:120) ~[mysql-connector-java-8.0.26.jar:8.0.26]
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) ~[mysql-connector-java-8.0.26.jar:8.0.26]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:953) ~[mysql-connector-java-8.0.26.jar:8.0.26]
at com.mysql.cj.jdbc.ClientPreparedStatement.executeQuery(ClientPreparedStatement.java:1003) ~[mysql-connector-java-8.0.26.jar:8.0.26]
at com.zaxxer.hikari.pool.ProxyPreparedStatement.executeQuery(ProxyPreparedStatement.java:52) ~[HikariCP-4.0.3.jar:na]
at com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeQuery(HikariProxyPreparedStatement.java) ~[HikariCP-4.0.3.jar:na]
at org.springframework.jdbc.core.JdbcTemplate$1.doInPreparedStatement(JdbcTemplate.java:722) ~[spring-jdbc-5.3.10.jar:5.3.10]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:651) ~[spring-jdbc-5.3.10.jar:5.3.10]
... 42 common frames omitted
2021-09-27 16:31:27.913 INFO 3800 --- [ main] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2021-09-27 16:31:27.915 INFO 3800 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown initiated...
2021-09-27 16:31:27.922 INFO 3800 --- [ main] com.zaxxer.hikari.HikariDataSource : HikariPool-1 - Shutdown completed.
Process finished with exit code 1
批处理配置
package com.nilmani.literalmission.config
import com.nilmani.literalmission.model.User
import org.springframework.batch.core.Job
import org.springframework.batch.core.Step
import org.springframework.batch.core.configuration.annotation.EnableBatchProcessing
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory
import org.springframework.batch.core.launch.support.RunIdIncrementer
import org.springframework.batch.item.ItemProcessor
import org.springframework.batch.item.ItemReader
import org.springframework.batch.item.ItemWriter
import org.springframework.batch.item.file.FlatFileItemReader
import org.springframework.batch.item.file.LineMapper
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper
import org.springframework.batch.item.file.mapping.DefaultLineMapper
import org.springframework.batch.item.file.transform.DelimitedLineTokenizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.io.FileSystemResource
@Configuration
@EnableBatchProcessing
class BatchConfig {
@Bean
fun job(jobBuilderFactory: JobBuilderFactory,
stepBuilderFactory: StepBuilderFactory,
itemReader: ItemReader<User>,
itemProcessor: ItemProcessor<User,User>,
itemWriter: ItemWriter<User>
):Job{
val step: Step = stepBuilderFactory["ETL-file-load"]
.chunk<User, User>(100)
.reader(itemReader)
.processor(itemProcessor)
.writer(itemWriter)
.build()
return jobBuilderFactory["ETL-Load"]
.incrementer(RunIdIncrementer())
.start(step)
.build()
}
@Bean
fun itemReader(): FlatFileItemReader<User>? {
val flatFileItemReader: FlatFileItemReader<User> = FlatFileItemReader<User>()
flatFileItemReader.setResource(FileSystemResource("src/main/resources/users.csv"))
flatFileItemReader.setName("CSV-Reader")
flatFileItemReader.setLinesToSkip(1)
flatFileItemReader.setLineMapper(lineMapper()!!)
return flatFileItemReader
}
@Bean
fun lineMapper(): LineMapper<User>? {
val defaultLineMapper: DefaultLineMapper<User> = DefaultLineMapper<User>()
val lineTokenizer = DelimitedLineTokenizer()
lineTokenizer.setDelimiter(",")
lineTokenizer.setStrict(false)
lineTokenizer.setNames("id", "name", "dept", "salary")
val fieldSetMapper: BeanWrapperFieldSetMapper<User> = BeanWrapperFieldSetMapper<User>()
fieldSetMapper.setTargetType(User::class.java)
defaultLineMapper.setLineTokenizer(lineTokenizer)
defaultLineMapper.setFieldSetMapper(fieldSetMapper)
return defaultLineMapper
}
}
DBWriter.kt
package com.nilmani.literalmission.batch
import com.nilmani.literalmission.model.User
import com.nilmani.literalmission.repository.UserRepository
import org.springframework.batch.item.ItemWriter
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
@Component
class DBWriter :ItemWriter<User> {
@Autowired
private lateinit var userRepository: UserRepository
@Autowired
fun DBWriter(userRepository: UserRepository){
this.userRepository = userRepository
}
@Throws(Exception::class)
override fun write(users: MutableList<out User>) {
println("Data Saved for Users: $users")
userRepository.saveAll(users)
}
}
项目处理器.kt
package com.nilmani.literalmission.batch
import com.nilmani.literalmission.model.User
import org.springframework.batch.item.ItemProcessor
import org.springframework.stereotype.Component
import java.util.*
import kotlin.collections.HashMap
@Component
class Processor : ItemProcessor<User,User> {
private val DEPT_NAMES: MutableMap<String, String> = HashMap()
fun Processor() {
DEPT_NAMES["100"] = "Technology"
DEPT_NAMES["102"] = "Operations"
DEPT_NAMES["103"] = "Accounts"
DEPT_NAMES["104"] = "Devloper"
}
@Throws(Exception::class)
override fun process(user: User): User? {
val deptCode:String=user.dept
val dept=DEPT_NAMES[deptCode]
if (dept != null) {
user.dept = dept
}
user.time= Date()
println(String.format("Converted from [%s] to [%s]", deptCode, dept))
return user
}
}
负载控制器.kt
package com.nilmani.literalmission.controller
import org.springframework.batch.core.*
import org.springframework.batch.core.launch.JobLauncher
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException
import org.springframework.batch.core.repository.JobRestartException
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/load")
class LoadController {
@Autowired
private lateinit var jobLauncher: JobLauncher
@Autowired
private lateinit var job:Job
@GetMapping
@Throws(
JobParametersInvalidException::class,
JobExecutionAlreadyRunningException::class,
JobRestartException::class,
JobInstanceAlreadyCompleteException::class
)
fun load(): BatchStatus {
val maps: MutableMap<String, JobParameter> = HashMap()
maps["time"] = JobParameter(System.currentTimeMillis())
val parameters = JobParameters(maps)
val jobExecution: JobExecution = jobLauncher.run(job, parameters)
System.out.println("JobExecution: " + jobExecution.status)
println("Batch is Running...")
while (jobExecution.isRunning) {
println("...")
}
return jobExecution.status
}
}
用户.kt
package com.nilmani.literalmission.model
import java.util.*
import javax.persistence.Entity
import javax.persistence.Id
@Entity
data class User(
@Id
val id:Long=0,
val name:String="",
var dept:String="",
val salary:String="",
var time:Date
)
我正确地添加了每件事我是如何得到这类问题的
spring:
datasource:
url: jdbc:mysql://localhost:3306/login
driverClassName: com.mysql.cj.jdbc.Driver
username: root
password:
jpa:
database-platform: org.hibernate.dialect.MySQL5Dialect
show-sql: true
hibernate:
ddl-auto: update
解决方案
根据错误Table 'login.batch_job_instance' doesn't exist
,您需要在运行作业之前在数据库中创建 Spring Batch 表。
您可以通过执行 MySQL 的DDL 脚本手动执行此操作,或者如果您使用 Spring Boot,请设置 property spring.batch.initialize-schema=always
。
推荐阅读
- java - 如何从不同的数据库中获取映射的实体?
- python - Telethon 在按钮之后写消息/开始聊天 - 机器人在 /start 之前发送消息
- javascript - 在 c# (Unity) 中解析 JSON 文件
- xcode - 在 Appstore 上将版本设置为仅限 iPad
- php - 从 Laravel 的下拉菜单中获取数据
- next.js - NextJS 拆分块缓存在开发模式下不起作用
- visual-studio-code - 如何使用我的自定义字符串修改 VSCode 中的第 3 行(n)和每个 n+6(如 9、15、24 等)?
- c++ - 指针和整数的模棱两可的重载?
- android - 类中的空共享首选项
- swift - 转义闭包捕获变异的“自我”参数 (SWIFT 5)