Spring AOP对Hibernate托管POJO的建议

时间:2011-10-05 23:40:59

标签: hibernate spring domain-driven-design aspectj spring-aop

我有一个父子关系,例如Order to Order Item,我在域模型中代表了这样的关系:

public class Order {
    private int id;    
    private Set<OrderItem> orderItems = new HashSet<OrderItem>();

    public int getId() {
        return id;
    }

    public void add(OrderItem orderItem) {
        orderItems.add(orderItem);
    }
}

public class OrderItem {
    private int id;

    public int getId() {
        return id;
    }

}

我使用Hibernate持久化这些实体,使用如下映射:

<class name="Order" table="ORDERS">
    <id name="id" column="ORDER_ID" access="field">
        <generator class="native" />
    </id>
    <set name="orderItems" table="ORDERS_TO_ITEMS" access="field" cascade="all">
        <key column="ORDER_ID" />
        <many-to-many class="OrderItem" unique="true" column="ITEM_ID" />
    </set>
</class>

<class name="OrderItem" table="ORDER_ITEMS">
    <id name="id" column="ITEM_ID" access="field">
        <generator class="native" />
    </id>
</class>

现在效果非常好。要将订单项添加到订单,例如在Spring Controller方法中,我可以用简单而干净的方式完成:

Order order = orderRepository.findById(orderId);
OrderItem item = new OrderItem();
order.add(item);

完成。我甚至在我的Bean定义文件中设置了OpenSessionInViewInterceptor,因此一旦控制器方法完成,订单项就会被保留。

问题是我想立即调用item.getId(),但是当order.add(item)方法返回时,事务尚未提交,并返回零。最佳实践似乎是创建一个事务服务方法,我这样做:

Order order = orderRepository.findById(orderId);
OrderItem item = new OrderItem();
orderService.addItem(order, item)

现在item.getId()立即返回生成的ID。

我遇到的问题是除了将orderService.addItem方法包装在事务中之外,order.add(item)方法没有用处。我想知道如何摆脱它。

我的问题是,我怎样才能使order.add(item)方法成为交易?

我看到它的唯一方法是,与Hibernate会话交互的orderRepository必须返回一个Spring AOP或AspectJ代理,我的add(item)方法可以在我的Bean定义文件中声明为事务性。

我如何能够返回这样的Spring托管代理订单?我可以通过覆盖Hibernate的Interceptor.onLoad方法来实现吗?

还有其他方法可以使订单(具体实现)与Spring Transaction Advisor相关联吗?

我知道我实现的服务可能是最实用的解决方案,但我真的很想知道如何将AOP建议附加到Hibernate持久化POJO实体。

1 个答案:

答案 0 :(得分:2)

您正在寻找的是"Using AspectJ to dependency inject domain objects with Spring"。我在github上提供了build-timeload-time编织的可执行示例。