如何在插入@ManyToOne映射的子表之前停止休眠做选择?

时间:2019-06-25 15:01:11

标签: hibernate spring-boot jpa spring-data-jpa jpa-2.0

在多对一映射中插入子表之前如何停止休眠选择?

我有一个学生桌:

    @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;
        }
    }

我有一个班级表:

@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;
    }
}

每当我执行studentRepo.save(studentEntity)时,它总是从父类中进行选择,即类表,然后如果该数据存在于父表中,那么它将插入子表即学生。 不能在单个网络通话中发生,而是先打两个通话,然后先从父级选择,然后插入。

1 个答案:

答案 0 :(得分:0)

如果我对您的理解正确,那么您想在同一调用中保存或使用现有的类(如果存在)。执行此操作的最佳性能方法是在发生故障的情况下插入并处理异常。但是,最佳实践是对数据库进行单独的请求:首先,检查该类是否存在;第二,插入它(如果需要),然后插入一个学生。我对您的建议是创建一个单独的@Transactional服务方法,该方法将为您执行该操作。就是这样:

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);
}

只需确保将包名称添加到class类中,否则,编译器会想到java.lang.Class。