【问题标题】:Cannot remove a JPA entity using Spring Integration无法使用 Spring Integration 删除 JPA 实体
【发布时间】:2013-10-07 17:37:14
【问题描述】:

当我尝试使用出站通道适配器删除实体时,我总是会删除分离的实例异常。 我知道应该在同一个事务中检索和删除一个实体以避免这个异常,但是如何使用 Spring Integration 来实现呢?

为了演示我修改the JPA sample的问题:

PersonService.java

public interface PersonService {
    ...
    void deletePerson(Person person);
}

Main.java

private static void deletePerson(final PersonService service) {
    final List<Person> people = service.findPeople();
    Person p1 = people.get(0);
    service.deletePerson(p1);
}

spring-integration-context.xml

<int:gateway id="personService"
service-interface="org.springframework.integration.samples.jpa.service.PersonService"
    default-request-timeout="5000" default-reply-timeout="5000">
    <int:method name="createPerson" request-channel="createPersonRequestChannel"/>
    <int:method name="findPeople"   request-channel="listPeopleRequestChannel"/>
    <int:method name="deletePerson" request-channel="deletePersonChannel"/>
</int:gateway>

<int:channel id="deletePersonChannel"/>

<int-jpa:outbound-channel-adapter entity-manager-factory="entityManagerFactory"
channel="deletePersonChannel" persist-mode="DELETE" >
    <int-jpa:transactional transaction-manager="transactionManager" />
</int-jpa:outbound-channel-adapter>

当我调用 deletePerson 时,我得到了异常:

线程“主”java.lang.IllegalArgumentException 中的异常: 删除分离的实例 org.springframework.integration.samples.jpa.Person#1001

更新:

显然我应该选择一个更接近我实际项目的示例,因为在这里您可以像 Artem 那样以编程方式创建一个新事务并在其中包装检索和删除函数调用。

在我的项目中,我有一个连接到出站通道适配器的变压器。转换器检索一个实体,出站通道适配器将其删除。在这种情况下,如何让转换器和出站通道适配器使用相同的事务?

【问题讨论】:

    标签: jpa spring-integration


    【解决方案1】:

    要使其正常工作,您应该将 deletePerson 中的所有操作包装到事务中,例如

    private static void deletePerson(final PersonService service) {
             new new TransactionTemplate(transactionManager)
           .execute(new TransactionCallbackWithoutResult() {
    
                protected void doInTransactionWithoutResult(TransactionStatus status) {
                     final List<Person> people = service.findPeople();
                     Person p1 = people.get(0);
                     service.deletePerson(p1);
    
                }
            });
    }
    

    在这种情况下,您也应该以某种方式向您的方法提供 transactionManager bean。

    更新:

    我在原始问题中向您展示了一个用例示例。 现在重新。 &lt;transformer&gt; -> &lt;jpa:outbound-channel-adapter&gt;。 在此您应该了解您的消息流从哪里开始:

    1. 如果是带有轮询器的&lt;inbound-channel-adapter&gt;,那么只需将&lt;poller&gt;&lt;transactional&gt;
    2. 如果是&lt;gateway&gt;,谁调用&lt;transformer&gt;,那么用@Transactional标记网关的方法就够了
    3. 这里还有一个交易建议技巧:Keep transaction within Spring Integration flow

    在所有情况下,您都应该从您的 &lt;jpa:outbound-channel-adapter&gt; 中删除 &lt;transactional&gt;

    【讨论】:

    • 感谢 Artem,它成功了,但是有什么方法可以通过 xml 来实现吗?
    • 再次感谢,#3 帮助了我。关于#1 和#2 的事情是我不想让整个流程成为事务性的。在我的情况下,流程从 tcp-inbound-channel-adapter 开始。在变压器之前,我有一个路由器来决定要执行哪个 jpa 操作。如果它决定删除,它会向转换器发送一条消息,只有它将有效负载转换为实体并将其发送到 jpa outbound-channel-adapter 以进行删除。
    猜你喜欢
    • 2011-07-17
    • 1970-01-01
    • 2015-11-07
    • 1970-01-01
    • 2019-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多