Hibernate version: 2.16
I am trying to follow the example in the book and the documentation related to mapping a many to many relationship with additional columns in the join table. I know this has come up before, and I have searched the archives, but I still cannot solve my problem.
I am trying to model a Order --> order_product <-- Product relationship.
My mapping:
Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="com.hibertest.vo.Order"
table="orders">
<id name="orderId"
column="order_id"
type="integer"
>
<generator class="native">
</generator>
</id>
<set
name="purchasedItems"
cascade="all-delete-orphan"
inverse="true"
lazy="true"
table="order_product"
>
<key column="order_id">
</key>
<composite-element class="com.hibertest.vo.Purchase">
<property name="purchaseDate" column="purchased_date" not-null="true"/>
<property name="price" not-null="true"/>
<property name="quantity" not-null="true"/>
<many-to-one not-null="true" name="product" class="com.hibertest.vo.Product" column="product_id"/>
</composite-element>
</set>
<property
name="orderName"
type="string"
column="order_name"
not-null="false"
unique="false"
/>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="com.hibertest.vo.Product"
table="product">
<id name="productId"
column="product_id"
type="integer"
>
<generator class="native">
</generator>
</id>
<property
name="name"
type="string"
column="product_name"
not-null="false"
unique="false"
/>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="com.hibertest.vo.Purchase"
table="order_product">
<composite-id name="id" class="com.hibertest.vo.Purchase$Id"
unsaved-value="any">
<key-property name="orderId"
column="order_id"
length="16"/>
<key-property name="productId"
column="product_id"
length="16"/>
</composite-id>
<property
name="purchaseDate"
type="string"
column="purchased_date"
not-null="false"
unique="false"
/>
<property
name="price"
type="string"
column="price"
not-null="false"
unique="false"
/>
<property
name="quantity"
type="integer"
column="quantity"
not-null="false"
unique="false"
/>
<many-to-one name="order"
insert="false"
update="false"
not-null="true"
column="ORDER_ID"/>
<many-to-one name="product"
insert="false"
update="false"
not-null="true"
column="PRODUCT_ID"/>
</class>
</hibernate-mapping>
As you can see I am using a composite id in purchase.hbm.xml.
However, when I run the following code:
Code:
try{
Session session = HibernateUtil.currentSession();
Transaction tx = session.beginTransaction();
Order order = (Order)session.load(Order.class, new Integer(1));
order.setOrderName("Changed order name");
Purchase p = (Purchase)order.getPurchasedItems().iterator().next();
//session.saveOrUpdate(order);
tx.commit();
System.out.print("Commited the transaction. Loaded User");
HibernateUtil.closeSession();
}
catch(HibernateException hex){
System.out.print("Caught HibernateException " + hex);
}
catch(Exception hex){
System.out.print("Caught Exception " + hex);
}
I keep on getting a Caught HibernateException net.sf.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.hibertest.vo.Purchase
I stepped with a debugger through the purchase class when I ran this code and it turns out that the inner class I am using for a composite key is not being populated by Hibernate. Those fields are null.
Code:
/*
* Created on Dec 13, 2004
*
* TODO To change the template for this generated file go to
* Window - Preferences - Java - Code Style - Code Templates
*/
package com.hibertest.vo;
import java.io.Serializable;
/**
* @author jalvar
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
*/
public class Purchase implements Serializable {
private String purchaseDate;
private String price;
private int quantity;
private Product product;
private Integer purchaseId;
private Order order;
// ******************* Begin Inner composite Id class ******************* //
public static class Id implements Serializable {
private Long orderId;
private Long productId;
public Id() {}
public Id(Long orderId, Long productId) {
this.orderId = orderId;
this.productId = productId;
}
public boolean equals(Object o) {
if (o instanceof Id) {
Id that = (Id)o;
return this.productId.equals(that.productId) &&
this.orderId.equals(that.orderId);
} else {
return false;
}
}
public int hashCode() {
return orderId.hashCode() + productId.hashCode();
}
/**
* @return Returns the orderId.
*/
public Long getOrderId() {
return orderId;
}
/**
* @param orderId The orderId to set.
*/
public void setOrderId(Long orderId) {
this.orderId = orderId;
}
/**
* @return Returns the productId.
*/
public Long getProductId() {
return productId;
}
/**
* @param productId The productId to set.
*/
public void setProductId(Long productId) {
this.productId = productId;
}
}
/**
* @return Returns the id.
*/
public Id getId() {
return id;
}
/**
* @param id The id to set.
*/
public void setId(Id id) {
this.id = id;
}
/**
* @return Returns the order.
*/
public Order getOrder() {
return order;
}
/**
* @param order The order to set.
*/
public void setOrder(Order order) {
this.order = order;
}
private Id id = new Id();
/**
* @return Returns the purchaseId.
*/
public Integer getPurchaseId() {
return purchaseId;
}
/**
* @param purchaseId The purchaseId to set.
*/
public void setPurchaseId(Integer purchaseId) {
this.purchaseId = purchaseId;
}
/**
* @return Returns the product.
*/
public Product getProduct() {
return product;
}
/**
* @param product The product to set.
*/
public void setProduct(Product product) {
this.product = product;
}
/**
* @return Returns the price.
*/
public String getPrice() {
return price;
}
/**
* @param price The price to set.
*/
public void setPrice(String price) {
this.price = price;
}
/**
* @return Returns the purchaseDate.
*/
public String getPurchaseDate() {
return purchaseDate;
}
/**
* @param purchaseDate The purchaseDate to set.
*/
public void setPurchaseDate(String purchaseDate) {
this.purchaseDate = purchaseDate;
}
/**
* @return Returns the quantity.
*/
public int getQuantity() {
return quantity;
}
/**
* @param quantity The quantity to set.
*/
public void setQuantity(int quantity) {
this.quantity = quantity;
}
}
I have tried to follow this as close to the book and documentation as possible, but I have had no luck with this.
Any help is greatly appreciated.
Thanks