I have two classes: Book and Member. In the Member class there are two HashSet which store Books: borrowedBooks and returnedBooks.
When I remove one Book from borrowedBooks and put it into returnedBook, Hibernate will do that without a problem for all except for the last element in borrowedBooks. However, if i remove the last element in borrowedBooks Hibernate also removes all of the Books in returnedBook. So, at the end of scenario there are no Books in borrowedBooks, but there are also no Books in returnedBooks.
For example:
1) borrowedBooks: a, b, c
1) returnedBooks:
---
2) borrowedBooks: a, b
2) returnedBooks: c
---
3) borrowedBooks: a
3) returnedBooks: b, c
---
4) borrowedBooks: -
4) returnedBooks: -
That's really not understandable! Why does this happen? Thanks a lot for your help! Here are my classes:
@Entity
public class Book {
@Id
@TableGenerator(...)
@GeneratedValue(generator = "Book_Barcode")
private long barcode;
private long isbn=0;
private String bookTitle="";
// some other fields
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (int) (barcode ^ (barcode >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Book other = (Book) obj;
if (barcode != other.barcode)
return false;
return true;
}
}
@Entity
public class Member {
@Id
@TableGenerator(...)
@GeneratedValue(generator = "Member_Id")
private int id;
@OneToMany(fetch = FetchType.EAGER) //please ignore FetchType!
private Set<Book> returnedBooks = new HashSet<>();
@OneToMany(fetch = FetchType.EAGER)
private Set<Book> borrowedBooks = new HashSet<>();
@OneToMany(fetch = FetchType.EAGER)
private Set<Book> renewedBooks = new HashSet<>();
}
@Repository
public class MemberDAOImpl implements MemberDAO {
@Autowired
private SessionFactory sessionFactory;
@Override
@Transactional
public void borrowBook(Member member, Book book) {
if (book.getStatus().equals("Available") &&
book.getAvailableAmount() > 0) {
Session currentSession = sessionFactory.getCurrentSession();
book.setBorrowedDate(new Date());
book.setAvailableAmount(book.getAvailableAmount() - 1);
book.setStatus("Borrowed");
Member newMember = currentSession.find(Member.class, member.getId());
newMember.getBorrowedBooks().add(book);
}
}
@Override
@Transactional
public void returnBook(Member member, Book book) {
if (book.getStatus().equals("Borrowed")) {
Session currentSession = sessionFactory.getCurrentSession();
Member newMember = currentSession.find(Member.class, member.getId());
newMember.getReturnedBooks().add(book);
newMember.getBorrowedBooks().remove(book);
book.setBorrowedDate(null);
book.setAvailableAmount(book.getAvailableAmount() + 1);
book.setStatus("Available");
book.setRenewedTimes(0);
}
}
}
@Controller
@RequestMapping("/member")
public class MemberController {
static Member member;
@Autowired
private MemberService memberService;
@Autowired
private BookService bookService;
@GetMapping("/bookBorrow")
public String bookBorrow(@RequestParam("barcode") long barcode, Model model) {
Book book = bookService.searchBookByBarcode(barcode);
memberService.borrowBook(member, book);
model.addAttribute("booksList", member.getBorrowedBooks());
model.addAttribute("member", member);
return "member-specific-home-page";
}
@GetMapping("/bookReturn")
public String bookReturn(@RequestParam("barcode") long barcode, Model model) {
Book book = bookService.searchBookByBarcode(barcode);
memberService.returnBook(member, book);
model.addAttribute("booksList", member.getReturnedBooks());
model.addAttribute("member", member);
return "member-specific-home-page";
}
}
So, I believe there is no problem in public void borrowBook(...).
Is there something wrong in public void returnBook(...)?
I spent a lot of time but i could not find a way... Thanks in advance!
================================ There is something wrong with Hibernate! For example: if i have 3 books in borrowedBooks set and than if i try to return them: so remove from borrowedBooks and put in returnedBook.
FIRST RETURN:
Hibernate: update Book set amount=?, availableAmount=?, bookTitle=?, borrowedDate=?, description=?, editedDate=?, edition=?, isbn=?, issuedDate=?, language=?, page=?, price=?, publisher=?, registrationDate=?, renewedDate=?, renewedTimes=?, status=? where barcode=?
Hibernate: insert into Member_Book (Member_id, returnedBooks_barcode) values (?, ?)
Hibernate: delete from Member_Book where Member_id=? and borrowedBooks_barcode=?
SECOND RETURN:
Hibernate: update Book set amount=?, availableAmount=?, bookTitle=?, borrowedDate=?, description=?, editedDate=?, edition=?, isbn=?, issuedDate=?, language=?, page=?, price=?, publisher=?, registrationDate=?, renewedDate=?, renewedTimes=?, status=? where barcode=?
Hibernate: insert into Member_Book (Member_id, returnedBooks_barcode) values (?, ?)
Hibernate: delete from Member_Book where Member_id=? and borrowedBooks_barcode=?
THIRD RETURN:
Hibernate: update Book set amount=?, availableAmount=?, bookTitle=?, borrowedDate=?, description=?, editedDate=?, edition=?, isbn=?, issuedDate=?, language=?, page=?, price=?, publisher=?, registrationDate=?, renewedDate=?, renewedTimes=?, status=? where barcode=?
Hibernate: insert into Member_Book (Member_id, returnedBooks_barcode) values (?, ?)
Hibernate: delete from Member_Book where Member_id=?
PLEASE LOOK AT THE "LAST" DELETE OPERATION: delete from Member_Book where Member_id=? WHY JUST "where Member_id=?" ???