我使用Spring JDBC将数据从DB加载到业务模型实体中。我的DAO接口由扩展JdbcDaoSupport类的类实现,这些类负责使用RowMapper类创建实体。然后我有一个facade类,它包含所有DAO接口,并充当请求业务实体的模型类(业务逻辑类)的网关。由于没有延迟加载,因此会立即加载所有业务实体数据。这对大多数情况都很好,但在某些情况下我确实想懒洋洋地从DB加载数据。
例如,我从数据库中获取所有订单,并且只有在日期满足特定条件(业务逻辑)时才想加载订单明细。这是我设计的一个简单例子。我正在寻找改进设计的方法,以便在需要时支持延迟加载订单明细数据。您可以在业务逻辑类中看到,仅当订单日期为今天时,ProcessOrder方法才需要订单详细信息,否则不关心详细信息。但是,我的DAO在通过facade类查询Order时加载所有Order Details。
我知道一种方法是在DAO和Facade类中公开GetOrderDetails方法,并在需要时允许业务逻辑类加载它。但是,这对我不起作用。我刚才提到了一个非常简单的案例,但可能存在复杂的场景,其中业务对象被传递到另一个转换层,我不希望这些层负责加载数据的惰性部分。
另外,另一种可能性是使用像Hibernate这样的ORM工具。但是,在我的应用程序中,这种情况可能仅适用于极少数地方,并且感觉使用ORM工具来实现此行为是一种过度杀伤力。
我不是在寻找任何超级花哨的东西,只是为了我的特殊情况而设计的简单设计。感谢您的任何帮助/建议。
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
}
}
}
}
JPA将这样做的方式是执行另一个查询以获取满足该条件的每个订单的每个orderDetails实体。
它会在您在代码中调用它时获取。
order.getOrderDetails()
因此,为了实现它,为什么不执行JPA hibernate所做的事情。
通过我能理解你的问题,这是我的回答。
您想懒洋洋地在Order对象中加载Order Details。为此,如果使用注释,则必须在映射文件或LAZY=true
中将Order Details集合设置为fetch=FetchType.LAZY
。
现在,当您查询Order对象时,在需要之前不会加载订单详细信息。
现在,由于会话将在DAO类中执行getOrder后关闭,因此您将无法在业务层中使用延迟加载的对象。为此,在返回对象之前在DAO方法中执行以下操作
Hibernate.initialize(order.getOrderDetails());
我希望我回答你的问题。