入站通道适配器

入站通道适配器用于使用 JPA QL 在数据库上执行 select 查询并返回结果。 消息负载可以是单个实体,也可以是实体的 List。 以下 XML 配置了一个 inbound-channel-adapter

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

配置参数参考

以下列表显示了 inbound-channel-adapter 可以设置的所有值:

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

使用 Java 配置

以下 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());
    }

}

使用 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();
    }

}