如何修复“ org.hibernate.PersistentObjectException:传递给持久对象的分离实体”

时间:2019-05-07 07:20:04

标签: java hibernate

我正在使用休眠orm填充数据库,并且不能传递多个对象。

我尝试在对象集合中使用级联MERGE,从oneToMany重组为manyToMany关系,但似乎问题与休眠无关。

我的实体很少:

Course.class

@Data
@Entity
@JsonIgnoreProperties(ignoreUnknown = true)
@Table(name = "course", catalog = "course_application")
public class Course {

    private static final int MAX_COURSES_PER_STUDENT = 3;
    private static final int MODULES_PER_COURSE = 10;
    private @Id
    @GeneratedValue
    Long id;
    private @Version
    int version;
    @NotNull
    private String name;
    @NotNull
    private int number;
    private float cost;
    private int modules;

    @ManyToMany
    @JoinTable(name = "course_listeners",
            joinColumns = @JoinColumn(name = "course_id"),
            inverseJoinColumns = @JoinColumn(name = "listener_id")
    )
    private List<Student> participators = new ArrayList<Student>();

    public Course() {
    }

    public Course(String name, int number, float cost) {
        this.name = name;
        this.number = number;
        this.cost = cost;
    }

    public void addParticipator(Student student) {
        participators.add(student);
    }

    public void addParticipator(Collection<Student> students) {
        participators.addAll(students);
    }

    @Override
    public String toString() {
        return name;
    }

    public String getName() {
        return name;
    }

    public void fill(Course course) {
        this.version++;
        this.name = course.getName();
        this.modules = course.getModules();
        this.number = course.getNumber();
    }
}

Student.class

@Data
@Entity
@Table(name = "students", catalog = "course_application")
@JsonIgnoreProperties(ignoreUnknown = true)
public class Student {

    @ManyToMany(targetEntity = CourseProgress.class, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinTable(name = "students_progress",
            joinColumns = @JoinColumn(name = "student_id"),
            inverseJoinColumns = @JoinColumn(name = "progress_id")
    )
    private final List<CourseProgress> progressList = new ArrayList<CourseProgress>();
    private @Id
    @GeneratedValue
    @Column(name = "student_id")
    Long id;
    private @Version
    int version;
    @NotNull
    private String name;
    private String address;
    private String phone;
    private Integer gradeBook;
    private float averageProgress;
    @Embedded
    private Advance advance;

    @ManyToMany(mappedBy = "participators")
    private List<Course> courses = new ArrayList<Course>();

    public Student() {

    }

    public Student(String name, String address, String phone, Integer gradeBook) {

        this.name = name;
        this.address = address;
        this.phone = phone;
        this.gradeBook = gradeBook;

    }

    @PostConstruct
    private void fillGradebookNumber() {
        gradeBook = gradeBook + Math.toIntExact(id);
    }

    @Override
    public String toString() {
        return getName();
    }

    public void addCourseProgress(CourseProgress progress) {
        progressList.add(progress);
    }

    public void fill(Student copy) {
        this.version++;
        this.name = copy.getName();
        this.phone = copy.getPhone();
        this.address = copy.getAddress();
        this.averageProgress = copy.getAverageProgress();
        this.gradeBook = copy.getGradeBook();
    }
}

CourseProgress.class

@Data
@Entity
@Table(name = "progress")
public class CourseProgress {

    @ElementCollection
    @CollectionTable(name = "marks", joinColumns = @JoinColumn(name = "progress_id"))
    @Column(name = "mark")
    private final List<Integer> marks = new ArrayList<Integer>();
    private @Id
    @GeneratedValue
    Long id;
    private @Version
    int version;
    private String name;
    @ManyToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
    private Course course;
    @Column(name = "average", columnDefinition = "Decimal(6,1)")
    private double average = 0.00;
    private int finalMark;

    public CourseProgress() {
    }

    public void addMark(Integer mark) {
        marks.add(mark);
        refreshAverage();
    }

    public void addMark(List<Integer> fewMarks) {
        marks.addAll(fewMarks);
        refreshAverage();
    }

    public void refreshAverage() {

        List onlyMarks = marks.stream().collect(Collectors.toList());
        IntSummaryStatistics stats = onlyMarks.stream().mapToInt((mark) -> (int) mark).summaryStatistics();
        average = stats.getAverage();

    }

    @Override
    public String toString() {
        return course.toString();
    }

}

我正在使用CommandLineRunner类填充数据库:

@Slf4j
@Configuration
public class LoadDatabase {

    @Bean
    CommandLineRunner populateDatabase(
            StudentRepository studentRepository,
            CourseRepository courseRepository,
            CourseProgressRepository progressRepository,
            ExchangeFileRepository exchangeFileRepository) {

        return args -> {

            log.info("Загружаем учащихся");
            Student studentIvanov = new Student(
                    "Иванов Иван Иванович",
                    "100200, Россия, г. Москва, ул. Вознесенская, 15 / ф",
                    "+7(978)111-22-33",
                    1000121);

            Student studentJackson = new Student(
                    "Бобби Джэксон Младший",
                    "100200, Россия, г. Москва, ул. Провансальная, 22 / 11",
                    "+7(978)111-22-33",
                    1000122);

            Student studentCarlson = new Student(
                    "Сэмми Смит Карлсон",
                    "100200, Россия, г. Москва, ул. Ленинская, 8а",
                    "+7(978)222-33-44",
                    1000123);

            Student studentHarris = new Student(
                    "Гарри Дэйл Харрисон",
                    "100200, Россия, г. Москва, ул. Оборонная, 127a / 1",
                    "+7(978)333-44-55",
                    1000124);

            Student studentGomez = new Student(
                    "Линдси Джэфферсон Гомез",
                    "100200, Россия, г. Москва, ул. Суздальская, 200 / 112",
                    "+7(978)555-66-77",
                    1000125);

            Student studentParker = new Student(
                    "Рэйчел Джэксон Паркер",
                    "100200, Россия, г. Москва, Флотский переулок, 1",
                    "+7(978)666-77-88",
                    1000126);

            log.info("Загружаем базовые курсы для студентов...");
            Course chemistryCourse = new Course("Химия для учеников старших классов и студентов", 202554110, 22000f);
            Course physicsCourse = new Course("Углубленный курс физики", 100292910, 25000f);
            Course programmingCourse = new Course("Общий кура подготовки программиста на языке Java Core.", 300235650, 30000f);

            CourseProgress ivanovJavaProgress = new CourseProgress();
            ivanovJavaProgress.setName("Курс программирования Java");
            ivanovJavaProgress.setCourse(programmingCourse);
            studentIvanov.addCourseProgress(ivanovJavaProgress);

            programmingCourse.addParticipator(studentIvanov);

            ivanovJavaProgress.addMark(Arrays.asList(5, 4, 4, 5, 4, 5));

            CourseProgress ivanovChemProgress = new CourseProgress();
            ivanovChemProgress.setName("Подготовительные курсы по химии");
            ivanovChemProgress.setCourse(chemistryCourse);
            studentIvanov.addCourseProgress(ivanovChemProgress);

            chemistryCourse.addParticipator(studentIvanov);

            ivanovChemProgress.addMark(Arrays.asList(2, 3, 2, 4, 5, 3));

            studentRepository.save(studentIvanov);

            CourseProgress jacksonJavaProgress = new CourseProgress();
            jacksonJavaProgress.setName("Курс программирования Java");
            jacksonJavaProgress.setCourse(programmingCourse);
            studentJackson.addCourseProgress(jacksonJavaProgress);

            programmingCourse.addParticipator(studentJackson);

            jacksonJavaProgress.addMark(Arrays.asList(5, 5, 5, 5, 4, 5));

            studentRepository.save(studentJackson);

            log.info("Загружаем тестовый экспортный фаайл" + exchangeFileRepository.save(
                    new ExchangeFile("D:\\export_json_31-03-2019_20_12_58.json", Long.valueOf(1846))));

            studentRepository.save(studentCarlson);
            studentRepository.save(studentHarris);
            studentRepository.save(studentGomez);
            studentRepository.save(studentParker);

        };
    }

}
studentRepository.save(studentIvanov); 

效果很好,可以正确填充,但是下一个持久对象

studentRepository.save(studentJackson);

异常失败

我希望每次使用orm保存对象时,代码实现都能正常工作。

1 个答案:

答案 0 :(得分:0)

尝试在保存学生实体的类或方法级别添加@Transactional注释。