【问题标题】:Spring Boot JPA initialize data - Syntax error in SQL statement ... expected "identifier"Spring Boot JPA 初始化数据 - SQL 语句中的语法错误......预期的“标识符”
【发布时间】:2022-01-14 16:55:06
【问题描述】:

尝试在启动时将数据实现到我的 Spring Boot 应用程序中。 据我研究,它应该是这样工作的:

user_role 类:

@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class UserRole {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String role;
}

schema.sql

CREATE TABLE `user_role` (
    `id` bigint(20) NOT NULL,
    `role` varchar(255) DEFAULT NULL,
    PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 

data.sql

INSERT INTO user_role (role) VALUES ('ADMIN');
INSERT INTO user_role (role) VALUES ('USER');

application.properties

spring.jpa.hibernate.ddl-auto=none
spring.jpa.defer-datasource-initialization=true
spring.sql.init.mode=always

但如果我尝试这样做,我在构建应用程序时只会收到以下错误:

SQL 语句中的语法错误 "CREATE TABLE USER_ROLE (ID BIGINT([*]20) NOT NULL, ROLE VARCHAR(255) DEFAULT NULL, PRIMARY KEY (ID)) ENGINE=INNODB DEFAULT字符集=UTF8MB4"; 预期“数组,不可见,可见,NOT,NULL,AS,DEFAULT,GENERATED,ON,NOT,NULL,AUTO_INCREMENT,DEFAULT,NULL_TO_DEFAULT,序列,选择性,COMMENT,CONSTRAINT,COMMENT,PRIMARY,UNIQUE,NOT,NULL,检查, REFERENCES, AUTO_INCREMENT, ., )"; SQL 语句: CREATE TABLE user_role (id bigint(20) NOT NULL, role varchar(255) DEFAULT NULL, PRIMARY KEY (id) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 [42001-202]

有人知道出了什么问题吗?

【问题讨论】:

  • 您有什么特别的原因要自己创建表格吗?您可以扩展 spring data jpa 存储库并创建表
  • @Gurkirat Singh Guliani:不,没有具体原因。我已经用 spring boot 数据创建了表。我只想在应用程序启动时在“user_role”表中实现数据“admin”和“user”。有没有更简单的方法?

标签: java spring-boot jpa


【解决方案1】:

Exception 说明你的 SQL 有问题。

您必须指定id 应该递增:

CREATE TABLE IF NOT EXISTS user_role
(
    id    INT AUTO_INCREMENT PRIMARY KEY,
    role  VARCHAR(50)  null
);

因为后面插入数据的时候,比如:

INSERT INTO user_role (role) VALUES ('ADMIN');

您不直接设置id,它应该由数据库引擎自动递增。

此外,JPA API 要求您的实体必须是可序列化的。 你必须像下面这样更新它:

public class UserRole implements Serializable {
    private static final long serialVersionUID = 1L;

可能出于您的目的,您选择了最简单的方法来执行此操作。

使用诸如 FlywayLiquiebase 之类的迁移应用程序并为此创建一些初始化脚本会更加困难。

但是,在这种情况下,您的数据库交互(例如向类添加新字段,从而分别更新数据库表)应该通过添加新的迁移脚本来完成。

写在这里,因为太长了,像帖子下的评论一样写。

【讨论】:

    【解决方案2】:

    如果您使用脚本创建了user_role 表,那么问题在于id 列定义中缺少AUTO_INCREMENT。因为您想在不手动添加 id 值的情况下插入字段。所以正确的建表sql代码应该是:

    CREATE TABLE `user_role` (
        `id` bigint(20) NOT NULL AUTO_INCREMENT,
        `role` varchar(255) DEFAULT NULL,
        PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 
    

    在这种情况下插入 sql 代码可以正常工作。

    但是你应该用 spring 生成一个表并用存储库插入数据!

    UserRole 实体的存储库:

    public interface UserRoleRepository extends CrudRepository<UserRole, Long> {}
    

    之后,只需使用服务中实体的新实例调用 save 方法:

    @AllArgsConstructor
    @Service
    public class YourService {
    
        private final UserRoleRepository userRoleRepository;
    
        public void exampleMethod() {
            final UserRole role = new UserRole();
            role.set("ADMIN");
            userRoleRepository.save(role);
        }
    }
    

    最后一件事:你真的想为角色创建表吗?我的意思是,如果用户可以创建其他角色,那么可以,但如果角色是固定的,那么只需将角色字段添加到字段类型为包含用户角色的枚举的用户即可。

    public enum UserRole {
        ADMIN,
        USER
    }
    

    具有角色字段的用户实体:

    @Entity
    public class User {
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        private int id;
    
        @Enumerated(EnumType.STRING)
        private UserRole role;
    }
    

    【讨论】:

      猜你喜欢
      • 2015-03-15
      • 2018-03-21
      • 2017-10-31
      • 1970-01-01
      • 2018-03-11
      • 2018-12-12
      • 2019-06-14
      • 2016-12-16
      • 1970-01-01
      相关资源
      最近更新 更多