Hibernate Foreign Key Problems

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

Answers (2)

Andronicus
Andronicus

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

Ajmal Muhammad
Ajmal Muhammad

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

Related Questions