This is a typical one to many mapping problem [Item to Bid.] If we talk about writing this logic in Java, we'll probably write something like below in the Item class.
public void addBid(Bid bid){
bids.add(bid);
bid.setItem(this);
}
We add the bid in bids and associate the item to the bid as well. Java does not manage associations neither does Hibernate. You have to explicitly make a link at both ends of the relation. Item to Bid, and Bid to Item as shown above.
How do you apprehend the above method. There are two updates. First, the bid got added to bids which is in Item. Second, we associated the Item to the Bid. Java as well as Hibernate see this as two updates. But if we think in terms of Database, we just added a Bid in a Bid_table table and that’s all. There is only one update !!!!
Hibernate supports transitive persistence model and we can tell hibernate to understand this relation using a property 'inverse="true"'. I guess example will make things more clear.
//Bid.class and its corresponding mapping file. Notice many-to-one element which is acting like, rather is, reference key.
public class Bid {
private Long id = new Long(-1);
private Item item;
private Double amount;
private Date bidDate;
public Bid(){}
public Bid(Double amount){
this.amount = amount;
this.bidDate = new Date();
}
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
...... Other getter and setters.
}
<class name="association.Bid" table="BID">
<id name="id" column="BID_ID" type="long">
<generator class="increment"/>
</id>
<property name="amount" column="amount" type="java.lang.Double" />
<property name="bidDate" column="BID_DATE" type="java.util.Date" />
<many-to-one
name="item"
column="ITEM_ID"
class="association.Item"
not-null="true"/>
</class>
//Item.class as its corresponing mapping file
public class Item {
private Long id;
private Set<Bid> bids = new HashSet<Bid>();
private String name;
private String description;
private Double initialAmount;
public Item(){}
public Item(String name,String description, Double initialAmount){
this.name = name;
this.description = description;
this.initialAmount = initialAmount;
}
public void addBid(Bid bid){
bids.add(bid);
bid.setItem(this);
}
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
....... other getters and setters
}
<class name="association.Item" table="ITEM">
<id name="id" column="ITEM_ID" type="long">
<generator class="increment"/>
</id>
<property name="name" column="name" type="java.lang.String" />
<property name="description" column="description" type="java.lang.String" />
<property name="initialAmount" column="initial_price" type="java.lang.Double" />
<set name="bids">
<key column="ITEM_ID"/>
<one-to-many class="association.Bid"/>
</set>
</class>
// TEST Class for this association.
public class ItemBidTest {
public static void main(String[] args){
Item item = new Item("SKU-1","SKU-1 Description", new Double(10.98));
item.addBid(new Bid(new Double(11.10)));
item.addBid(new Bid(new Double(11.15)));
item.addBid(new Bid(new Double(11.20)));
saveItem(item);
}
public static void saveItem(Item item){
Transaction tx = null;
Session session = InitSessionFactory.getInstance().getCurrentSession();
try {
tx = session.beginTransaction();
session.save(item);
tx.commit();
} catch (HibernateException e) {
e.printStackTrace();
if (tx != null && tx.isActive())
tx.rollback();
}
}
}
----------OUTPUT, Mapping of bids in Item.hbm.xml is below ----------------------------
<set name="bids" cascade="all-delete-orphan">
<key column="ITEM_ID"/>
<one-to-many class="association.Bid"/>
</set>
Hibernate: insert into ITEM (name, description, initial_price, ITEM_ID) values (?, ?, ?, ?)
Hibernate: insert into BID (amount, BID_DATE, ITEM_ID, BID_ID) values (?, ?, ?, ?)
Hibernate: insert into BID (amount, BID_DATE, ITEM_ID, BID_ID) values (?, ?, ?, ?)
Hibernate: insert into BID (amount, BID_DATE, ITEM_ID, BID_ID) values (?, ?, ?, ?)
Hibernate: update BID set ITEM_ID=? where BID_ID=?
Hibernate: update BID set ITEM_ID=? where BID_ID=?
Hibernate: update BID set ITEM_ID=? where BID_ID=?
----------OUTPUT, MAPPING in Item.hbm.xml CHANGED to below -----------------------------
<set name="bids" cascade="all-delete-orphan" inverse="true">
<key column="ITEM_ID"/>
<one-to-many class="association.Bid"/>
</set>
Hibernate: insert into ITEM (name, description, initial_price, ITEM_ID) values (?, ?, ?, ?)
Hibernate: insert into BID (amount, BID_DATE, ITEM_ID, BID_ID) values (?, ?, ?, ?)
Hibernate: insert into BID (amount, BID_DATE, ITEM_ID, BID_ID) values (?, ?, ?, ?)
Hibernate: insert into BID (amount, BID_DATE, ITEM_ID, BID_ID) values (?, ?, ?, ?)
>>> We therefore got rid of extra update queries to database.