SpringBoot, Hibernate and flyway db issue

AnnaKlein :

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:

  1. Adding a new user userRepo.save(new User("A")); to my empty db
  2. Shutdown application
  3. Add the flywaydb dependency to my pom
  4. create an empty .sql file named V1__baseline.sql to make use of spring.flyway.baseline-on-migrate = true and start the app, success, shutdown
  5. create a new sql file named V2__migrate.sql with content ALTER 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?

Artiow :

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.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=103075&siteId=1