Странный конфликт проверки в Spring JPA TableGenerator

У меня есть устаревшая база данных с составным первичным ключом в таблице project. (BaseEntity содержит общие свойства для lastModifiedDate и lastModifiedBy)

@Entity
@IdClass(ProjectPk.class)
public class Project extends BaseEntity {

    @Id
    @GeneratedValue(strategy=GenerationType.TABLE, generator = "nextProjectId")
    @TableGenerator(
            name = "nextProjectId",
            table = "projectId",
            pkColumnName = "proj_Id",
            pkColumnValue = "proj_id"
    )
    private Long  projId;

    @Id
    private int version;

  //other properties, getters and setters omitted for clarity
}

класс ПК

public class ProjectPk implements java.io.Serializable {
    private int  projId;
    private int  version;

  //both constructoirs, equals, hashcode, getters and setters omitted for clarity
}
  • У меня есть файлы миграции пролетного пути для имитации производственной базы данных.
drop table if exists project;
CREATE TABLE project
(
    proj_id             bigint,
    version             int,
    -- other columns omitted for clarity
    PRIMARY KEY (`proj_id`, `version`)
) ENGINE=InnoDB;

drop table if exists project_id;
CREATE TABLE project_id
(
    proj_id             bigint
) ENGINE=InnoDB;

  • flyway создает таблицы в соответствии с заказом в файле миграции
Table: project_id
Columns:
proj_id bigint
...


Table: project
Columns:
proj_id bigint PK 
version int PK
...

во время сборки maven я получаю ошибку проверки

  • Schema-validation: wrong column type encountered in column [proj_id] in table [project_id]; found [bigint (Types#BIGINT)], but expecting [varchar(255) (Types#VARCHAR)]

Что я сделал не так, чтобы ожидался спящий режим [varchar(255) (Types#VARCHAR)]?

Это проект SpringBoot 2.6.6 с базой данных MySql.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Версия Java на основе версии загрузки
Версия Java на основе версии загрузки
Если вы зайдете на официальный сайт Spring Boot , там представлен start.spring.io , который упрощает создание проектов Spring Boot, как показано ниже.
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
1
0
56
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я вижу следующие проблемы с вашим кодом:

  1. Несоответствие типов между Project.projId (длинный тип) и ProjectPk.projId (тип int).
  2. Вы используете неправильную структуру таблицы для таблицы project_id.

Вы можете увидеть рабочий пример ниже.

Предположим, что у вас есть следующие таблицы:

CREATE TABLE test_project
(
    proj_id   bigint,
    version   int,
    title     VARCHAR(50),
    
    PRIMARY KEY (proj_id, version)
);

create table table_identifier (
    table_name varchar(255) not null,
    product_id bigint,
    primary key (table_name)
);
insert into table_identifier values ('test_project', 20);

и следующее отображение:

@Entity
@Table(name = "test_project")
@IdClass(ProjectPk.class)
public class Project {

    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "nextProjectId")
    @TableGenerator(
        name = "nextProjectId",
        table = "table_identifier",
        pkColumnName = "table_name",
        valueColumnName = "product_id",
        allocationSize = 5
    )
    @Column(name = "proj_id")
    private Long  projId;

    @Id
    private int version;

    // other fields, getters, setters ...
}

вы сможете сохранить объект, как показано ниже:

Project project = new Project();
project.setVersion(1);
// ...
entityManager.persist(project);

Благодарю за ваш ответ. Возможно ли иметь table_identifier без столбца «table_name varchar (255) not null»? К сожалению, в устаревшей таблице базы данных нет этого столбца. Возможно, проблема в том, что Hibernate ожидает этот столбец по дизайну (т.е. предполагается наличие нескольких строк для каждой таблицы), но в устаревшей базе данных нет столбца идентификатора таблицы. Я предполагаю, что тот, кто проектировал макет БД, имел в виду что-то вроде «сгенерированной последовательности БД».

AlexeiP 29.10.2022 19:36

Я понял! Я неправильно истолковал значение pkColumnName = "proj_Id". Позвольте мне попробовать поиграть с ним.

AlexeiP 29.10.2022 19:44

См. эту часть документации по спящему режиму. По умолчанию таблица использования гибернации hibernate_sequences

SternK 29.10.2022 19:57

Я думаю, что невозможно иметь table_identifier без столбца table_name, потому что спящий режим использует эту таблицу для хранения текущего значения последовательности для каждой таблицы, использующей стратегию GenerationType.TABLE.

SternK 29.10.2022 20:15

Спасибо, мне действительно нужно убедить администратора базы данных изменить таблицу последовательностей, созданную 20 лет назад ))).

AlexeiP 29.10.2022 20:22

Другие вопросы по теме