Hibernate Indexed List Example

0

There are two different list types available in hibernate:

  1. Ordered lists – order is not persisted and instead defined in mapping
  2. Indexed lists – order is persisted

In this article, we will see an example of indexed list where the order is persisted.

Define list mapping

Order and it items indexed by item sequence will be our example.
Here is the mapping.

order.hbm.xml:

<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.javarticles.hibernate">

	<class name="com.javarticles.hibernate.Order" table="orders">
		<id name="orderKey" column="order_id" type="java.lang.Long"
			unsaved-value="null">
			<generator class="native" />
		</id>
		<property name="orderNbr" column="nbr" type="string" length="30" />
		<list name="orderItems" lazy="true" inverse="true" cascade="all">
			<key column="order_id" />
			<index column="seq"/>
			<one-to-many class="com.javarticles.hibernate.OrderItem" />
		</list>	
	</class>

	<class name="com.javarticles.hibernate.OrderItem" table="order_items">
		<id name="orderItemKey" column="order_item_id" type="java.lang.Long"
			unsaved-value="null">
			<generator class="native" />
		</id>
        <property name="orderItemSeq" column="seq" type="java.lang.Long" not-null="true">
            <meta attribute="field-description">Order item sequence number</meta>
        </property>		
		<many-to-one name="orderItemOrder" column="order_id"
			class="com.javarticles.hibernate.Order" not-null="true" />
		<property name="orderItemDesc" column="order_item_desc" type="string"
			length="45" />
        <property name="orderItemQty" column="qty" type="java.lang.Long" not-null="true" length="3"/>
	</class>

</hibernate-mapping>

Since inverse is set to true, we need to manage the bi-directional link ourselves. See method addOrderItem().

Order:

package com.javarticles.hibernate;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Order {
    private Long orderKey;
    private String orderNbr;
    private List<OrderItem> orderItems;

    public Long getOrderKey() {
        return orderKey;
    }

    public void setOrderKey(Long orderKey) {
        this.orderKey = orderKey;
    }

    public String getOrderNbr() {
        return orderNbr;
    }

    public void setOrderNbr(String orderNbr) {
        this.orderNbr = orderNbr;
    }
    
    public OrderItem addOrderItem(String desc, Long qty) {
        OrderItem orderItem = new OrderItem();
        orderItem.setOrderItemDesc(desc);
        orderItem.setOrderItemQty(qty);
        List orderItems = getOrderItems();
        if (orderItems == null) {
            orderItems = new ArrayList<>();
            setOrderItems(orderItems);
        }
        orderItems.add(orderItem);
        orderItem.setOrderItemOrder(this);
        return orderItem;
    }

    public List getOrderItems() {
        return orderItems;
    }

    public void setOrderItems(List orderItems) {
        this.orderItems = orderItems;
    }

}

OrderItem:

package com.javarticles.hibernate;

public class OrderItem {
    private Long orderItemSeq;
    private Long orderItemKey;
    private String orderItemDesc;
    private Long orderItemQty;
    private Order orderItemOrder;

    public Long getOrderItemKey() {
        return orderItemKey;
    }

    public void setOrderItemKey(Long orderItemKey) {
        this.orderItemKey = orderItemKey;
    }

    public String getOrderItemDesc() {
        return orderItemDesc;
    }

    public void setOrderItemDesc(String orderItemDesc) {
        this.orderItemDesc = orderItemDesc;
    }

    public Long getOrderItemQty() {
        return orderItemQty;
    }

    public void setOrderItemQty(Long orderItemQty) {
        this.orderItemQty = orderItemQty;
    }

    public Order getOrderItemOrder() {
        return orderItemOrder;
    }

    public void setOrderItemOrder(Order orderItemOrder) {
        this.orderItemOrder = orderItemOrder;
    }

    public Long getOrderItemSeq() {
        return orderItemSeq;
    }

    public void setOrderItemSeq(Long orderItemSeq) {
        this.orderItemSeq = orderItemSeq;
    }       
}

We first insert few order items and then update the item sequence which is also our index column.
First time when we insert items, hibernate makes sure they are in order. Even if we have set the sequence to some huge number, hibernate resets the sequence to an ordered one relative to the last sequence.

Any further updates to the item sequence is accepted as it is.

HibernateListByIndexExample:

package com.javarticles.hibernate;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import org.hibernate.MappingException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class HibernateListByIndexExample {

    public static void main(String[] args) throws MappingException, IOException {
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        try {
            Session session = sessionFactory.getCurrentSession();
            Transaction tx = session.getTransaction();
            tx.begin();
            Query query = session.createQuery("from Order");
            List<Order> orderList = query.list();
            for (Order order : orderList) {
                session.delete(order);
            }
            tx.commit();
            
            System.out.println("Insert order/order items");
            //Insert order/order items
            session = sessionFactory.openSession();
            tx = session.getTransaction();
            tx.begin();
            Order order = new Order();
            final String orderNbr = "ORN8118";
            order.setOrderNbr(orderNbr);
            OrderItem orderItem1 = order.addOrderItem("Laptop", 2L); 
            orderItem1.setOrderItemSeq(0L); 
            
            OrderItem orderItem2 = order.addOrderItem("Tab", 5L); 
            orderItem2.setOrderItemSeq(1L);         
            
            OrderItem orderItem3 = order.addOrderItem("Notebook", 12L); 
            orderItem3.setOrderItemSeq(88888888L);   
            
            OrderItem orderItem4 = order.addOrderItem("Mobile", 8L); 
            orderItem4.setOrderItemSeq(11111111L);   
            session.save(order);
            tx.commit();
            
            printQueryResults(sessionFactory, orderNbr);

            System.out.println("Insert new order item, following invert convention");
            // insert new order item
            session = sessionFactory.openSession();
            tx = session.getTransaction();
            tx.begin();
            query = session.createQuery("from Order where orderNbr = '" + orderNbr + "'");
            order = (Order) query.list().get(0);
            OrderItem orderItemX = order.addOrderItem("Stationary", 5L);
            orderItemX.setOrderItemSeq(444444L);
            tx.commit();  
  
            printQueryResults(sessionFactory, orderNbr);
            
            
            System.out.println("Update existing order item, fetch itmes from order, update second item");
            //update existing order item, fetch from order based on seq
            session = sessionFactory.openSession();
            tx = session.getTransaction();
            tx.begin();
            query = session.createQuery("from Order where orderNbr = '" + orderNbr + "'");
            order = (Order) query.list().get(0);
            orderItem1 = order.getOrderItems().get(1);
            orderItem1.setOrderItemSeq(99999L);
            tx.commit();  
            
            printQueryResults(sessionFactory, orderNbr);
            
            System.out.println("Update existing order item, fetch from order based on seq 2");
            //Update existing order item, fetch from order based on seq
            session = sessionFactory.openSession();
            tx = session.getTransaction();
            tx.begin();
            query = session.createQuery("from OrderItem where orderItemSeq = 2");
            OrderItem orderItem = (OrderItem) query.list().get(0);
            orderItem.setOrderItemSeq(2222222L);
            tx.commit();     
            
            printQueryResults(sessionFactory, orderNbr);
            
            System.out.println("Insert new order item without taking care of invert");
            //Insert new order item without taking care of invert
            session = sessionFactory.openSession();
            tx = session.getTransaction();
            tx.begin();
            OrderItem orderItem5 = new OrderItem();
            orderItem5.setOrderItemDesc("Books");
            orderItem5.setOrderItemOrder(order);
            orderItem5.setOrderItemQty(12L);
            orderItem5.setOrderItemSeq(555555L);
            session.save(orderItem5);
            tx.commit();    
            
            printQueryResults(sessionFactory, orderNbr);
        } finally {
            sessionFactory.close();
        }
    }
    
    private static void printQueryResults(SessionFactory sessionFactory, String orderNbr) {
        Session session = sessionFactory.openSession();
        Transaction tx = session.getTransaction();
        tx.begin();
        Query query = session.createQuery("from Order where orderNbr = '" + orderNbr + "'");
        List<Order> orderList = query.list();
        Order order = orderList.get(0);
        
        List<OrderItem> orderItems = order.getOrderItems();
        if (orderItems != null) {
            System.out.println("Size of items: " + orderItems.size());                
            Iterator<OrderItem> itr = orderItems.iterator();
            
            while (itr.hasNext()) {
                OrderItem item = itr.next();
                if (item != null) {
                    System.out.println("Item at Seq " + item.getOrderItemQty() + ", " + item.getOrderItemDesc());
                }
            }
        }
        
        tx.commit();   
    }
}

Output:

Insert order/order items

Size of items: 4
Item at Seq 0, Laptop
Item at Seq 1, Tab
Item at Seq 2, Notebook
Item at Seq 3, Mobile

Insert new order item, following invert convention

Size of items: 444446
Item at Seq 0, Laptop
Item at Seq 1, Tab
Item at Seq 2, Notebook
Item at Seq 3, Mobile
Item at Seq 444445, Stationary

Update existing order item, fetch itmes from order, update second item

Size of items: 444446
Item at Seq 0, Laptop
Item at Seq 2, Notebook
Item at Seq 3, Mobile
Item at Seq 99999, Tab
Item at Seq 444445, Stationary

Update existing order item, fetch from order based on seq 2

Size of items: 2222223
Item at Seq 0, Laptop
Item at Seq 3, Mobile
Item at Seq 99999, Tab
Item at Seq 444445, Stationary
Item at Seq 2222222, Notebook

Insert new order item without taking care of invert

Size of items: 2222223
Item at Seq 0, Laptop
Item at Seq 3, Mobile
Item at Seq 99999, Tab
Item at Seq 444445, Stationary
Item at Seq 555555, Books
Item at Seq 2222222, Notebook

Retrieve hibernate list item by index

After running the above example, we will now check the items size and retrieve the ones which exist actually.

HibernateRetrieveOrderItemBySeqExample:

package com.javarticles.hibernate;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import org.hibernate.MappingException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

public class HibernateRetrieveOrderItemBySeqExample {

    public static void main(String[] args) throws MappingException, IOException {
        Configuration configuration = new Configuration().configure();
        SessionFactory sessionFactory = configuration.buildSessionFactory();
        try {
            final String orderNbr = "ORN8118";
            Session session = sessionFactory.getCurrentSession();
            Transaction tx = session.getTransaction();
            tx.begin();
            Query query = session.createQuery("from Order where orderNbr = '" + orderNbr + "'");
            Order order = (Order) query.list().get(0);
            
            List<OrderItem> orderItems = order.getOrderItems();
            if (orderItems != null) {
                System.out.println("Size of items: " + orderItems.size());
                System.out.println("Last Item: " + orderItems.get(orderItems.size() -1).getOrderItemDesc());
                Iterator<OrderItem> itr = orderItems.iterator();             
                while (itr.hasNext()) {
                    OrderItem item = itr.next();
                    if (item != null) {
                        System.out.println("Item at Seq " + item.getOrderItemSeq() + ", " + item.getOrderItemDesc());
                    }
                }
            }
            
            tx.commit();            
        } finally {
            sessionFactory.close();
        }
    }
}

We can retrieve a specific item using its index. We first printed the items size. Next retrieved the last order item. Though actual items are only 6, the count of items suggests there are 2222223 items. Wwe traverse through the items that actually exist and print the details.
Note of caution here is the items count is not the actual count but is the index number.

Output:

Size of items: 2222223
Last Item: Notebook
Item at Seq 0, Laptop
Item at Seq 3, Mobile
Item at Seq 99999, Tab
Item at Seq 444445, Stationary
Item at Seq 555555, Books
Item at Seq 2222222, Notebook

Download the source code

This was an example of hibernate list index.

You can download the source code here: hibernateListExample.zip

About Author

Ram’s expertise lies in test driven development and re-factoring. He is passionate about open source technologies and loves blogging on various java and open-source technologies like spring.
You can reach him at [email protected]

Comments are closed.