简体   繁体   中英

Spring + Hibernate: creating child mapped to fictional parent in OneToMany relationship

I have these 2 entities:

@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
@Getter
@Entity
@Table(name = "BOOKS")
public class Book {

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private long id;

    @NotNull
    @Column(name = "TITLE")
    private String title;

    @NotNull
    @Column(name = "AUTHOR")
    private String author;

    @NotNull
    @Column(name = "PUBLICATION_YEAR")
    private int publicationYear;

    @JsonBackReference
    @EqualsAndHashCode.Exclude
    @OneToMany(
            targetEntity = BookCopy.class,
            mappedBy = "book",
            cascade = CascadeType.ALL,
//            orphanRemoval = true,
            fetch = FetchType.LAZY
    )
    private List<BookCopy> bookCopies = new ArrayList<>();

    public Book(String title, String author, int publicationYear) {
        this.title = title;
        this.author = author;
        this.publicationYear = LocalDate.of(publicationYear, 1, 1).getYear();
    }
}
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
@Getter
@Setter
@Entity
@Table(name = "BOOK_COPIES")
public class BookCopy {

    @Id
    @GeneratedValue
    @Column(name = "ID")
    private long id;

    @JsonManagedReference
    @NotNull
    @EqualsAndHashCode.Exclude
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "TITLE_ID")
    private Book book;

    @Enumerated(EnumType.STRING)
    @Column(name = "RENT_STATUS")
    private RentStatus rentStatus;

    public BookCopy(Book book, RentStatus rentStatus) {
        this.book = book;
        this.rentStatus = rentStatus;
    }

    public void setBook(Book book) {
        this.book = book;
        book.getBookCopies().add(this);
    }
}

Now, through Hibernate I create and save a new BookCopy item, by sending through to my Spring Web system a JSON like this one:

{
    "book":{
        "id": 99999
    },
    "rentStatus": "HIRED"
}

The thing is, that book by that id does not exist in the Book table. Is there a way, in which I can have this BookCopy save operation first verify the existence of its parent relationship?

UPDATE: Adding classes taking care of saving in DB:

First, the DBService class:

@Repository
public class BookCopyDbService {
    @Autowired
    private BookCopyRepository bookCopyRepository;

    public BookCopy saveBookCopy(BookCopy bookCopy) {
        return bookCopyRepository.save(bookCopy);
    }
}

And the CrudRepository class, interfacing with the DB:

@Transactional
@Repository
public interface BookCopyRepository extends CrudRepository<BookCopy, Long> {
}

Probably, I could put some logic in BookCopyDbService's saveBookCopy(), which would first try to find that book by ID in the Book table, and save BookCopy only if a book was found in that search, but I was wondering if Hibernate actually had some mechanism in place which did that for me.

You need to first fetch the Book entity by the id and then try to set the BookCopy. If book doesn't exsits, then you can throw exception.

@Service
public class BookService {
    @Autowired
    private BookRepository bookRepository;

    @Transactional
    public BookCopy saveBookCopy(BookCopy bookCopy,Long bookId) {
      Book book =bookRepository.findById(bookId).orElseThrow(()-> new 
       BookNotFoundException("Book not found."));
      book.getBookCopies().add(bookCopy);

        return book.getBookCopy();
    }

}

@Transactional will take care of inserting the BookCopy into the table.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM