Spring Data JDB C: обязательное свойство идентификатора не найдено для коллекции MappedCollection - PullRequest
0 голосов
/ 02 марта 2020
class Game(
    @MappedCollection(idColumn = "game")         <---- unnecessary
    var rules: List<Rule> = emptyList(),
){
    @Id
    var id: Long? = null
}

data class Rule(
    @MappedCollection(idColumn = "rule", keyColumn = "rule_key")<---- unnecessary
    val ruleValues: List<RuleValue>
) 

data class RuleValue(val value: String)

и схема

create table game
(
    id              serial primary key
);

create table rule
(
    id              serial primary key,
    game            long references game (id),
    game_key        integer
);

create table rule_value
(
    id               serial primary key,
    game             long references game (id),
    game_key         integer,
    rule             long references rule (id),
    rule_key         integer,
    value            varchar(256)
);

Вкратце у меня есть Game в качестве совокупности root. game имеет список (порядок важен) Rules, а rule имеет список (порядок важен) rule values. rule value - это просто строка на данный момент, но она может расширяться в будущем.

У меня есть 2 вопроса:

1) Обязательное свойство идентификатора не найдено : Когда я при попытке сохранить игру я получаю сообщение об исключении Caused by: java.lang.IllegalStateException: Required identifier property not found for class com...RuleValue! .

2) java. sql .SQLSyntaxErrorException : зачем нужны столбцы game и game_key в таблица rule_value? Если я не поставлю их, я получу Caused by: java.sql.SQLSyntaxErrorException: Unknown column 'game_key' in 'field list'

Я использую Spring Boot версии 2.2.5.RELEASE с org.springframework.boot:spring-boot-starter-data-jdbc соответствует spring-data-jdbc версии 1.1.5.RELEASE


РЕШЕНИЕ-1: добавление поля ID в класс

Как подсказал @ chrylis-onstrike-, я добавил @Id поля во все классы данных

class Game(
    @MappedCollection(idColumn = "game")
    var rules: List<Rule> = emptyList(),
){
    @Id
    var id: Long? = null
}

data class Rule(
    @MappedCollection(idColumn = "rule", keyColumn = "rule_key")
    val ruleValues: List<RuleValue>
) {
    @Id
    var id: Long? = null <---- this is new
}

data class RuleValue(val value: String) {
    @Id
    var id: Long? = null  <---- this is new
}

и схема изменена на

create table game
(
    id              serial primary key
);

create table rule
(
    id              serial primary key,
    game            long references game (id),
    game_key        integer
);

create table rule_value
(
    id               serial primary key,
#    game             long references game (id), <---- removed this
#    game_key         integer,                   <---- removed this
    rule             long references rule (id),
    rule_key         integer,
    value            varchar(256)
);


РЕШЕНИЕ-2: добавление составных первичных ключей в скрипт

class Game(
    @MappedCollection(idColumn = "game")
    var rules: List<Rule> = emptyList(),
){
    @Id
    var id: Long? = null
}

data class Rule(
    @MappedCollection(idColumn = "rule", keyColumn = "rule_key")
    val ruleValues: List<RuleValue>
)

data class RuleValue(val value: String) 

и схема изменена на

create table game
(
    id              serial primary key
);

create table rule
(
#    id      serial primary key, <---- removed 
    game     integer,
    game_key integer,
    primary key (game, game_key) <---- added 
);

create table rule_value
(
#    id      serial primary key, <---- removed 
    game     integer, <---- added 
    game_key integer, <---- added 
    rule_key integer,
    value    varchar(2048),
    primary key (game, game_key, rule_key) <---- added 
);


Заключение Вам необходимо решить, являются ли ваши объекты value object s или сущностью. У объекта значения, вероятно, не должно быть поля id в классе, поскольку его идентичность определяется значениями, которые он несет. Однако вам необходимо идентифицировать строку в таблице базы данных и связать ее с ее владельцем, поэтому вам нужно создать составные первичные ключи в объектах значений, если вы хотите сохранить их в разных таблицах.

1 Ответ

1 голос
/ 03 марта 2020
  1. Обязательное свойство идентификатора не найдено.

    Я согласен с @ chrylis-onstrike - ошибка говорит вам добавить поле с аннотацией @Id. Но я также согласен с вами: это не должно быть так. Мне понадобится хотя бы полная трассировка стека, чтобы понять, что происходит. А репродуктор был бы еще лучше. Не стесняйтесь создавать проблему на https://jira.spring.io/browse/DATAJDBC

    Дальнейшее исследование предоставленного репродуктора показало, что проблема вызвана тем, что столбец id все еще присутствует в базе данных и является identity столбец. Поэтому JDB C возвращает значение после вставки и Spring Data. JDB C пытается установить его как идентификатор объекта, а затем не может установить этот идентификатор с исключением, упомянутым в вопросе.

  2. Зачем мне игра и столбцы game_key в таблице rule_value?

    Пока Rule не имеет выделенного идентификатора, его первичный ключ является комбинацией game и game_key, поэтому ссылка из rule_value и обратно состоит из этих двух полей.

    Они не должны быть необходимы, когда Rule имеет идентификатор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...