问题
How to stop hibernate to do select before insert in child table in many to one mapping?
I have a student table :
@Entity
@Table
@NoArgsConstructor
@AllArgsConstructor
@Builder
@Data
@IdClass(StudentId.class)
public class Student implements Persistable<StudentId> {
@Id
private String studentUuid;
@Id
private String studentName;
@Column
private String sex;
public Student(String studentUuid,String studentName){
this.studentUuid = studentUuid;
this.studentName = studentName;
}
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns({
@JoinColumn(
name = "classUuid",referencedColumnName = "classUuid"),
@JoinColumn(
name = "className",referencedColumnName = "className")
})
private Class className;
@Override
public StudentId getId() {
return new StudentId().builder().studentName(studentName).studentUuid(studentUuid).build();
}
@Override
public boolean isNew() {
return true;
}
}
I have a Class table:
@Entity
@Table
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
@IdClass(ClassId.class)
public class Class implements Persistable<ClassId> {
@Id
private String classUuid;
@Id
private String className;
@Column
private String classRoomNo;
@Column
private String classSize;
@OneToMany(mappedBy = "className",cascade = CascadeType.ALL,fetch = FetchType.LAZY)
private List<Student> studentList;
@Override
public ClassId getId() {
return new ClassId().builder().className(className).classUuid(classUuid).build();
}
@Override
public boolean isNew() {
return true;
}
}
Whenever i do studentRepo.save(studentEntity) it always do select from parent class i.e. Class table then if the data exists in the parent table then it do insert in child table i.e. student. Cannot it happen in a single network call rather then hitting two calls first select from parent then insert.
回答1:
If I understand you correctly, you want to save or use existing class (if exists) within the same call. The performance-best way to do this is to insert and handle exception in case of failure. However, the best practice is to make separate requests to the database: first, to check if the class exists; second, to insert it (if needed), and then insert a student. My advice to you would be to create a separate @Transactional
service method, that would execute that operation for you. Just like this:
private final ClassRepository classRepository;
@Transactional
public Student createStudent(Object studentDto) {
Class cls = classRepository.findByClassUuid(studentDto.getStudentClass().getClassUuid())
// in case it returns optional
.orElse(classRepository.save(Class.builder()
.className("..")
.classSize("..")
//...
.build()));
Student studentEntity = new Student();
// setters skipped
return studentRepo.save(studentEntity);
}
Just make sure you add the package name to your class
class, otherwise, compiler will think of java.lang.Class.
来源:https://stackoverflow.com/questions/56756965/how-to-stop-hibernate-to-do-select-before-insert-in-child-table-in-manytoone-ma