Spring boot JPA определяет каскадный порядок объектов

#java #spring-boot #jpa

#java #spring-boot #jpa

Вопрос:

У меня есть 3 класса объектов, определенных как показано ниже:

 @Entity
public class Rimorchio {

@Id
@GeneratedValue
private long idrimorchio;

@Column(unique = true)
private String targa;

// .... Getters and Setters

}


@Entity
public class Atk {

@Id
@GeneratedValue
private long idatk;

@Column(unique = true)
private String codice;

@Column(unique = true)
private String targa;

@OneToOne
private Rimorchio suggerito;

// .... Getters and Setters

}


@Entity
public class Trasportatore {

@Id
@GeneratedValue
private long idtrasportatore;

@Column(unique = true)
private String nometrasportatore;

@OneToMany(cascade = {CascadeType.PERSIST})
private List<Rimorchio> listarimorchi;

@OneToMany(cascade = {CascadeType.PERSIST})
private List<Atk> listaatk;

@OneToMany(cascade = {CascadeType.PERSIST})
private List<Autista> listaautisti;

// .... Getters and Setters

}
  

Когда я пытаюсь сохранить в базе данных класс Trasportatore, я получаю следующую ошибку:

    org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - 
   save the transient instance before flushing : 
   com.petroli.gestionefasipetroli.entities.Atk.suggerito -> 
   com.petroli.gestionefasipetroli.entities.Rimorchio
  

Итак, я должен сохранить экземпляр Rimorchio перед экземпляром Atk.
У меня есть структура с репозиторием, который расширяет JpaRepository, и службой, которая просто вызывает

  repository.saveAndFlush(trasportatore);
  

Как я могу определить порядок вставки в БД, чтобы избежать этой проблемы? Или есть другое решение (возможно, избегающее каскадных операций вручную) для достижения этой цели?

Комментарии:

1. Есть ли какая-то причина, по которой у вас нет каскадного сохранения, установленного для отношений OneToOne?

2. Да, потому что Rimorchio в Atk не является обязательным. Если я вставлю туда каскадирование, все будет работать хорошо (я должен удалить каскадирование из Trasportatore). Проблема в том, что может существовать Atk без Rimorchio!

3. Каскадное сохранение не останавливает и не влияет на это — оно не имеет ничего общего с обязательными или необязательными ссылками, только то, что JPA должен делать, если вы вызываете persist, и он находит ссылку на неуправляемый объект. Если у вас есть Atk, которые существуют без экземпляров Rimorchio, для них требуется вызов persist, но для тех, которые уже сохраняются, это недопустимо.

4. Да, но если я добавлю каскадное сохранение в OneToOne, у меня будет исключение SQLIntegrityConstraintViolationException: дублирующая запись. Если я использую каскадное сохранение только в отношении OneToOne, я не могу вставить Rimorchio во вставку Trasportatore.

5. отличаются ли эти экземпляры? Вам нужно исправить вашу модель так, чтобы в X-> Y-> Z-> X’, X== X’. X не будет иметь установленного идентификатора до тех пор, пока не сохранится (или даже после фиксации или сброса), поэтому JPA не может знать, что они представляют одни и те же данные. Если строки ‘targa’ предназначены для уникальной идентификации строки экземпляра, вы можете использовать их в качестве идентификатора, и это может помочь вам справиться с повторным использованием экземпляров, которые должны быть одинаковыми в этом графе объектов.