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

Spring Boot中JdbcUserDetailsManager无法创建表及插入数据问题排查

问题

整合Spring Security与JdbcUserDetailsManager的Spring Boot应用启动时出现SQL语法错误:

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [insert into users (username, password, enabled) values (?,?,?)]

原以为是缺少users表,但JdbcUserDetailsManager应该自动创建该表,手动创建表后错误依旧。

配置类代码

@Configuration
public class UserDetailsConfig {

    @Autowired
    private DataSource dataSource;

    @Bean
    UserDetailsManager users(DataSource dataSource) {
        System.out.println();
        UserDetails defaultUser = User.builder()
                .username("admin")
                .password(this.passwordEncoder().encode("admin"))
                .roles("ADMIN", "USER")
                .build();
        JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource);
        try {
            //users.deleteUser(defaultUser.getUsername());
            users.createUser(defaultUser);
        } catch (Exception e) {
            System.out.println("database not yet initialized");
            e.printStackTrace();
        }
        return users;
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

}

application配置

spring.datasource.url=jdbc:postgresql://localhost:5432/food_production
spring.datasource.username=postgres
spring.datasource.password=123
spring.datasource.driver-class-name=org.postgresql.Driver

spring.jpa.hibernate.ddl-auto=update

spring.jpa.show-sql=true

server.port=6969

spring.security.user.name=admin
spring.security.user.password=admin
spring.security.user.roles=admin

环境信息

  • Spring版本:3.2.2
  • Java版本:17
  • PostgreSQL版本:16.2

可能的原因及解决方法

  • JdbcUserDetailsManager无自动建表逻辑
    别被误导,JdbcUserDetailsManager本身不会自动创建表,它只负责用预设SQL操作表。你需要自行创建符合要求的表结构,或者通过schema.sql初始化表。

  • 手动建表结构不符合要求
    若手动创建的users表字段类型、约束不对,会触发语法错误。PostgreSQL下,符合JdbcUserDetailsManager要求的表结构如下:

    -- users表
    CREATE TABLE users (
        username VARCHAR(50) PRIMARY KEY,
        password VARCHAR(255) NOT NULL,
        enabled BOOLEAN NOT NULL
    );
    
    -- 权限表(必须配套创建,因为用到了roles)
    CREATE TABLE authorities (
        username VARCHAR(50) NOT NULL,
        authority VARCHAR(50) NOT NULL,
        PRIMARY KEY (username, authority),
        FOREIGN KEY (username) REFERENCES users(username)
    );
    
  • Bean初始化时机冲突
    你在创建UserDetailsManager Bean时直接调用createUser,此时Hibernate的ddl-auto=update可能还未执行完毕,表未创建就执行插入操作。可以把初始化用户的逻辑放到ApplicationRunner中,等应用启动完成后再执行:

    @Bean
    ApplicationRunner initUser(UserDetailsManager userDetailsManager, PasswordEncoder passwordEncoder) {
        return args -> {
            if (!userDetailsManager.userExists("admin")) {
                UserDetails defaultUser = User.builder()
                        .username("admin")
                        .password(passwordEncoder.encode("admin"))
                        .roles("ADMIN", "USER")
                        .build();
                userDetailsManager.createUser(defaultUser);
            }
        };
    }
    
  • 配置冲突
    你同时配置了spring.security.user.*和自定义UserDetailsManager,会导致Spring Security自动配置与自定义配置冲突。删掉spring.security.user.name、spring.security.user.password、spring.security.user.roles这三行,仅保留自定义配置。

  • 表名/字段名大小写问题
    PostgreSQL默认对标识符大小写不敏感,但如果创建表时用了双引号(如CREATE TABLE "Users"),就会区分大小写。检查你的表名是否和JdbcUserDetailsManager默认SQL一致,即小写的users和authorities。

内容的提问来源于stack exchange,提问作者Kreuterkeule

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 09:23:12