У меня есть две сущности в двунаправленном отношении «многие ко многим».
A <-> «многие ко многим» <-> B
У меня есть конечная точка, где клиент может создатьэкземпляра A, и в то же время добавьте к этому A некоторое количество объектов B, передав массив ключей идентификаторов объектов B.Помните , что эти объекты B уже существуют в базе данных .Не существует бизнес или программных решений для тесной связи их создания с созданием A.
Так что класс A выглядит так, а B - то же самое, но со ссылками на A.
@Entity
class A {
@Id
@GeneratedValue
int id;
@ManyToMany
List<B> bs;
String someValue;
int someValue2;
// With some getters and setters omitted for brevity
}
Итак, сначала попытайтесь, чтобы мой код конечной точки выглядел следующим образом.
public A createA(@RequestBody A aToCreate) {
A savedA = aRepository.save(aToCreate);
savedA.getbs().forEach(b -> Service.callWithBValue(b.getImportantValue());
}
И клиент отправил бы такой JSON-запрос, чтобы создать новый A, который содержал бы ссылки на B с идентификатором 3 и Bс идентификатором 4.
{
"bs": [{id:3}, {id:10}],
"someValue": "not important",
"someValue2": 1
}
Хорошо, так что все работает нормально, я вижу, что все поля десериализованы хорошо, и затем я иду, чтобы сохранить мой новый экземпляр A, используя.
aRepository.save(aToCreate);
И этопрекрасно работает ... за исключением того факта, что мне нужны все данные, связанные с экземплярами сущности b, но объект A, возвращаемый aRepository.save()
, заполнил только поля автозаполнения на A и ничего не сделал с сущностями B.Они все еще просто полые сущности, у которых установлены только свои идентификаторы.
Wut.
Итак, я осматриваюсь, и, очевидно, SimpleJpaRepository делает это.
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
Ипоскольку объект A является совершенно новым, он сохраняет только объект A, но не объединяет его, поэтому я не получаю никаких богатых данных B.Итак, хорошо, если я изменю свой код, чтобы принять это во внимание, я получу это.
public A createA(@RequestBody A aToCreate) {
A savedA = aRepository.save(aRepository.save(aToCreate));
savedA.getbs().forEach(b -> Service.callWithBValue(b.getImportantValue());
}
, который работает просто отлично.При втором проходе через службу хранилища он сливается, а не сохраняется, поэтому отношения В становятся гидратированными.
Мой вопрос: это правильно, или я могу сделать что-то еще, что выглядит не столь уж неэффективно иУжасно?
Чтобы было ясно, это имеет значение ТОЛЬКО при создании нового экземпляра A, и когда A находится в базе данных, это больше не проблема, потому что SimpleJpaRepository попадет в строку em.merge()
код.Также я пробовал разные аннотации CascadingType для отношений, но ни одна из них не является тем, что я хочу.Каскадирование - это сохранение состояния представления родительской сущности своих дочерних объектов своим дочерним элементам, но я хочу гидрировать дочерние сущности при создании нового экземпляра вместо того, чтобы совершать две поездки в базу данных.