#java #spring #hibernate #jpa #bidirectional
#java #гибернация #остальное #джакарта-ee #http-post
Вопрос:
У меня есть отношения «один ко многим» между классом person и классом car. У человека может быть много автомобилей и наоборот. Я использую restful API для публикации данных. Мои аннотации и служба получения работают нормально, но моя служба post выдает » java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL" error
всякий раз, когда я пытаюсь вставить новые данные. Дочерняя таблица foreign key
вставляется как null
.
Вот часть моего кода.
Person.java
private List<Car> cars = new ArrayList<Car>();
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="person")
@JsonManagedReference
public List<Car> getCars() {
return cars;
}
Car.java
private Person person;
@ManyToOne
@JoinColumn(name = "PERSON_ID", nullable = false, updatable = true, insertable = true)
@JsonBackReference
public Person getPerson() {
return person;
}
Мой класс обслуживания:
@POST
@Path("/PersonRegistration")
@Consumes(MediaType.APPLICATION_JSON)
public Response postPersonCars(Person person) throws Exception{
Session session = null;
ObjectMapper mapper = new ObjectMapper();
//Person per = new Person();
//Car cars = new Car();
try{
session = HibernateUtil.getSessionFactory().openSession();
session.beginTransaction();
//per.setCars(person.getCars());
session.save(person);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
throw e;
}finally{
if(null != session){
session.close();
}
}
return Response.status(201).entity(mapper.writeValueAsString(person)).build();
}
Ответ №1:
Эта аннотация:
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY, mappedBy="person")
имеет два последствия:
mappedBy
подразумевает, чтоCar
это сторона-владелец отношения. Это означает, что всякий раз, когда вы хотите установить связь междуCar
иPerson
, вам нужно сделать это, установивCar.person
для свойства соответствующее значение. Изменения вPerson.cars
режиме гибернации будут проигнорированы.cascade=CascadeType.ALL
означает, что всякий раз, когда вы сохраняете aPerson
, Hibernate также будет вызывать операцию сохранения для всех объектов, содержащихся вPerson.cars
Результат: вы вызываете Session.save()
группу Car
объектов, для которых Car.person
свойство не установлено должным образом.
Решение: либо измените сторону владельца отношения (имейте в виду, что вам также понадобится @JoinColumn
on Person.cars
, если вы не хотите, чтобы создавалась дополнительная таблица базы данных), либо выполните цикл Person.cars
и Car.person
правильно установите свойство в каждом из них.
cascade=CascadeType.ALL
предполагает, что первое решение лучше подходит для вашего варианта использования.
Комментарии:
1. Спасибо crizzis за ваш ответ. Я вызываю session.save для объекта person, у которого есть ArrayList автомобилей. Итак, я должен повторить json и установить cars на Person?
2. Вы должны перебирать
person.getCars()
и вызыватьcar.setPerson(person)
каждыйcar
3. Итак, для удаления мне тоже нужно сделать то же самое? перебрать person.getCars и удалить car, а затем person? Это хороший подход или я что-то упускаю?
4. Нет. В этом случае должно быть достаточно удаления person, поскольку
CascadeType.ALL
будет каскадное удаление