SpringBoot、Hibernate 和 flyway 数据库问题
SpringBoot, Hibernate and flyway db issue
根据 rieckpil 建议更新
嗨,
现在我正面临一个问题,只有当我对 H2 数据库中的 add/read 实体使用 CrudRepository 时才会出现。
一个非常基本的例子:
我的属性:
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
和一个示例class
@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,我得到 异常:
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
我的步骤是:
- 正在向我的空数据库添加新用户
userRepo.save(new User("A"));
- 关闭应用程序
- 将 flywaydb 依赖项添加到我的 pom
- 创建一个名为
V1__baseline.sql
的空 .sql 文件以使用 spring.flyway.baseline-on-migrate = true
并启动应用程序,成功,关闭
- 创建一个名为
V2__migrate.sql
的新 sql 文件,内容为 ALTER TABLE USER ADD COLUMN LASTLOGIN bigint(20) default 0
然后我将字段 private long lastLogin;
添加到 class 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]
那么我在这里做错了什么?
您的 Flyway 脚本似乎没有被填充。你必须遵循像 V01__INIT.sql
这样的 Flyway 命名约定(你需要两个 _
)并将它们存储在 src/main/resources/db/migration
。
在您的应用程序启动期间,您应该会看到 Flyway 填充您的脚本或日志,表明您已将最新模式应用到数据库。
您可以在此处找到一个简单的 Flyway 示例:https://flywaydb.org/getstarted/how
此外,我建议使用 spring.jpa.hibernate.ddl-auto=validate
来确保只有 Flyway 创建您的数据库模式。
您的 class 字段命名为 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
class,指示 CrudRepository
所在的包。
根据 rieckpil 建议更新
嗨,
现在我正面临一个问题,只有当我对 H2 数据库中的 add/read 实体使用 CrudRepository 时才会出现。
一个非常基本的例子:
我的属性:
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
和一个示例class
@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,我得到 异常:
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
我的步骤是:
- 正在向我的空数据库添加新用户
userRepo.save(new User("A"));
- 关闭应用程序
- 将 flywaydb 依赖项添加到我的 pom
- 创建一个名为
V1__baseline.sql
的空 .sql 文件以使用spring.flyway.baseline-on-migrate = true
并启动应用程序,成功,关闭 - 创建一个名为
V2__migrate.sql
的新 sql 文件,内容为ALTER TABLE USER ADD COLUMN LASTLOGIN bigint(20) default 0
然后我将字段 private long lastLogin;
添加到 class 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]
那么我在这里做错了什么?
您的 Flyway 脚本似乎没有被填充。你必须遵循像 V01__INIT.sql
这样的 Flyway 命名约定(你需要两个 _
)并将它们存储在 src/main/resources/db/migration
。
在您的应用程序启动期间,您应该会看到 Flyway 填充您的脚本或日志,表明您已将最新模式应用到数据库。
您可以在此处找到一个简单的 Flyway 示例:https://flywaydb.org/getstarted/how
此外,我建议使用 spring.jpa.hibernate.ddl-auto=validate
来确保只有 Flyway 创建您的数据库模式。
您的 class 字段命名为 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
class,指示 CrudRepository
所在的包。