开发者

Spring AOP Advice for Hibernate managed POJO

开发者 https://www.devze.com 2023-04-10 19:35 出处:网络
I have a parent-child relationship, such as Order to Order Item, which I have represented in the domain model like this:

I have a parent-child relationship, such as Order to Order Item, which I have represented in the domain model like this:

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;
    }

}

I am persisting these entities with Hibern开发者_运维问答ate, using a mapping like this:

<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>

This is working very nicely now. To add an Order Item to an Order, for example in a Spring Controller method, I can do it in a simple and clean way:

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

Done. I even set-up the OpenSessionInViewInterceptor in my Bean Definition file, so as soon as the controller method completes, the Order Item is persisted.

The issue is I would like to call item.getId() right away, but when the order.add(item) method returns, the transaction has not yet been commited, and zero is returned. The best practice seems to be creating a transactional service method, and I did it like this:

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

Now item.getId() returns the generated ID right away.

The issue I have is the orderService.addItem method serves no purpose other than to wrap the order.add(item) method in a transaction. I would like to know how I can get rid of it.

My question is, how can I possibly make the order.add(item) method transactional?

The only way I see it, the orderRepository interacting with the Hibernate session must return a Spring AOP or AspectJ proxy, whose add(item) method I can declare as transactional in my Bean Definition file.

How would I be able to return such a Spring managed proxy Order? Can I do it by overriding Hibernate's Interceptor.onLoad method?

Is there any other way to make the Order, a concrete implementation, be associated with a Spring Transaction Advisor?

I know the service I implemented is probably the most practical solution, but I am really curious to know how I can attach AOP Advice to a Hibernate persisted POJO entity.


What you're looking for is "Using AspectJ to dependency inject domain objects with Spring". I have executable examples of both build-time and load-time weaving available on github.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号