如何从jpa中的join表中删除数据

vcudknz3  于 2021-07-13  发布在  Java
关注(0)|答案(4)|浏览(326)

我试图创建一个图书馆管理系统,为此我创建了两个实体 Student 以及 Books 两者都使用 @ManytoMany 因此,我使用了另一个联接表,当学生从图书馆发出图书时,我存储图书id和学生id,但当学生返回图书时,该行包含联接表中的两个id,应该删除,但当我尝试删除联接表中的所有数据或我的学生和图书时删除这里是我的代码,请告诉我我在这里做错了什么,什么应该是最好的做法
学生实体

package com.Library.LibraryManagement.Entity;

import java.sql.Timestamp;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name="student")
public class Student {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private Integer id;
    @Column(name="first_name")
    private String firstName;
    @Column(name="last_name")
    private String lastName;
    @Column(name="student_email")
    private String email;
    @Column(name="student_course")
    private Integer course;
    @Column(name="date_of_birth")
    private String dateOfBirth;
    @Column(name="student_status")
    private Integer status;
    @Column(name="added_at")
    private Timestamp addedAt;

    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinTable(name="student_books",
                joinColumns=@JoinColumn(name = "student_id"),
                inverseJoinColumns = @JoinColumn(name="books_id"))
    private List<Books> books;

    public Student() {
    //Empty Constructor 
    }

    public Student(String firstName, String lastName, String email, Integer course,String dateOfBirth,Integer status,Timestamp addedAt) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
        this.course = course;
        this.dateOfBirth = dateOfBirth;
        this.status = status;
        this.addedAt = addedAt;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public Integer getCourse() {
        return course;
    }

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

    public String getDateOfBirth() {
        return dateOfBirth;
    }

    public void setDateOfBirth(String dateOfBirth) {
        this.dateOfBirth = dateOfBirth;
    }

    public Integer getStatus() {
        return status;
    }

    public void setStatus(Integer status) {
        this.status = status;
    }

    public Timestamp getAddedAt() {
        return addedAt;
    }

    public void setAddedAt(Timestamp addedAt) {
        this.addedAt = addedAt;
    }

    public List<Books> getBooks() {
        return books;
    }

    public void setBooks(List<Books> books) {
        this.books = books;
    }

    public void removeBook(Books boo) {
        this.books.remove(boo);
        boo.getStudents().remove(this);
    }

    @Override
    public String toString() {
        return "{\"id\":\"" + id + "\", \"firstName\":\"" + firstName + "\", \"lastName\":\"" + lastName
                + "\", \"email\":\"" + email + "\", \"course\":\"" + course + "\", \"dateOfBirth\":\"" + dateOfBirth
                + "\", \"status\":\"" + status + "\", \"addedAt\":\"" + addedAt + "\"}";
    }

}

图书实体

package com.Library.LibraryManagement.Entity;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

@Entity
@Table(name="books")
public class Books {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="id")
    private Integer id;
    @Column(name="book_name")
    private String bookName;
    @Column(name="book_publisher")
    private String bookPublisherName;
    @Column(name="book_description")
    private String bookDescription;
    @Column(name="book_language")
    private String bookLanguage;
    @Column(name="book_in_stock")
    private Integer bookInStock;
    @Column(name="added_at")
    private Timestamp addedAt;
    @Column(name="deleted")
    private Integer deleted;

    @ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinTable(name="student_books",
                joinColumns=@JoinColumn(name = "books_id"),
                inverseJoinColumns = @JoinColumn(name="student_id"))
    private List<Student> students;

    public Books() {

    }

    public Books(String bookName, String bookPublisherName, String bookDescription, String bookLanguage,Timestamp addedAt,
            Integer bookInStock,Integer deleted) {
        this.bookName = bookName;
        this.bookPublisherName = bookPublisherName;
        this.bookDescription = bookDescription;
        this.bookLanguage = bookLanguage;
        this.bookInStock = bookInStock;
        this.addedAt =addedAt;
        this.deleted = deleted;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getBookName() {
        return bookName;
    }

    public void setBookName(String bookName) {
        this.bookName = bookName;
    }

    public String getBookPublisherName() {
        return bookPublisherName;
    }

    public void setBookPublisherName(String bookPublisherName) {
        this.bookPublisherName = bookPublisherName;
    }

    public String getBookDescription() {
        return bookDescription;
    }

    public void setBookDescription(String bookDescription) {
        this.bookDescription = bookDescription;
    }

    public String getBookLanguage() {
        return bookLanguage;
    }

    public void setBookLanguage(String bookLanguage) {
        this.bookLanguage = bookLanguage;
    }

    public Integer getBookInStock() {
        return bookInStock;
    }

    public void setBookInStock(Integer bookInStock) {
        this.bookInStock = bookInStock;
    }

    public Timestamp getAddedAt() {
        return addedAt;
    }

    public void setAddedAt(Timestamp addedAt) {
        this.addedAt = addedAt;
    }

    public Integer getDeleted() {
        return deleted;
    }

    public void setDeleted(Integer deleted) {
        this.deleted = deleted;
    }

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    public void removeBook(Student stu) {
        this.students.remove(stu);
        stu.getBooks().remove(this);
    }

    @Override
    public String toString() {
        return "{\"id\":\"" + id + "\", \"bookName\":\"" + bookName + "\", \"bookPublisherName\":\"" + bookPublisherName
                + "\", \"bookDescription\":\"" + bookDescription + "\", \"bookLanguage\":\"" + bookLanguage
                + "\", \"bookInStock\":\"" + bookInStock + "\", \"addedAt\":\"" + addedAt + "\", \"deleted\":\""
                + deleted + "\"}";
    }

    //Convience MEthods to help with adding the student
    public void addStudent(Student theStudent) {
        if(students ==null) {
            students = new ArrayList<>();
        }
        students.add(theStudent);
    }
}

用于从联接表中重新生成数据的方法

@Override
    @Transactional
    public void returnBok(Student student, Books book) {
        try {
            if(student !=null && book !=null) {
//              Student stu = book.getStudents(.); 
//                  book.removeBook(student);
                for(Books books : student.getBooks()) {
                    student.removeBook(book);
                }
                entityManage.remove(student);
            }
        }catch(Exception e) {
            e.printStackTrace();
        }
    }
rdrgkggo

rdrgkggo1#

那是因为你在用 entityManager.remove . 由于层叠,该命令将删除一个学生及其所有相关书籍。
如果您只想从关联中删除一本书,则 returnBook 方法应该如下所示:

@Transactional
public void returnBook(Student student, Books book) {
    try {
         if(student !=null && book !=null) {
             Student entityStudent = entityManager.getReference( Student.class, student.getId())
             Book entityBook = entityManager.getReference( Book.class, book.getId())
             entityStudent.removeBook(entityBook);
        }
    }
...
}

在提交或刷新会话期间,更改将传播到数据库。
注意,我添加了 getReference() 因为我不知道 student 以及 book 是托管实体。如果是的话,就没必要用了 getReference() .
假设这是什么 removeBook 看起来像:

public void removeBook(Book book) {
        this.books.remove( book );
        book.getStudents().remove( this );
    }

正如hibernate orm文档中所描述的那样,更新关联的两边是很重要的。
此外,协会在其中一个实体上的Map应为:

@ManyToMany(mappedBy = "...")

你应该决定哪个实体拥有这个协会。
顺便问一下,您确定要实现的Map不是hibernate orm文档中描述的Map吗 Example 172. Bidirectional many-to-many with link entity ?

8ulbf1ek

8ulbf1ek2#

您的多对多关系Map不正确。
文件上说:
每一个多对多关联都有两个方面,拥有方和非拥有方,或相反。联接表是在拥有方指定的。如果关联是双向的,那么任何一方都可以被指定为拥有方。如果关系是双向的,则非拥有方必须使用 mappedBy 元素 ManyToMany 注解以指定拥有方的关系字段或属性。
(重点补充)。
您的注解Map关系就像双方都拥有它一样,这是不正确的。
一旦选择了拥有方,就可以通过更新拥有方上的关系字段并保存修改后的拥有实体来修改关系。你有其他的答案来说明怎么做。您可能还希望对非拥有方进行相应的更改,或者刷新非拥有方实体以使该方的关系字段同步。

brvekthn

brvekthn3#

一定会的

student.getBooks().remove(book);

entityManger.save(student)
r9f1avp5

r9f1avp54#

不要使用returnbook方法,请使用以下方法:

@Override
    @Transactional
    public void returnBok(Student student, Books book) {
        try {
            if (student != null && book != null) {
                student.getBooks().removeIf(books -> {
                    return Objects.equals(book.getId(), books.getId());
                });
                entityManager.save(student);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

因为在上述方法中,您正在删除整个student对象 entityManage.remove(student); ,这就是你的学生被删除的原因 cascade = CascadeType.ALL 在Map中,书本对象也会被删除。
还有一个建议。而不是填充getter、setter和构造函数。
使用lombok插件:
https://projectlombok.org/setup/maven
https://www.baeldung.com/lombok-ide

相关问题