I use Spring JDBC to load the data from a DB into the business model entity. My DAO interfaces are implemented by the classes that extend the JdbcDaoSupport class, which are responsible to creating the entity using the RowMapper classes. Then I have a facade class, which holds all the DAO interfaces and acts as a gateway to my model class (business logic class) requesting the business entities. Since, there is no lazy loading, all business entity data are loaded at once. This is fine for most of the cases, but in some cases I do want to load the data from DB lazily.
For example, I get all the Orders from the DB and would like to load Order Details only if the date meets certain condition (business logic). Here is a simple example of my design. I am looking for ways to improve the design so I could support lazy loading of Order Detail data if needed. You can see in the Business logic class, the ProcessOrder method needs the Order details only if the Order Date is Today, else doen't care about the details. However, my DAO loads all the Order Details when querying for Order by the facade class.
I understand one way is to expose the GetOrderDetails method in DAO and Facade class and allow the business logic class to load it, when needed. But, it wouldn't work for me. I have just mentioned a very simple case here, but there could be complex scenarios where the business object is passed on to another transformation layer and I don't want these layers to be responsible for loading the lazy part of the data.
Also, another possibility is to use a ORM tool like Hibernate. However, in my application this case may be applicable only at very few places and feel using an ORM tool to achieve this behavior is an overkill.
I am not looking for anything super fancy, just a simple design to make this happen for my special cases. Thanks for any help/suggestions.
class Order // Simple POJO business entity
{
int OrderID;
Date OrderDate;
Collection<OrderDetail> OrderDetails; // Need to load lazily
}
class OrderDetail //Simple POJO business entity
{
Order order;
int ItemID;
double Cost;
int Quantity;
}
// DAO Interface
interface OrderDAO
{
Order getOrder(int aOrderID);
}
// Concrete DAO class
JdbcOrderDao extends JdbcDaoSupport implements OrderDao
{
Order getOrder(int aOrderID)
{
Order order = getJdbcTemplate.query(....., new OrderRowMapper());
populateOrderDetails(order);
return order;
}
private PopulateOrderDetails(Order aOrder)
{
//Query the DB and fill the Order details data.
}
private class OrderRowMapper implements ParameterizedRowMapper<Order>
{
// Code implemented to create and return the business entity from the resultset;
}
}
// Facade class that hides the DAO interface and exposes the business methods
ServiceFacade
{
private OrderDAO orderDAO;
public Order GetOrder(int aOrderID)
{
return orderDAO.getOrder(aOrderID);
}
}
// Business Logic class
BusinessModelLoader
{
List<Order> Orders = new ArrayList<Order>();
LoadOrders()
{
for(Integer orderID : allOrderIDs)
Orders.add(facade.getOrder(orderID));
}
ProcessOrders()
{
for(Order order: Orders)
{
if (order.OrderDate == Today)
{
List<OrderDetail> details = order.OrderDetails; // Need to perform lazy loading here automatically
// Do something with details
}
}
}
}