Reputation: 2731
I wanted to design many-to-many relationship with composition key via hibernate.
I used 3 classes including book
,orders
and orderDetail
class except for composition key class
. In the database, there are 3 tables named for BOOK
, ORDERS
and ORDER_DETAIL
.
I defined all mapping class in the hibernate.cfg.xml
.
<mapping class="com.bookstore.entity.Book"/>
<mapping class="com.bookstore.entity.OrderDetail"/>
<mapping class="com.bookstore.entity.OrderDetailId"/>
<mapping class="com.bookstore.entity.Orders"/>
<!-- Drop and re-create the database schema on start-up -->
<property name="hibernate.hbm2ddl.auto">update</property>
Here are my classes shown below.
Book class
@Entity
@Table(name="BOOK",catalog = "JSPPROJECTDATABASE")
public class Book implements Serializable{
@Id
@SequenceGenerator(name="BOOK_SEQ", sequenceName="BOOK_SEQ", allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="BOOK_SEQ")
@Column(name="BOOK_ID", nullable = false)
private int id;
@OneToMany(mappedBy = "pk.books", cascade=CascadeType.ALL)
private Set<OrderDetail> orderDetails = new HashSet<OrderDetail>();
// constructor
// getter and setter
public Set<OrderDetail> getOrderDetails() {
return orderDetails;
}
public void setOrderDetails(Set<OrderDetail> orderDetails) {
this.orderDetails = orderDetails;
}
}
For Orders class
@Entity
@Table(name="ORDERS",catalog = "JSPPROJECTDATABASE")
public class Orders implements Serializable{
@Id
@SequenceGenerator(name="ORDERS_SEQ", sequenceName="ORDERS_SEQ", allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="ORDERS_SEQ")
@Column(name="ORDER_ID", nullable = false)
private int id;
@OneToMany(mappedBy = "pk.order", cascade=CascadeType.ALL)
private Set<OrderDetail> orderDetails = new HashSet<OrderDetail>();
// constructor
// getter and setter
public Set<OrderDetail> getOrderDetails() {
return orderDetails;
}
public void setOrderDetails(Set<OrderDetail> orderDetails) {
this.orderDetails = orderDetails;
}
}
OrderDetail Class
@Entity
@Table(name = "ORDER_DETAIL", catalog = "JSPPROJECTDATABASE")
@AssociationOverrides({
@AssociationOverride(name = "pk.order",
joinColumns = @JoinColumn(name = "ORDER_ID")),
@AssociationOverride(name = "pk.books",
joinColumns = @JoinColumn(name = "BOOK_ID")) })
public class OrderDetail implements Serializable{
private OrderDetailId pk = new OrderDetailId();
@Column(name="QUANTITY")
private int quantity;
@Column(name="SUBTOTAL")
private float subTotal;
public OrderDetail() {
super();
// TODO Auto-generated constructor stub
}
@EmbeddedId
public OrderDetailId getPk() {
return pk;
}
public void setPk(OrderDetailId pk) {
this.pk = pk;
}
@Transient
public Book getBook() {
return getPk().getBooks();
}
public void setBook(Book book) {
getPk().setBooks(book);
}
@Transient
public Orders getOrders() {
return getPk().getOrder();
}
public void setOrders(Orders orders) {
getPk().setOrder(orders);
}
public int getQuantity() {
return quantity;
}
public void setQuantity(int quantity) {
this.quantity = quantity;
}
public float getSubTotal() {
return subTotal;
}
public void setSubTotal(float subTotal) {
this.subTotal = subTotal;
}
}
Composititon Class named for OrderDetailId
@Embeddable
public class OrderDetailId implements Serializable{
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name = "BOOK_ID",insertable = false, updatable = false,nullable = false)
private Book books;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name = "ORDER_ID",insertable = false, updatable = false,nullable = false)
private Orders order;
public Book getBooks() {
return books;
}
public void setBooks(Book books) {
this.books = books;
}
public Orders getOrder() {
return order;
}
public void setOrder(Orders order) {
this.order = order;
}
}
When I run the code, there is an error appeared on the screen.
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table REVIEW add constraint FKf8kovbt4otqcvp75w008agrbx foreign key (CUSTOMER_ID) references CUSTOMER" via JDBC Statement
at org.hibernate.tool.schema.internal.exec.GenerationTargetToDatabase.accept(GenerationTargetToDatabase.java:67)
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table REVIEW add constraint FKf339wkg63wmuutk10j4iowly0 foreign key (BOOK_ID) references BOOK" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table ORDERS add constraint FKkdbly1ij6f4kqh378kfne6ilx foreign key (CUSTOMER_ID) references CUSTOMER" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table ORDER_DETAIL add constraint FKag30vapylo13u3lax0elv3n06 foreign key (order) references ORDERS" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table ORDER_DETAIL add constraint FKqk2p0pl26ysleeejh8isy44or foreign key (books) references BOOK" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table BOOK add constraint FKprh5cdnlwefrxo30ausnijl3d foreign key (CATEGORY_ID) references CATEGORY" via JDBC Statement
org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL "alter table ORDER_DETAIL add order raw(255) not null" via JDBC Statement
If I defined any wrong variable in the class or any wrong association in its relationship, how can I fix it?
Upvotes: 2
Views: 1634
Reputation: 26056
It's because mappedBy
is used to indicate a field, that is used for mapping (name of that field). You have probably used column names. If you want to use mappedBy
, you need to declare bidirectional relationship and on the child side use @JoinColumn
. Then you can pass the name of that field into mappedBy
.
Suppose you have the following in OrderDetailId
:
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name = "BOOK_ID")
private Book books;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name = "ORDER_ID")
private Orders order;
Then in Orders
:
@OneToMany(mappedBy = "order", cascade=CascadeType.ALL)
private Set<OrderDetail> orderDetails = new HashSet<OrderDetail>();
and in Book
:
@OneToMany(mappedBy = "pk.books", cascade=CascadeType.ALL)
private Set<OrderDetail> orderDetails = new HashSet<OrderDetail>();
Upvotes: 1
Reputation: 695
You have to use columns for mapping.
But in you code for OrderDetailId
, you were used another entity references.
For better design you have to use simple Id's in ID class
Upvotes: 1