SpringBoot, Hibernate и выпуск БД - PullRequest
       32

SpringBoot, Hibernate и выпуск БД

0 голосов
/ 27 сентября 2018

обновлено с предложением 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

Если я собираюсь работать с репозиторием Crud, я получил исключение :

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> {

}

Хелпер-класс для проверки этой процедуры

@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. создать пустой файл .sql с именем V1__baseline.sql чтобы использовать spring.flyway.baseline-on-migrate = true и запустить приложение, успех, завершение работы
  5. создать новый файл sql с именем V2__migrate.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]

Так что я тут не так делаю?

Ответы [ 2 ]

0 голосов
/ 28 сентября 2018

Ваше поле класса с именем 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.

Вы должны пометить свой класс SpringBootServletInitializer с помощью@EnableJpaRepositories аннотация с указанием пакета, в котором находится CrudRepository.

0 голосов
/ 27 сентября 2018

Похоже, ваши скрипты Flyway не заполняются.Вы должны следовать правилам именования Flyway, например V01__INIT.sql (вам нужно два _), и хранить их в src/main/resources/db/migration.

Во время запуска вашего приложения вы должны увидеть, что Flyway либо заполняет ваши сценарии, либо журналы, что вы уже применили последнюю схему к базе данных.

Простой пример Flyway можно найти здесь.: https://flywaydb.org/getstarted/how

Кроме того, я бы порекомендовал использовать spring.jpa.hibernate.ddl-auto=validate, чтобы убедиться, что только Flyway создает схему вашей базы данных.

...