【问题标题】:Spring AOP Advice for Hibernate managed POJO针对 Hibernate 托管 POJO 的 Spring AOP 建议
【发布时间】:2011-10-05 23:40:58
【问题描述】:

我有一个父子关系,例如订单到订单项,我在域模型中表示如下:

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>

现在效果很好。要将 Order Item 添加到 Order 中,例如在 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 代理,我可以在我的 Bean 定义文件中将其 add(item) 方法声明为事务性。

我如何才能返回这样的 Spring 托管代理订单?我可以通过覆盖 Hibernate 的 Interceptor.onLoad 方法来做到这一点吗?

有没有其他方法可以让 Order(一个具体的实现)与 Spring Transaction Advisor 相关联?

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

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

    • The support is intended to be used for objects created outside of the control of any container. Domain objects often fall into this category because they are often created programmatically using the new operator, or by an ORM tool as a result of a database query. -- 就是这样。我找不到使用 @Configurable 属性的任何替代方法。有什么方法可以从目标类外部声明它?
    • "Other Spring aspects for AspectJ" 简要提到了一种无需注释的方法。我自己从未尝试过,但看起来很简单。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多