updated with rieckpil suggestion
Hi,
right now I am facing an issue which appears only when I am using a CrudRepository to add/read entities from a H2 DB.
A very basic example which works:
My properties:
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
and an example 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;
}
}
Using this .sql file
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
If I am going to work with a CrudRepository I got the 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]
Repo
@Repository
public interface UserRepo extends CrudRepository<User, Long> {
}
Helper-Class to test this procedure
@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 (is empty since it is only used to get a baseline of the DB with consisting user TestUser
V2__migrate.sql
ALTER TABLE USER ADD COLUMN LASTLOGIN bigint(20) default 0
My steps are:
- Adding a new user
userRepo.save(new User("A"));
to my empty db - Shutdown application
- Add the flywaydb dependency to my pom
- create an empty .sql file named
V1__baseline.sql
to make use ofspring.flyway.baseline-on-migrate = true
and start the app, success, shutdown - create a new sql file named
V2__migrate.sql
with contentALTER TABLE USER ADD COLUMN LASTLOGIN bigint(20) default 0
then I add the field private long lastLogin;
to the class User
.
When I now start the application again I get the error I mentioned above
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]
So what I do wrong here?
Your class field named as lastLogin
and Hibernate translate it to last_login
to find a column in the database. You must specify which column the field corresponds to manually like this:
@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;
}
Also, you don't need @Repository
anymore.
You must tag your SpringBootServletInitializer
class with an @EnableJpaRepositories
annotation indicating the package where the CrudRepository
are located.