【问题标题】:How to add data to Many to Many association with extra column using JPA, Hibernate如何使用 JPA、Hibernate 将数据添加到与额外列的多对多关联
【发布时间】:2020-08-17 12:49:30
【问题描述】:

我有一个 User 表和一个 Book 表要连接。

所以我创建了第三个表 Borrow,它具有外键 (book_id, user_id) 和 takenDatebroughtDate 字段。

User.java

@Entity
@Table(name = "Users")
public class User {


    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String name;
    private String surname;
    private String username;
    private String email;
    private String password;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Borrow> borrow;
    ....

Book.java

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

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    private String title;
    private String ISBN;
    private String author;
    private String issuer;
    private Integer dateOfIssue;
    private Boolean IsRented;


    @OneToMany(mappedBy = "book", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Borrow> borrow;
    .....

Borrow.java

@Entity
@Table(name = "Borrows")
@IdClass(BorrowId.class)
public class Borrow {

    private Date takenDate;
    private Date broughtDate;

    //lazy means it will get details of book
    // only if we call GET method

    @Id
    @JsonIgnore
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "book_id", referencedColumnName = "id")
    private Book book;


    @Id
    @JsonIgnore
    @ManyToOne
    @JoinColumn(name = "user_id", referencedColumnName = "id")
    private User user;
    ....

BorowId.java

public class BorrowId implements Serializable {

    private int book;
    private int user;

    // getters/setters and most importantly equals() and hashCode()

    public int getBook() {
        return book;
    }

    public void setBook(int book) {
        this.book = book;
    }

    public int getUser() {
        return user;
    }

    public void setUser(int user) {
        this.user = user;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof BorrowId)) return false;
        BorrowId borrowId = (BorrowId) o;
        return getBook() == borrowId.getBook() &&
                getUser() == borrowId.getUser();
    }

    @Override
    public int hashCode() {
        return Objects.hash(getBook(), getUser());
    }
}

MySql 数据库设计如下:

我正在尝试将数据添加到 Borrow 表中,如下所示:

已编辑

@Transactional
    @PostMapping("/addUser/{id}/borrow")
    public ResponseEntity<Object> createItem(@PathVariable int id, @RequestBody Borrow borrow, @RequestBody Book book){
        Optional<User> userOptional = userRepository.findById(id);
        Optional<Book> bookOptional = bookRepository.findById(book.getId());


        if(!userOptional.isPresent()){
            throw new UserNotFoundException("id-" + id);
        }

        User user = userOptional.get();
        borrow.setUser(user);
        borrow.setBook(book);

        borrowRepository.save(borrow);

        URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{id}").buildAndExpand(borrow.getId()).toUri();

                return ResponseEntity.created(location).build();
    }

我还没有完成它,因为我不确定如何:/ 任何提示表示赞赏!

【问题讨论】:

    标签: java spring-boot hibernate jpa


    【解决方案1】:

    你快到了。你只需要记住两件事:

    1)您还必须通过存储库获取Book(目前您只获取User

    2) 这三个操作必须在同一个事务上下文中:

       fetching of `User`, fetching of `Book` and save `Borrow` entity.
    

    提示:您可以将所有这些放在 Service 中并将其标记为 @Transactional 或将 @Post 方法标记为 @Transactional。我会建议第一个选项,但这取决于你。

    编辑:

    Optional<Book> bookOptional = bookRepository.findById(book.getId());
    

    此外,这里使用 @EmbeddedId 而不是 @IdClass 似乎就足够了,因为 id 是实际的外国实体:

    @Embeddable
    public class BorrowId{
       
        @ManyToOne(fetch = FetchType.LAZY)
        @JoinColumn(name = "book_id", referencedColumnName = "id")
        private Book book;
    
    
        @ManyToOne
        @JoinColumn(name = "user_id", referencedColumnName = "id")
        private User user;
    }
    

    然后在 Borrow 类中:

    @Entity class Borrow{
      @EmbeddedId BorrwId borrowId;
      ...
    }
    

    在 Post 方法中:

        BorrowId borrowId = new BorrowId();
        borrowId.setUser(user);
        borrowId.setBook(book);
    
        borrow.setBorrowId(borrowId);
    
        borrowRepository.save(borrow);
    

    【讨论】:

    • 感谢您的回答。我根据我的理解(因为我是初学者)尝试了一些编辑代码。你能检查一下它在上面的代码中吗?
    • 谢谢,是的,我忘记了图书 ID。我再次更新了代码。我添加了位置并返回了 ResponseEntity。但是buildAndExpand(borrow.getId()) 用红色下划线表示Cannot resolve method 'getId' in 'Borrow' 因为借用我没有id 我的id 是两个外键。我应该怎么办?我应该将 id 作为自动增量添加到借用实体吗?
    • 但我想我不能再添加一个 ID,因为我已经有了它:/
    • 你可以通过 isbn 找到这本书......必须有一些独特的属性来自请求......
    • 嗯,我想我必须从借表而不是书上得到它
    猜你喜欢
    • 2017-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-16
    • 2017-08-24
    • 1970-01-01
    • 2011-07-04
    相关资源
    最近更新 更多