Hibernate ManyToOne сохранить. Сохранить родителей без детей. Но ребенка следует искать по определенному признаку - PullRequest
0 голосов
/ 05 февраля 2020

Я просто хочу сохранить родительский объект с подходящим внешним ключом для отношения. Для этого отношения я просто хочу дать определенный атрибут, он должен быть найден, получить идентификатор и установить идентификатор для родителя в качестве внешнего ключа. Ниже приведен пример.

Мои сущности:

PEOPLE(
  PEOPLE_ID number(19) PRIMARY KEY, 
  NAME varchar(255), 
  TYPE_ID number(19), 
  FOREIGN KEY (TYPE_ID) REFERENCES TYPE(TYPE_ID)
);
TYPE(
  TYPE_ID number(19) PRIMARY KEY, 
  NAME varchar(255) unique
);

ЛЮДИ связаны с ТИПОМ. Так что у многих людей может быть один ТИП, а у одного ТИПА может быть много ЛЮДЕЙ. Но меня интересует только направление ЛЮДИ к ТИПУ.

Таблица типов заполнена некоторыми значениями. Нет необходимости вставлять или обновлять данные. TYPE-Values ​​1, Student 2, Teacher ...

PEOPLE Entity:

@Entity
@Table(name = "PEOPLE")
public class PeopleDBO {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name= "PEOPLE_ID")
    private Long id;

    private String name;

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name= "TYPE_ID", referencedColumnName="TYPE_ID")
    private TypeDBO type;

    //getters and setters
}

TYPE Entity:

@Entity
@Data
@Table(name = "TYPE")
public class TypeDBO {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "TYPE_ID")
    private Long id;

    private String name;

    //getters and setters
}

Я использую стандартные репозитории JPA для сохранить сущности

Код:

final TypeDBO type = new TypeDBO();
type.setName("Teacher");

final PeopleDBO people = new PeopleDBO();
people.setName("George");
people.setType(type);

peopleRepository.save(people);

В приведенном выше коде я пытаюсь просто установить TYPE.NAME и hibernate должен сам искать исправленную запись, найти правильный идентификатор и peopleRepository. просто сохраните родителя. Я думаю, у меня есть две проблемы здесь. Прежде всего, я получаю это сообщение об ошибке, потому что TYPE.NAME является уникальным, и hibernate пытается вставить уже существующее имя:

org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint ["PUBLIC.PRIMARY_KEY_9 ON PUBLIC.TYPE(TYPE_ID) VALUES 2"; SQL statement:
insert into TYPE (NAME, TYPE_ID) values (?, ?) [23505-199]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement

И вторая проблема будет (как только будет решена первая), что гибернация Не знаю, какой атрибут должен быть найден.

ОК. Я мог бы написать следующий код и сначала прочитать ТИП, но я хочу избежать этого. Потому что это просто образец. В моем реальном проекте 7 таких ТИПОВ, и я думаю, что будет действительно неэффективно сначала прочитать все типы, чтобы сохранить одного родителя.

Я хочу избежать этого кода:

final TypeDBO type typeRepository.findByName("Teacher");

final PeopleDBO people = new PeopleDBO();
people.setName("George");
people.setType(type);

peopleRepository.save(people);

Делать У вас есть идея, как ее решить, или какие-то ключевые слова, чтобы я мог провести более подробное исследование?

Заранее большое спасибо! D.

Ответы [ 2 ]

0 голосов
/ 05 февраля 2020

Как вы сказали, тип сущности будет заполнен предопределенными значениями. Поэтому при сохранении сущности Popele вам необходимо отобразить существующую запись типа на основе значения типа

Но в приведенном ниже коде вы всегда пытаетесь создать новую запись типа. Не смотря на это, вам нужно получить запись типа из БД на основе имени и того объекта, который вам нужно отобразить при сохранении записи Poeple.

final TypeDBO type = new TypeDBO (); type.setName ("Teacher");

аналогично приведенному ниже, вы можете получить запись TypeDBO type = featchByName ("Teacher")

, а затем установить это значение при сохранении записи о людях. people.setType (тип);

0 голосов
/ 05 февраля 2020

То, что вы хотите sh, на самом деле невозможно с JPA, и я бы посоветовал вам, если вы хотите сохранить этот стиль программирования, делать это скорее с JDB C, чем с JPA, потому что этот стиль не является тем, что подразумевается под JPA но это очень легко выполнимо в JDB C. JPA хочет, чтобы вы думали в сущностях, а не в столбцах базы данных (это то, что JPA подразумевает под «абстракцией»), поэтому ваш последний пример - именно то, как JPA предназначен для использования его создателями.

Но, конечно, вы Вы можете заменить ваши отношения @ManyToOne на базовый столбец c String, который представляет ваш внешний ключ, но затем вы должны сами установить sh отношения между объектами во время выполнения, т. е. при загрузке PeopleDBO, вам потребуется загрузите соответствующий TypeDBO самостоятельно, используя второй запрос, а затем, возможно, настройку объекта PeopleDBO.

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