One of the biggest problem that I found while working with EJB is to set up a working many to many relation between two Enterprise Java Beans.
Without losing in generality let us assume that we have a relation Book - Authors.
As we can imagine a Book could have more than one author and an Author could have written more then one book.
We want to model two EJBs in a way that when we want to store a book into our DBs, automatically the system saves (or merge Depend whether the author is already present in the DB) the authors.
As clarification let me put the two EJBs
The first piece of code is the Book Entity
-----------------------
public class Book implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "Book_Id")
private Integer Book_Id;
@Basic(optional = false)
@Column(name = "Title")
private String title;
@Basic(optional = false)
@Column(name = "Pub_Date")
private String pubDate;
@Basic(optional = false)
@Column(name = "Price")
private double price;
@Basic(optional = false)
@Column(name = "Quantity")
private int quantity;
@Basic(optional = false)
@Column(name = "Deleted")
private boolean deleted;
@JoinTable(name = "BOOK_AUTHOR", joinColumns = {
@JoinColumn(name = "Book_Id", referencedColumnName = "Book_Id")}, inverseJoinColumns = {
@JoinColumn(name = "Author_Id", referencedColumnName = "Author_Id")})
@ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
private List<Author> authorList;
public Book() {
}
public Book(Integer Book_Id) {
this.Book_Id = Book_Id;
}
public Book(Integer Book_Id, String title, String pubDate, double price, int quantity, boolean deleted) {
this.Book_Id = Book_Id;
this.title = title;
this.pubDate = pubDate;
this.price = price;
this.quantity = quantity;
this.deleted = deleted;
}
public Integer getBook_Id() {
return Book_Id;
}
public void setBook_Id(Integer Book_Id) {
this.Book_Id = Book_Id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getPubDate() {
return pubDate;
}
public void setPubDate(String pubDate) {
this.pubDate = pubDate;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public boolean getDeleted() {
return deleted;
}
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
@Override
public int hashCode() {
int hash = 0;
hash += (Book_Id != null ? Book_Id.hashCode() : 0);
return hash;
}
public List<Author> getAuthorList() {
return authorList;
}
public void setAuthorList(List<Author> authorList) {
this.authorList = authorList;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Book)) {
return false;
}
Book other = (Book) object;
if ((this.Book_Id == null && other.Book_Id != null) || (this.Book_Id != null && !this.Book_Id.equals(other.Book_Id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "entity.Book[Book_Id=" + Book_Id + "]";
}
}
-----------------------
And the second is the Author entity
-----------------------
public class Author implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "Author_Id")
private Integer Author_Id;
@Basic(optional = false)
@Column(name = "Name")
private String name;
@Basic(optional = false)
@Column(name = "Surname")
private String surname;
@Basic(optional = false)
@Column(name = "Email")
private String email;
@Basic(optional = false)
@Column(name = "Deleted")
private boolean deleted;
public Author() {
}
public Author(Integer Author_Id) {
this.Author_Id = Author_Id;
}
public Author(Integer Author_Id, String name, String surname, String email, boolean deleted) {
this.Author_Id = Author_Id;
this.name = name;
this.surname = surname;
this.email = email;
this.deleted = deleted;
}
public Integer getAuthorId() {
return Author_Id;
}
public void setAuthorId(Integer Author_Id) {
this.Author_Id = Author_Id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean getDeleted() {
return deleted;
}
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
@Override
public int hashCode() {
int hash = 0;
hash += (Author_Id != null ? Author_Id.hashCode() : 0);
return hash;
}
@Override
public boolean equals(Object object) {
// TODO: Warning - this method won't work in the case the id fields are not set
if (!(object instanceof Author)) {
return false;
}
Author other = (Author) object;
if ((this.Author_Id == null && other.Author_Id != null) || (this.Author_Id != null && !this.Author_Id.equals(other.Author_Id))) {
return false;
}
return true;
}
@Override
public String toString() {
return "entity.Author[Author_Id=" + Author_Id + "]";
}
-----------------------
In this example we have a uni-directional many to many relation, this mean that we can have the list of author that wrote a particular book but not vice versa.(w cannot have the list of books written by this author). Note that if you want to do this it is enough to add in Author a list with the following annotation:
@ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER, mappedBy = "authorList")
private List<Book> bookList;
Of course authorList is the list of author in the Book bean and, for sure we have to add its proper getter and setter.
Once done this,our many to many relation is ready to work.
Let however analyze a bit better what is highlighted in the Book Bean.
@JoinTable(name = "BOOK_AUTHOR", joinColumns = {
@JoinColumn(name = "Book_Id", referencedColumnName = "Book_Id")}, inverseJoinColumns = {
@JoinColumn(name = "Author_Id", referencedColumnName = "Author_Id")})
@ManyToMany(cascade = {CascadeType.ALL}, fetch = FetchType.EAGER)
private List<Author> authorList;
First of all, BOOK_AUTHOR is a small table that contains only the Book_Id and the Author_Id. This table is not mapped into an entity and is only a DBTable that we can create just by using the code posted on the previous post named :Let hibernate create DB tables.
As always we have to specify hibernate that the relation is a many-to-many that needs a cascade all relation and that when we ask for a book, it has to load directly also its related authors.
No comments:
Post a Comment