You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Batch教程实践遇BadSqlGrammarException:PEOPLE表不存在或权限不足

Spring Batch实操报错:BadSqlGrammarException(PEOPLE表不存在/权限不足)

问题描述

我正在跟着Spring官方的《创建批处理服务》入门指南实操,指南用的是HyperSQL数据库。我完全按步骤来,却碰到了BadSqlGrammarException错误,提示“user lacks privilege or object not found: PEOPLE”,对应的SQL语句是INSERT INTO people(first_name,last_name) VALUES (?, ?)。下面是完整的错误栈和我的BatchConfiguration配置类代码,作为新手我搜了相关问题但没找到解决办法。

错误栈信息

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; 错误的SQL语法 [INSERT INTO people(first_name,last_name) VALUES (?, ?)]
    at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:101) ~[spring-jdbc-6.0.4.jar:6.0.4]
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:70) ~[spring-jdbc-6.0.4.jar:6.0.4]
    at org.springframework.jdbc.core.JdbcTemplate.translateException(JdbcTemplate.java:1538) ~[spring-jdbc-6.0.4.jar:6.0.4]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:667) ~[spring-jdbc-6.0.4.jar:6.0.4]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:691) ~[spring-jdbc-6.0.4.jar:6.0.4]
    at org.springframework.jdbc.core.JdbcTemplate.batchUpdate(JdbcTemplate.java:1034) ~[spring-jdbc-6.0.4.jar:6.0.4]
    at org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate.batchUpdate(NamedParameterJdbcTemplate.java:373) ~[spring-jdbc-6.0.4.jar:6.0.4]
    at org.springframework.batch.item.database.JdbcBatchItemWriter.write(JdbcBatchItemWriter.java:190) ~[spring-batch-infrastructure-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.writeItems(SimpleChunkProcessor.java:203) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.doWrite(SimpleChunkProcessor.java:170) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.write(SimpleChunkProcessor.java:297) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.step.item.SimpleChunkProcessor.process(SimpleChunkProcessor.java:227) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.step.item.ChunkOrientedTasklet.execute(ChunkOrientedTasklet.java:75) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:389) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.step.tasklet.TaskletStep$ChunkTransactionCallback.doInTransaction(TaskletStep.java:313) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) ~[spring-tx-6.0.4.jar:6.0.4]
    at org.springframework.batch.core.step.tasklet.TaskletStep$2.doInChunkContext(TaskletStep.java:256) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.scope.context.StepContextRepeatCallback.doInIteration(StepContextRepeatCallback.java:82) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.repeat.support.RepeatTemplate.getNextResult(RepeatTemplate.java:362) ~[spring-batch-infrastructure-5.0.0.jar:5.0.0]
    at org.springframework.batch.repeat.support.RepeatTemplate.executeInternal(RepeatTemplate.java:206) ~[spring-batch-infrastructure-5.0.0.jar:5.0.0]
    at org.springframework.batch.repeat.support.RepeatTemplate.iterate(RepeatTemplate.java:139) ~[spring-batch-infrastructure-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.step.tasklet.TaskletStep.doExecute(TaskletStep.java:241) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.step.AbstractStep.execute(AbstractStep.java:227) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.job.SimpleStepHandler.handleStep(SimpleStepHandler.java:153) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.job.flow.JobFlowExecutor.executeStep(JobFlowExecutor.java:68) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.job.flow.support.state.StepState.handle(StepState.java:68) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.job.flow.support.SimpleFlow.resume(SimpleFlow.java:167) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.job.flow.support.SimpleFlow.start(SimpleFlow.java:142) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.job.flow.FlowJob.doExecute(FlowJob.java:137) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.job.AbstractJob.execute(AbstractJob.java:316) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.launch.support.SimpleJobLauncher$1.run(SimpleJobLauncher.java:157) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.core.task.SyncTaskExecutor.execute(SyncTaskExecutor.java:50) ~[spring-core-6.0.4.jar:6.0.4]
    at org.springframework.batch.core.launch.support.SimpleJobLauncher.run(SimpleJobLauncher.java:148) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.batch.core.launch.support.TaskExecutorJobLauncher.run(TaskExecutorJobLauncher.java:70) ~[spring-batch-core-5.0.0.jar:5.0.0]
    at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.execute(JobLauncherApplicationRunner.java:199) ~[spring-boot-autoconfigure-3.0.2.jar:3.0.2]
    at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.executeLocalJobs(JobLauncherApplicationRunner.java:178) ~[spring-boot-autoconfigure-3.0.2.jar:3.0.2]
    at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.launchJobFromProperties(JobLauncherApplicationRunner.java:166) ~[spring-boot-autoconfigure-3.0.2.jar:3.0.2]
    at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:161) ~[spring-boot-autoconfigure-3.0.2.jar:3.0.2]
    at org.springframework.boot.autoconfigure.batch.JobLauncherApplicationRunner.run(JobLauncherApplicationRunner.java:156) ~[spring-boot-autoconfigure-3.0.2.jar:3.0.2]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:758) ~[spring-boot-3.0.2.jar:3.0.2]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:748) ~[spring-boot-3.0.2.jar:3.0.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:315) ~[spring-boot-3.0.2.jar:3.0.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1302) ~[spring-boot-3.0.2.jar:3.0.2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1291) ~[spring-boot-3.0.2.jar:3.0.2]
    at com.example.batchprocessing.DemoApplication.main(DemoApplication.java:10) ~[classes/:na]
Caused by: java.sql.SQLSyntaxErrorException: 用户权限不足或对象不存在:PEOPLE,语句为 [INSERT INTO people(first_name,last_name) VALUES (?, ?)]
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    at org.hsqldb.jdbc.JDBCPreparedStatement.<init>(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    at org.hsqldb.jdbc.JDBCConnection.prepareStatement(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    at com.zaxxer.hikari.pool.ProxyConnection.prepareStatement(ProxyConnection.java:327) ~[HikariCP-5.0.1.jar:na]
    at com.zaxxer.hikari.pool.HikariProxyConnection.prepareStatement(HikariProxyConnection.java) ~[HikariCP-5.0.1.jar:na]
    at org.springframework.jdbc.core.JdbcTemplate$SimplePreparedStatementCreator.createPreparedStatement(JdbcTemplate.java:1637) ~[spring-jdbc-6.0.4.jar:6.0.4]
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:649) ~[spring-jdbc-6.0.4.jar:6.0.4]
    ... 41 common frames omitted
Caused by: org.hsqldb.HsqlException: 用户权限不足或对象不存在:PEOPLE
    at org.hsqldb.error.Error.error(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    at org.hsqldb.error.Error.error(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    at org.hsqldb.ParserDQL.readTableName(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    at org.hsqldb.ParserDQL.readRangeVariableForDataChange(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    at org.hsqldb.ParserDML.compileInsertStatement(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    at org.hsqldb.ParserCommand.compilePart(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    at org.hsqldb.ParserCommand.compileStatement(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    at org.hsqldb.Session.compileStatement(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    at org.hsqldb.StatementManager.compile(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    at org.hsqldb.Session.execute(Unknown Source) ~[hsqldb-2.7.1.jar:2.7.1]
    ... 47 common frames omitted

BatchConfiguration配置类代码

package com.example.batchprocessing;

import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider;
import org.springframework.batch.item.database.JdbcBatchItemWriter;
import org.springframework.batch.item.database.builder.JdbcBatchItemWriterBuilder;
import org.springframework.batch.item.file.FlatFileItemReader;
import org.springframework.batch.item.file.builder.FlatFileItemReaderBuilder;
import org.springframework.batch.item.file.mapping.BeanWrapperFieldSetMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

@Configuration
public class BatchConfiguration {

    @Bean
    public FlatFileItemReader<Person> reader() {
        return new FlatFileItemReaderBuilder<Person>()
                .name("personItemReader")
                .resource(new ClassPathResource("sample-data.csv"))
                .delimited()
                .names(new String[]{"firstName", "lastName"})
                .fieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
                    setTargetType(Person.class);
                }})
                .build();
    }

    @Bean
    public PersonItemProcessor processor() {
        return new PersonItemProcessor();
    }

    @Bean
    public JdbcBatchItemWriter<Person> writer(DataSource dataSource) {
        return new JdbcBatchItemWriterBuilder<Person>()
                .itemSqlParameterSourceProvider(new BeanPropertyItemSqlParameterSourceProvider<>())
                .sql("INSERT INTO people(first_name,last_name) VALUES (:firstName, :lastName)")//此处报错
                .dataSource(dataSource)
                .build();
    }
    
    @Bean
    public Job importUserJob(JobRepository jobRepository,
                             JobCompletionNotificationListener listener, Step step1) {
        return new JobBuilder("importUserJob", jobRepository)
                .incrementer(new RunIdIncrementer())
                .listener(listener)
                .flow(step1)
                .end()
                .build();
    }

    @Bean
    public Step step1(JobRepository jobRepository,
                      PlatformTransactionManager transactionManager, JdbcBatchItemWriter<Person> writer) {
        return new StepBuilder("step1", jobRepository)
                .<Person, Person> chunk(10, transactionManager)
                .reader(reader())
                .processor(processor())
                .writer(writer)
                .build();
    }
}

解决办法

核心原因

错误提示明确指向PEOPLE表不存在或权限不足,本质是数据库中没有提前创建people表,Spring Batch写入数据时找不到目标表。

具体步骤

  1. 添加建表脚本
    在src/main/resources目录下创建schema.sql文件,写入以下建表语句:

    CREATE TABLE people (
        id BIGINT IDENTITY PRIMARY KEY,
        first_name VARCHAR(255),
        last_name VARCHAR(255)
    );
    

    Spring Boot启动时会自动执行该脚本,初始化HyperSQL数据库的表结构。

  2. 确认数据库配置
    检查application.properties(或application.yml)中的数据库配置是否正确,确保使用的是内存模式的HyperSQL:

    spring.datasource.url=jdbc:hsqldb:mem:testdb
    spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
    spring.datasource.username=sa
    spring.datasource.password=
    spring.jpa.hibernate.ddl-auto=none
    

    其中spring.jpa.hibernate.ddl-auto=none用于禁用Hibernate自动生成表,确保使用我们手动编写的schema.sql。

  3. 验证表是否创建成功
    可以通过添加日志或数据库客户端连接HyperSQL内存库查看表状态。连接信息:

    • URL: jdbc:hsqldb:mem:testdb
    • 用户名: sa
    • 密码: 空

补充说明

官方指南默认会通过schema.sql初始化表结构,可能你在实操时遗漏了这个步骤。Spring Batch的写入操作依赖目标表已存在,必须确保表创建完成后再执行批处理任务。

内容的提问来源于stack exchange,提问作者arihant raj singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 08:59:14