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 в классе, поскольку его идентичность определяется значениями, которые он несет. Однако вам необходимо идентифицировать строку в таблице базы данных и связать ее с ее владельцем, поэтому вам нужно создать составные первичные ключи в объектах значений, если вы хотите сохранить их в разных таблицах.