【问题标题】:SpringBoot, Hibernate and flyway db issueSpring Boot、Hibernate 和 flyway db 问题
【发布时间】:2019-03-03 18:01:45
【问题描述】:

更新了 rieckpil 的建议

嗨,

现在我面临一个问题,该问题仅在我使用 CrudRepository 从 H2 DB 添加/读取实体时出现。

一个非常基本的例子:

我的属性

spring.datasource.url=jdbc:h2:file:~/flyawayTest;DB_CLOSE_ON_EXIT=FALSE;AUTO_RECONNECT=TRUE
spring.datasource.username=admin
spring.datasource.password=password
spring.datasource.driver-class-name=org.h2.Driver
spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=validate
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.H2Dialect
spring.flyway.baseline-on-migrate = true

和一个示例类

@Entity
@Data
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String username;

    public User() {
    }

    public User(String username) {
        this.username = username;
    }

    public User(String username, long lastLogin) {
        this.username = username;
        //this.lastLogin = lastLogin;
    }
}

使用这个 .sql 文件

CREATE TABLE USER (
  ID bigint(20) NOT NULL AUTO_INCREMENT,
  USERNAME varchar(100) NOT NULL,
  PRIMARY KEY (ID)
);

insert into USER (USERNAME) values ('User');

ALTER TABLE USER ADD COLUMN LASTLOGIN bigint(20) default 0

如果我要使用 CrudRepository,我会遇到 exception

Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing column [last_login] in table [user]

回购

@Repository
public interface UserRepo extends CrudRepository<User, Long> {

}

Helper-Class 来测试这个过程

@Component
public class UCML implements CommandLineRunner {


    private final UserRepo userRepo;

    public UCML(UserRepo userRepo) {
        this.userRepo = userRepo;
    }

    @Override
    public void run(String... args) throws Exception {

        userRepo.save(new User("TestUser"));
        userRepo.findAll().forEach(System.out::println);
    }
}

V1__baseline.sql(为空,因为它仅用于获取包含用户 TestUser 的数据库的基线

V2__migrate.sql

ALTER TABLE USER ADD COLUMN LASTLOGIN bigint(20) default 0

我的步骤是:

  1. 将新用户 userRepo.save(new User("A")); 添加到我的空数据库中
  2. 关闭应用程序
  3. 将 flywaydb 依赖添加到我的 pom 中
  4. 创建一个名为V1__baseline.sql 的空.sql 文件以使用spring.flyway.baseline-on-migrate = true 并启动应用程序,成功,关闭
  5. 创建一个名为V2__migrate.sql 的新sql 文件,内容为ALTER TABLE USER ADD COLUMN LASTLOGIN bigint(20) default 0

然后我将字段private long lastLogin; 添加到类User

当我现在再次启动应用程序时,我收到上面提到的错误

Caused by: javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: missing column [last_login] in table [user]

那么我在这里做错了什么?

【问题讨论】:

    标签: java hibernate spring-boot h2 flyway


    【解决方案1】:

    您的 Flyway 脚本似乎没有被填充。您必须遵循像 V01__INIT.sql 这样的 Flyway 命名约定(您需要两个 _)并将它们存储在 src/main/resources/db/migration

    在您的应用程序启动期间,您应该会看到 Flyway 填充您的脚本或您已将最新架构应用到数据库的日志。

    您可以在此处找到一个简单的 Flyway 示例:https://flywaydb.org/getstarted/how

    此外,我建议使用spring.jpa.hibernate.ddl-auto=validate 以确保只有 Flyway 会创建您的数据库架构。

    【讨论】:

    • 我根据您的建议更新了我的问题。确实错误发生了变化,但我什至不知道现在是更好还是更糟。
    • 你能更新你的示例类吗?因为现在有 lastLogin 对象属性。错误消息说 JPA 缺少数据库列。另外,请将所有您的 Flyway 脚本添加到您的问题中
    • 完成。 lastLogin 属性是我要添加到表中的列user
    • 我建议删除当前数据库(如果可能),然后仅使用 Flyway 初始化数据库架构并创建一个迁移脚本 V01__INIT_USER.sql 来初始化整个用户表
    【解决方案2】:

    您的类字段名为lastLogin,Hibernate 将其转换为last_login 以在数据库中查找列。您必须像这样手动指定字段对应的列:

    @Data
    @Entity
    @Table(name = "USER", schema = "YOUR_SCHEMA_NAME")
    public class User {
    
        @Id
        @Column(name = "ID", nullable = false)
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private Long id;
    
        @Basic
        @Column(name = "USERNAME", nullable = false)
        private String username;
    
        @Basic
        @Column(name = "LASTLOGIN")
        private Long lastLogin = 0;
    }
    

    另外,您不再需要@Repository

    您必须使用@EnableJpaRepositories 注释标记您的SpringBootServletInitializer 类,指示CrudRepository 所在的包。

    【讨论】:

    • 非常感谢。还有关于 @Repository 注释的附加信息,这对我改进很有用!有点跑题了,但是你有一个很好的消息来源来了解这样的变化吗?
    猜你喜欢
    • 1970-01-01
    • 2023-03-09
    • 2017-11-10
    • 1970-01-01
    • 2020-12-31
    • 2020-02-02
    • 2019-04-19
    • 2015-05-29
    • 1970-01-01
    相关资源
    最近更新 更多