Проблема отношения многих ко многим с использованием репозитория Crud и Spring Boot - PullRequest
0 голосов
/ 23 января 2020

Я создаю приложение Spring Boot с использованием Crud Repository. У меня проблема с созданием отношений «многие ко многим». Проблема возникает, когда я хочу добавить новую запись в сущность Learning, которая должна принадлежать существующей записи в сущности Student. Ошибка выглядит следующим образом:

Ошибка обработки запроса; вложенным исключением является org.springframework.dao.InvalidDataAccessApiUsageException: отдельная сущность передана для сохранения: pl.anitakowalczyk.surwejlansapi.dao.entity.Student; Вложенное исключение: org.hibernate.PersistentObjectException: отдельная сущность передана для сохранения: pl.anitakowalczyk.surwejlansapi.dao.entity.Student

Это код, который представляет сохранение этой новой записи в базе данных:

Course course = courseRepository.findById(courseId).get();
Student student = currentUser;
Integer percent = points * 100 / allPoints;
Learning learning = new Learning(course, percent);
learning.setStudent(student);
learningRepository.save(learning);

Что я делаю не так?

Вот схема базы данных: ERD

Студент. java

package pl.anitakowalczyk.surwejlansapi.dao.entity;

import lombok.Data;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Data
@Entity
public class Student {
    private Integer studentid;
    private String imie;
    private String nazwisko;
    private String login;
    private String password;
    private List<Learning> learnings = new ArrayList<Learning>();

    public Student() {
    }

    public Student(String imie, String nazwisko, String login, String password) {
        this.imie = imie;
        this.nazwisko = nazwisko;
        this.login = login;
        this.password = password;
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    public Integer getStudentid() {
        return studentid;
    }

    public void setStudentid(Integer studentid) {
        this.studentid = studentid;
    }

    public String getImie() {
        return imie;
    }

    public void setImie(String imie) {
        this.imie = imie;
    }

    public String getNazwisko() {
        return nazwisko;
    }

    public void setNazwisko(String nazwisko) {
        this.nazwisko = nazwisko;
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @OneToMany(mappedBy = "student", cascade = CascadeType.ALL)
    public List<Learning> getLearnings() {
        return learnings;
    }

    public void setLearnings(List<Learning> learnings) {
        this.learnings = learnings;
    }

}

Обучение. java

package pl.anitakowalczyk.surwejlansapi.dao.entity;

import lombok.Data;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;

@Data
@Entity
public class Learning implements Serializable {

    private Integer learningid;
    private Student student;
    private Course course;
    private int progress;
    private Date date;

    public Learning() {
    }

    public Learning(Student student, Course course, int progress) {
        this.student = student;
        this.course = course;
        this.progress = progress;
        this.date = new Date();
    }

    public Learning(Course course, int progress) {
        this.course = course;
        this.progress = progress;
        this.date = new Date();
    }

    @Id
    @GeneratedValue
    @Column(name = "learningid")
    public Integer getLearningid() {
        return learningid;
    }

    public void setLearningid(Integer learningid) {
        this.learningid = learningid;
    }

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "studentid")
    public Student getStudent() {
        return student;
    }

    public void setStudent(Student student) {
        this.student = student;
    }

    @ManyToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "courseid")
    public Course getCourse() {
        return course;
    }

    public void setCourse(Course course) {
        this.course = course;
    }

    public int getProgress() {
        return progress;
    }

    public void setProgress(int progress) {
        this.progress = progress;
    }


    @Column(name = "date")
    public Date getDate() {
        return date;
    }

    public void setDate(Date date) {
        this.date = date;
    }



}

проверка. jsp

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<!DOCTYPE html >
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Aplikacja FISZKI</title>
    <link rel="stylesheet" href="https://unpkg.com/swiper/css/swiper.css">
    <link rel="stylesheet" href="https://unpkg.com/swiper/css/swiper.min.css">
</head>
<body>
<div class="container">
    <div class="header">Kurs <span style="font-weight: 600">${courseName}</span></div>
    <div class="words">
        <c:choose>
            <c:when test="${empty words}">
                <div class="empty">
                    Ten kurs nie posiada jeszcze żadnych słów do nauki.
                </div>
            </c:when>
            <c:otherwise>
                <div class="swiper-container">
                    <div class="swiper-wrapper">
                        <c:forEach items="${words}" var="word">
                            <div class="swiper-slide">
                                <div>
                                    <fieldset class="word">
                                        <legend>Polskie znaczenie</legend>
                                        <div >${word.polish}</div>
                                    </fieldset>
                                </div>
                                <div>
                                    <fieldset id="eng${word.wordid}field" class="word">
                                        <legend>Angielskie znaczenie</legend>
                                        <textarea  id="eng${word.wordid}" rows="1" cols="20"></textarea>
                                        <button onclick="checkEnglish('eng${word.wordid}', '${word.english}')" style="margin: 0px;" id="sprawdz" type="button">Sprawdź</button>
                                    </fieldset>
                                </div>
                            </div>
                        </c:forEach>
                    </div>
                    <div class="swiper-pagination"></div>
                    <div class="swiper-button-next"></div>
                    <div class="swiper-button-prev"></div>
                </div>
            </c:otherwise>
        </c:choose>

        <div class="buttonlist">

            <div class="zakoncz">
                <form id="form" method="post" action="">
                    <button id="zakoncz" type="button" onclick="countPoints(${fn:length(words)}, ${courseId})">Zakończ</button>
                </form>
            </div>
            <div class="buttony">
                <a href="http://localhost:8090/fiszki/login?logout=1">
                    <button type="submit" name="submit" value="buttonname" id="wyloguj">Wyloguj</button>
                </a>
            </div>
        </div>
    </div>
</div>
<script src="https://unpkg.com/swiper/js/swiper.min.js"></script>

<script>
    var swiper = new Swiper('.swiper-container', {
        pagination: {
            el: '.swiper-pagination',
            type: 'progressbar',
        },
        navigation: {
            nextEl: '.swiper-button-next',
            prevEl: '.swiper-button-prev',
        }
    });


    function checkEnglish(engId, englishMeaning) {
        if(document.getElementById(engId).value === englishMeaning) {
            document.getElementById(engId + "field").style.border = "1px solid #00b300";
            document.getElementById(engId + "field").setAttribute("point", "1");
        } else {
            document.getElementById(engId + "field").style.border = "1px solid #cc0000";
        }
    };

    function countPoints(totalPoints, courseID) {
        if(totalPoints === 0 ) {
            window.location = "http://localhost:8090/fiszki/courses";
        } else {
        var points = 0;
        if(document.querySelectorAll('[point]')) {
            document.querySelectorAll('[point]').forEach(function(item){
                points++;
            })
        }
        document.querySelector("form").action = "/fiszki/finishTest/" + courseID + "/" + points + "/" + totalPoints;
        document.forms["form"].submit();
        return points;
        }
    };

</script>
</body>
</html>
...