У меня есть отношения родитель-потомок, такие как Порядок заказа, который я представил в модели предметной области следующим образом:
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);
Готово. Я даже настроил OpenSessionInViewInterceptor в своем файле определения компонента, поэтому, как только метод контроллера завершится, элемент заказа будет сохранен.
Проблема в том, что я хотел бы сразу вызвать item.getId()
, но когда метод order.add(item)
возвращается, транзакция еще не зафиксирована, и возвращается ноль. Лучше всего создается метод транзакционного сервиса, и я сделал это так:
Order order = orderRepository.findById(orderId);
OrderItem item = new OrderItem();
orderService.addItem(order, item)
Теперь item.getId()
сразу возвращает сгенерированный идентификатор.
Проблема, с которой я столкнулся, заключается в том, что метод orderService.addItem
не служит никакой другой цели, кроме как обернуть метод order.add(item)
в транзакцию. Я хотел бы знать, как я могу избавиться от этого.
Мой вопрос: как я могу сделать метод order.add(item)
транзакционным?
Единственный способ, которым я это вижу, это то, что orderRepository, взаимодействующий с сеансом Hibernate, должен возвращать прокси Spring AOP или AspectJ, чей метод add(item)
я могу объявить как транзакционный в моем файле определения компонента.
Как я могу вернуть такой заказ Spring-прокси? Могу ли я сделать это путем переопределения метода Interceptor.onLoad
в Hibernate?
Есть ли другой способ сделать Order, конкретную реализацию, связанным с Spring Transaction Advisor?
Я знаю, что реализованный мною сервис, вероятно, является наиболее практичным решением, но мне действительно любопытно узнать, как я могу подключить AOP Advice к персистентному объекту POJO в Hibernate.