Inbound Channel Adapter

入站通道适配器用于使用 JPA QL 执行数据库选择查询并返回结果。消息有效负载可以是单个实体或实体的`List`。以下 XML 配置一个`inbound-channel-adapter`:

<int-jpa:inbound-channel-adapter channel="inboundChannelAdapterOne"  1
                    entity-manager="em"                              2
                    auto-startup="true"                              3
                    query="select s from Student s"                  4
                    expect-single-result="true"                      5
                    max-results=""                                   6
                    max-results-expression=""                        7
                    delete-after-poll="true"                         8
                    flush-after-delete="true">                       9
    <int:poller fixed-rate="2000" >
      <int:transactional propagation="REQUIRED" transaction-manager="transactionManager"/>
    </int:poller>
</int-jpa:inbound-channel-adapter>
1 在 `query`属性中执行 JPA QL 后,`inbound-channel-adapter`放置消息(包含有效内容)的通道。
2 用于执行必需 JPA 操作的 `EntityManager`实例。
3 一个属性,表示组件在应用程序上下文启动时是否应该自动启动。该值默认为 true.
4 其结果作为消息有效内容发送的 JPA QL
5 此属性表示 JPQL 查询在结果中给出一个实体还是一个实体的 List。如果值设置为 true,则将单个实体作为消息的有效内容发送。然而,如果在将此值设置为 true`后返回多个结果,则会抛出 `MessagingException。该值默认为 false.
6 此非零、非负整数值告诉适配器在执行选择操作时不要选择超过给定数量的行。默认情况下,如果未设置此属性,查询将选择所有可能的记录。此属性与 `max-results-expression`互斥。可选。
7 一个在结果集中查找最大结果数量的表达式。与 `max-results`互斥。可选。
8 如果您希望在执行查询后删除接收到的行,请将该值设置为 true。您必须确保组件作为事务的一部分进行操作。否则,您可能会遇到诸如: `java.lang.IllegalArgumentException: Removing a detached instance …​`之类的异常。
9 如果您想在删除接收到的实体后立即刷新持久化上下文并且不想依赖 EntityManager`的 `flushMode`时,请将该值设置为 `true。该值默认为 false.

Configuration Parameter Reference

以下清单显示了可以为`inbound-channel-adapter`设置的所有值:

<int-jpa:inbound-channel-adapter
  auto-startup="true"           1
  channel=""                    2
  delete-after-poll="false"     3
  delete-per-row="false"        4
  entity-class=""               5
  entity-manager=""             6
  entity-manager-factory=""     7
  expect-single-result="false"  8
  id=""
  jpa-operations=""             9
  jpa-query=""                  10
  named-query=""                11
  native-query=""               12
  parameter-source=""           13
  send-timeout="">              14
  <int:poller ref="myPoller"/>
 </int-jpa:inbound-channel-adapter>
1 此生命周期属性表示此组件在应用程序上下文启动时是否应该自动启动。此属性默认为 true.可选。
2 适配器使用执行所需的 JPA 操作产生的有效内容向其发送一条消息的通道。
3 一个布尔标志,表示在适配器轮询到所选记录后是否将其删除。默认情况下,值为 false(即不删除记录)。您必须确保组件作为事务的一部分进行操作。否则,您可能会遇到诸如: `java.lang.IllegalArgumentException: Removing a detached instance &#8230;&#8203;`之类的异常。可选。
4 指示记录可批量删除还是必须一次删除一条记录的布尔标志。默认情况下,值为 false (即,记录可以批量删除)。可选。
5 要从数据库中查询的实体类的完全限定名。适配器会根据实体类名自动构建一个 JPA 查询。可选。
6 用于执行 JPA 操作的 jakarta.persistence.EntityManager 实例。可选。
7 用于获取执行 JPA 操作的 jakarta.persistence.EntityManager 实例的 jakarta.persistence.EntityManagerFactory 实例。可选。
8 指示选择操作预计会返回单个结果还是 List 结果的布尔标志。如果将此标志设置为 true,则所选的单个实体将作为消息的有效负载发送。如果返回多个实体,则会引发异常。如果为 false,则将 List 实体作为消息的有效负载发送。该值默认为 false。可选。
9 用于执行 JPA 操作的 org.springframework.integration.jpa.core.JpaOperations 实现。我们建议不要提供自己的实现,而使用默认的 org.springframework.integration.jpa.core.DefaultJpaOperations 实现。您可以使用任何 entity-managerentity-manager-factoryjpa-operations 属性。可选。
10 此适配器执行的 JPA QL。可选。
11 此适配器需要执行的命名查询。可选。
12 此适配器执行的原生查询。您可以使用任何 jpa-querynamed-queryentity-classnative-query 属性。可选。
13 用于解析查询中参数值的 o.s.i.jpa.support.parametersource.ParameterSource 实现。如果 entity-class 属性具有一定值,则此实现将被忽略。可选。
14 向通道发送消息时等待的最长时间(以毫秒为单位)。可选。

Configuring with Java Configuration

以下 Spring Boot 应用程序展示了如何使用 Java 配置入站适配器的示例:

@SpringBootApplication
@EntityScan(basePackageClasses = StudentDomain.class)
public class JpaJavaApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(JpaJavaApplication.class)
            .web(false)
            .run(args);
    }

    @Autowired
    private EntityManagerFactory entityManagerFactory;

    @Bean
    public JpaExecutor jpaExecutor() {
        JpaExecutor executor = new JpaExecutor(this.entityManagerFactory);
        jpaExecutor.setJpaQuery("from Student");
        return executor;
    }

    @Bean
    @InboundChannelAdapter(channel = "jpaInputChannel",
                     poller = @Poller(fixedDelay = "${poller.interval}"))
    public MessageSource<?> jpaInbound() {
        return new JpaPollingChannelAdapter(jpaExecutor());
    }

    @Bean
    @ServiceActivator(inputChannel = "jpaInputChannel")
    public MessageHandler handler() {
        return message -> System.out.println(message.getPayload());
    }

}

Configuring with the Java DSL

以下 Spring Boot 应用程序展示了如何使用 Java DSL 配置入站适配器的示例:

@SpringBootApplication
@EntityScan(basePackageClasses = StudentDomain.class)
public class JpaJavaApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(JpaJavaApplication.class)
            .web(false)
            .run(args);
    }

    @Autowired
    private EntityManagerFactory entityManagerFactory;

    @Bean
    public IntegrationFlow pollingAdapterFlow() {
        return IntegrationFlow
            .from(Jpa.inboundAdapter(this.entityManagerFactory)
                        .entityClass(StudentDomain.class)
                        .maxResults(1)
                        .expectSingleResult(true),
                e -> e.poller(p -> p.trigger(new OnlyOnceTrigger())))
            .channel(c -> c.queue("pollingResults"))
            .get();
    }

}