z17
@z17
Java, PHP

Как добавить в БД (hibernate) элемент с внешним ключом без выборки для него объекта (по id)?

Скажем, есть два Entity, связанные между собой внешним ключом:
@Entity
@Table(name = "a")
public class AEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "name", nullable = false)
    private String name;
}

@Entity
@Table(name = "b")
public class BEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "a_id", nullable = false)
    private AEntity a;

    @Column(name = "name", nullable = false)
    private String name;
}


С фронтенда приходит запрос на insert новой записи B, понятное дело приходит в нём name и id элемента из A, а не сам элемент.

Как правильно сделать insert в БД, без заполнения поля BEntity.a, а по его id?
Ибо мне кажется что сначала выбирать нужную запись из таблицы a, чтобы потом вставить запись в таблицу b плохое решение.
  • Вопрос задан
  • 2728 просмотров
Решения вопроса 1
@guras256
"легального" способа я не знаю и вряд ли он есть. смысл Jpa в том, что ты работаешь в объектной модели, а не с sql запросами.
ты можешь присылать запрос с фронтенда в виде:
{
  "name": "some name",
  "a": {
    "id": 1
  }
}

и все будет хорошо работать

так же рекомендую сделать связь unidirectional, то есть поместить в A
@JsonIgnore
    @OneToMany(mappedBy = "a")
    private List<BEntity> bs;


в общем зависит от целей и необходимостей.
Если ты хочешь получать именно id, то ты просто используешь инструмент не по назначению, бери myBatis и пиши sql.

А если хочешь упороться, поставь transient поле в класс BEntity и перекладывай из него в AEntity -_- :
@Entity
@Table(name = "b")
public class BEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "a_id", nullable = false)
    @JsonIgnore
    private AEntity a;

    @Transient
    private Long aEntityId;

    @Column(name = "name", nullable = false)
    private String name;
}

// получаешь ответ с фронденда:
BEntity b = getBEntity();
// Создаешь AEntity
AEntity a = new AEntity();
// запихиваешь в нее нужный id из транзаент поля
a.setId(b.getAEntityId());
//засовываешь А в Б
b.setA(a);
// можно сохранять


но это вариант из разряда идиотизма

в общем спрашивай, если будут еще вопросы
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
jaxtr
@jaxtr
JavaEE/Spring-разработчик
Если у тебя нет каскадирования при сохранении для BEntity.a, то тебе достаточно будет инициализировать объект класса AEntity с указанным id, большего для связывания и не требуется.

Как вариант - в BEntity добавить поле aId, а BEntity.a сделать немодифицируемым:
@Column(nullable = false)
    private Long aId;

    @ManyToOne
    @JoinColumn(name = "a_id", nullable = false, insertable = false, updatable = false)
    private AEntity a;


В таком случае ты сможешь добавлять связь без заполнения поля. Связанная будет загружаться из БД при запросе, но не будет изменяться при сохранении, хотя это легко решается присвоением нового значения aId в сеттере a.

Но ИМХО, если это всё делается в контексте REST-сервисов, то объект класса AEntity в объекте класса BEntity должен быть полностью заполнен.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Bell Integrator Ульяновск
До 400 000 ₽
Bell Integrator Хабаровск
До 400 000 ₽
Bell Integrator Ижевск
До 400 000 ₽
23 апр. 2024, в 08:58
15000 руб./за проект
23 апр. 2024, в 08:42
60 руб./за проект