Spring data jdbc: one-to-one, one-to-many relations
Т.к. в Spring Data JDBC нет стандартных хибернейтовских аннотаций типа @OneToOne, @OneToMany и @JoinColumn, то для меня было проблематично понять можно ли там вообще организовать отношения и использовать их при получении или сохранении объектов. Оказалось это делается так:
One-To-One
@Getter @Builder @NoArgsConstructor @AllArgsConstructor public class Operation { @Id private Long id; //idColumn - The column name for id column in the corresponding relationship table. @MappedCollection (idColumn = "operation_id" ) private TaxInfo taxInfo; } ------------------------------------------------------------- @Getter @Builder @NoArgsConstructor @AllArgsConstructor public class TaxInfo { @Id private Long id; private Long operationId; private Integer amount; } |
При такой реализации объект Operation без проблем вычитывается из БД уже с смапленным внутрь TaxInfo. Так же без проблем работает сохранение нового Operation с заполненным TaxInfo (корректно заполняются поля id и operationId.
One-To-Many
Несколько проблематично отношение один ко многим. Здесь сложность состояла в том, что я использовал List для агрегации нескольких TaxInfo, и при сохранении получал эксепшн ConstraintViolationException.
Решение состояло в том, чтобы использовать Set (или Map):
@Getter @Builder @NoArgsConstructor @AllArgsConstructor public class Operation { @Id private Long id; //idColumn - The column name for id column in the corresponding relationship table. @Builder .Default @MappedCollection (idColumn = "operation_id" ) private Set<TaxInfo> taxInfo = new HashSet<>(); } ------------------------------------------------------------- @Getter @Builder @NoArgsConstructor @AllArgsConstructor public class TaxInfo { @Id private Long id; private Long operationId; private Integer amount; } |
При такой реализации объект Operation без проблем вычитывается из БД уже с смапленными внутрь TaxInfo. Так же без проблем работает сохранение нового Operation с заполненными TaxInfo (корректно заполняются поля id и operationId.
Теперь про эксепшены. У меня были проблемы именно с аннотацией @MappedCollection в совокупности с использованием List:
- использование @MappedCollection(idColumn = «operation_id»)
Эксепшн ConstraintViolationException (Столбец «OPERATION_KEY» не найден). Проблема в том, что нужно указать keyColumn (или использовать суффикс «_KEY»). keyColumn — The column name for key columns of List or Map collections in the corresponding relationship table. Т.е. как я понял, приложение желает заполнить id для List или key для Map. И если с Map всё вроде ясно, то заполнение id для List — странная затея, и мне так и не удалось понять как оно работает (поятоянно получал эксепшн при сохранении)
- использование @MappedCollection(idColumn = «operation_id», keyColumn = «operation_id») или @MappedCollection(idColumn = «operation_id», keyColumn = «id»)
Эксепшн ConstraintViolationException Нарушение ссылочной целостности. Второй вариант ( keyColumn = «id» ) может показаться рабочим, но только при сохранении первой записи. Тоже не понятно как это использовать с List