|
此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.4! |
|
此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring Integration 6.3.4! |
JPA 出站通道适配器允许您通过请求通道接受消息。 有效负载可以用作要保留的实体,也可以与 JPQL 查询的参数表达式中的标头一起使用。 以下部分介绍了执行这些操作的可能方法。
使用 Entity 类
以下 XML 将出站通道适配器配置为将实体持久保存到数据库:
<int-jpa:outbound-channel-adapter channel="entityTypeChannel" (1)
entity-class="org.springframework.integration.jpa.test.entity.Student" (2)
persist-mode="PERSIST" (3)
entity-manager="em"/ > (4)
| 1 | 将有效 JPA 实体发送到 JPA 出站通道适配器的通道。 |
| 2 | 适配器接受的实体类的完全限定名称,以保留在数据库中。 实际上,在大多数情况下,你可以省略这个属性,因为适配器可以从 Spring Integration 消息有效负载中自动确定实体类。 |
| 3 | 适配器要执行的操作。
有效值为 、 和 。
默认值为 .PERSISTMERGEDELETEMERGE |
| 4 | 要使用的 JPA 实体管理器。 |
的这四个属性将其配置为通过输入渠道接受实体,并将其处理为 、 或基础数据源中的实体。outbound-channel-adapterPERSISTMERGEDELETE
从 Spring Integration 3.0 开始,payloads to 或 也可以是 type .
在这种情况下,返回的每个对象都被视为一个实体,并使用底层 .
迭代器返回的 Null 值将被忽略。PERSISTMERGEjava.lang.IterableIterableEntityManager |
从版本 5.5.4 开始,配置了 的 可以接受有效负载,以便对提供的实体执行批量删除持久操作。JpaOutboundGatewayJpaExecutorPersistMode.DELETEIterable |
| 1 | 将有效 JPA 实体发送到 JPA 出站通道适配器的通道。 |
| 2 | 适配器接受的实体类的完全限定名称,以保留在数据库中。 实际上,在大多数情况下,你可以省略这个属性,因为适配器可以从 Spring Integration 消息有效负载中自动确定实体类。 |
| 3 | 适配器要执行的操作。
有效值为 、 和 。
默认值为 .PERSISTMERGEDELETEMERGE |
| 4 | 要使用的 JPA 实体管理器。 |
从 Spring Integration 3.0 开始,payloads to 或 也可以是 type .
在这种情况下,返回的每个对象都被视为一个实体,并使用底层 .
迭代器返回的 Null 值将被忽略。PERSISTMERGEjava.lang.IterableIterableEntityManager |
从版本 5.5.4 开始,配置了 的 可以接受有效负载,以便对提供的实体执行批量删除持久操作。JpaOutboundGatewayJpaExecutorPersistMode.DELETEIterable |
使用 JPA 查询语言 (JPA QL)
上一节介绍了如何使用实体执行操作。
本节介绍如何将出站通道适配器与 JPA QL 一起使用。PERSIST
以下 XML 将出站通道适配器配置为将实体持久保存到数据库:
<int-jpa:outbound-channel-adapter channel="jpaQlChannel" (1)
jpa-query="update Student s set s.firstName = :firstName where s.rollNumber = :rollNumber" (2)
entity-manager="em"> (3)
<int-jpa:parameter name="firstName" expression="payload['firstName']"/> (4)
<int-jpa:parameter name="rollNumber" expression="payload['rollNumber']"/>
</int-jpa:outbound-channel-adapter>
| 1 | 将消息发送到出站通道适配器的 input 通道。 |
| 2 | 要执行的 JPA QL。
此查询可能包含使用 element 计算的参数。parameter |
| 3 | 适配器用于执行 JPA 操作的实体管理器。 |
| 4 | 用于定义属性中指定的 JPA QL 的参数名称值的元素(每个参数一个)。query |
该元素接受一个属性,该属性对应于提供的 JPA QL 中指定的命名参数(前面示例中的第 2 点)。
参数的值可以是 static,也可以是使用表达式派生的。
static 值和用于派生值的表达式分别使用 和 属性指定。
这些属性是互斥的。parameternamevalueexpression
如果指定了该属性,则可以提供 optional 属性。
此属性的值是其值由该属性表示的类的完全限定名称。
默认情况下,类型假定为 .
以下示例显示如何定义 JPA 参数:valuetypevaluejava.lang.String
<int-jpa:outbound-channel-adapter ...
>
<int-jpa:parameter name="level" value="2" type="java.lang.Integer"/>
<int-jpa:parameter name="name" expression="payload['name']"/>
</int-jpa:outbound-channel-adapter>
如前面的示例所示,您可以在出站通道适配器元素中使用多个元素,并使用表达式和其他具有静态值的参数来定义一些参数。
但是,请注意不要多次指定相同的参数名称。
您应该为 JPA 查询中指定的每个命名参数提供一个元素。
例如,我们指定两个参数: 和 .
该属性是 type 的 static 值,而该属性派生自消息的有效负载。parameterparameterlevelnameleveljava.lang.Integername
尽管指定对 JPA QL 有效,但这样做没有意义。
出站通道适配器不返回任何结果。
如果要选择一些值,请考虑改用出站网关。select |
| 1 | 将消息发送到出站通道适配器的 input 通道。 |
| 2 | 要执行的 JPA QL。
此查询可能包含使用 element 计算的参数。parameter |
| 3 | 适配器用于执行 JPA 操作的实体管理器。 |
| 4 | 用于定义属性中指定的 JPA QL 的参数名称值的元素(每个参数一个)。query |
尽管指定对 JPA QL 有效,但这样做没有意义。
出站通道适配器不返回任何结果。
如果要选择一些值,请考虑改用出站网关。select |
使用本机查询
本节介绍如何使用本机查询对 JPA 出站通道适配器执行操作。 使用本机查询与使用 JPA QL 类似,不同之处在于查询是本机数据库查询。 通过使用本机查询,我们失去了使用 JPA QL 获得的数据库供应商独立性。
通过使用本机查询,我们可以实现的一件事是执行数据库插入,这在 JPA QL 中是不可能的。 (为了执行插入,我们将 JPA 实体发送到通道适配器,如前所述)。 下面是一个小的 xml 片段,它演示了如何使用本机查询在表中插入值。
| 您的 JPA 提供程序可能不支持将命名参数与本机 SQL 查询结合使用。 虽然它们与 Hibernate 一起工作良好,但 OpenJPA 和 EclipseLink 不支持它们。 请参阅 issues.apache.org/jira/browse/OPENJPA-111。 JPA 2.0 规范的第 3.8.12 节规定:“只有位置参数绑定和对结果项的位置访问可以移植地用于本机查询。 |
以下示例使用本机查询配置 outbound-channel-adapter:
<int-jpa:outbound-channel-adapter channel="nativeQlChannel"
native-query="insert into STUDENT_TABLE(FIRST_NAME,LAST_UPDATED) values (:lastName,:lastUpdated)" (1)
entity-manager="em">
<int-jpa:parameter name="lastName" expression="payload['updatedLastName']"/>
<int-jpa:parameter name="lastUpdated" expression="new java.util.Date()"/>
</int-jpa:outbound-channel-adapter>
| 1 | 此出站通道适配器执行的本机查询。 |
请注意,其他属性(如 和 )和元素具有与 JPA QL 相同的语义。channelentity-managerparameter
| 您的 JPA 提供程序可能不支持将命名参数与本机 SQL 查询结合使用。 虽然它们与 Hibernate 一起工作良好,但 OpenJPA 和 EclipseLink 不支持它们。 请参阅 issues.apache.org/jira/browse/OPENJPA-111。 JPA 2.0 规范的第 3.8.12 节规定:“只有位置参数绑定和对结果项的位置访问可以移植地用于本机查询。 |
| 1 | 此出站通道适配器执行的本机查询。 |
使用命名查询
使用命名查询与使用 JPA QL 或本机查询类似,不同之处在于我们指定命名查询而不是查询。
首先,我们将介绍如何定义 JPA 命名查询。
然后,我们将介绍如何声明出站通道适配器以使用命名查询。
如果我们有一个名为 的实体,我们可以在类上使用注释来定义两个命名查询:和 。
以下示例显示了如何执行此操作:StudentStudentselectStudentupdateStudent
@Entity
@Table(name="Student")
@NamedQueries({
@NamedQuery(name="selectStudent",
query="select s from Student s where s.lastName = 'Last One'"),
@NamedQuery(name="updateStudent",
query="update Student s set s.lastName = :lastName,
lastUpdated = :lastUpdated where s.id in (select max(a.id) from Student a)")
})
public class Student {
...
}
或者,您可以使用 orm.xml 来定义命名查询,如下例所示:
<entity-mappings ...>
...
<named-query name="selectStudent">
<query>select s from Student s where s.lastName = 'Last One'</query>
</named-query>
</entity-mappings>
现在,我们已经展示了如何使用 annotations 或 using 来定义命名查询,现在我们展示一个小的 XML 片段,该片段使用命名查询定义 ,如下例所示:orm.xmloutbound-channel-adapter
<int-jpa:outbound-channel-adapter channel="namedQueryChannel"
named-query="updateStudent" (1)
entity-manager="em">
<int-jpa:parameter name="lastName" expression="payload['updatedLastName']"/>
<int-jpa:parameter name="lastUpdated" expression="new java.util.Date()"/>
</int-jpa:outbound-channel-adapter>
| 1 | 我们希望适配器在通过通道接收消息时执行的命名查询。 |
| 1 | 我们希望适配器在通过通道接收消息时执行的命名查询。 |
配置参数参考
下面的清单显示了您可以在出站通道适配器上设置的所有属性:
<int-jpa:outbound-channel-adapter
auto-startup="true" (1)
channel="" (2)
entity-class="" (3)
entity-manager="" (4)
entity-manager-factory="" (5)
id=""
jpa-operations="" (6)
jpa-query="" (7)
named-query="" (8)
native-query="" (9)
order="" (10)
parameter-source-factory="" (11)
persist-mode="MERGE" (12)
flush="true" (13)
flush-size="10" (14)
clear-on-flush="true" (15)
use-payload-as-parameter-source="true" (16)
<int:poller/>
<int-jpa:transactional/> (17)
<int-jpa:parameter/> (18)
</int-jpa:outbound-channel-adapter>
| 1 | 生命周期属性指示此组件是否应在应用程序上下文启动期间启动。
它默认为 .
自选。true |
| 2 | 出站适配器从中接收消息以执行所需操作的通道。 |
| 3 | JPA Operation 的实体类的完全限定名称。
、 和 属性是互斥的。
自选。entity-classquerynamed-query |
| 4 | 用于执行 JPA 操作的实例。
自选。jakarta.persistence.EntityManager |
| 5 | 用于获取 的实例 的实例,该实例执行 JPA 操作。
自选。jakarta.persistence.EntityManagerFactoryjakarta.persistence.EntityManager |
| 6 | 用于执行 JPA 操作的实现。
我们建议不要提供您自己的实现,而是使用默认实现。
您可以使用 、 或 属性中的任何一个。
自选。org.springframework.integration.jpa.core.JpaOperationsorg.springframework.integration.jpa.core.DefaultJpaOperationsentity-managerentity-manager-factoryjpa-operations |
| 7 | 要由此适配器执行的 JPA QL。 自选。 |
| 8 | 需要由此适配器执行的命名查询。 自选。 |
| 9 | 此适配器要执行的本机查询。
您可以使用 、 或 属性中的任何一个。
自选。jpa-querynamed-querynative-query |
| 10 | 注册多个使用者时此使用者的顺序,从而管理负载均衡和故障转移。
它默认为 .
自选。Ordered.LOWEST_PRECEDENCE |
| 11 | 的实例 用于获取 的实例 ,用于解析查询中参数的值。
如果您使用 JPA 实体执行操作,则忽略。
子元素与属性互斥,必须在提供的 .
自选。o.s.i.jpa.support.parametersource.ParameterSourceFactoryo.s.i.jpa.support.parametersource.ParameterSourceparameterparameter-source-factoryParameterSourceFactory |
| 12 | 接受以下选项之一: , , 或 .
指示适配器需要执行的操作。
仅当您将实体用于 JPA 操作时才相关。
如果您提供 JPA QL、命名查询或本机查询,则忽略。
它默认为 .
自选。
从 Spring Integration 3.0 开始,要 persist 或 merge 的有效负载也可以是 type 。
在这种情况下,返回的每个对象都被视为一个实体,并使用基础 .
迭代器返回的 Null 值将被忽略。PERSISTMERGEDELETEMERGEjava.lang.IterableIterableEntityManager |
| 13 | 如果要在执行 persist、merge 或 delete 操作后立即刷新持久性上下文,并且不想依赖 的 ,请将此值设置为 .
它默认为 .
仅在未指定属性时适用。
如果此属性设置为 ,则隐式设置为 ,如果没有其他值对其进行配置。trueflushModeEntityManagerfalseflush-sizetrueflush-size1 |
| 14 | 如果要在执行持久化、合并或删除操作后立即刷新持久性上下文,并且不想依赖 .
默认值设置为 ,这意味着 “'no flush'”。
此属性适用于具有有效负载的消息。
例如,如果设置为 ,则在每三个实体之后调用一次。
此外,在整个循环之后再次调用。
如果 'flush-size' 属性指定的值大于 '0',则无需配置该属性。flushModeEntityManager0Iterableflush-size3entityManager.flush()entityManager.flush()flush |
| 15 | 如果要在每次刷新操作后立即清除持久性上下文,请将此值设置为 'true'。
仅当属性设置为 或属性设置为大于 的值时,才会应用该属性的值。flushtrueflush-size0 |
| 16 | 如果设置为 ,则消息的有效负载将用作参数的源。
但是,如果设置为 ,则 entire 可用作参数的源。
自选。truefalseMessage |
| 17 | 定义事务管理属性和对 JPA 适配器要使用的事务管理器的引用。 自选。 |
| 18 | 一个或多个属性 — 查询中使用的每个参数对应一个属性。
计算值或表达式以计算参数的值。
自选。parameter |
| 1 | 生命周期属性指示此组件是否应在应用程序上下文启动期间启动。
它默认为 .
自选。true |
| 2 | 出站适配器从中接收消息以执行所需操作的通道。 |
| 3 | JPA Operation 的实体类的完全限定名称。
、 和 属性是互斥的。
自选。entity-classquerynamed-query |
| 4 | 用于执行 JPA 操作的实例。
自选。jakarta.persistence.EntityManager |
| 5 | 用于获取 的实例 的实例,该实例执行 JPA 操作。
自选。jakarta.persistence.EntityManagerFactoryjakarta.persistence.EntityManager |
| 6 | 用于执行 JPA 操作的实现。
我们建议不要提供您自己的实现,而是使用默认实现。
您可以使用 、 或 属性中的任何一个。
自选。org.springframework.integration.jpa.core.JpaOperationsorg.springframework.integration.jpa.core.DefaultJpaOperationsentity-managerentity-manager-factoryjpa-operations |
| 7 | 要由此适配器执行的 JPA QL。 自选。 |
| 8 | 需要由此适配器执行的命名查询。 自选。 |
| 9 | 此适配器要执行的本机查询。
您可以使用 、 或 属性中的任何一个。
自选。jpa-querynamed-querynative-query |
| 10 | 注册多个使用者时此使用者的顺序,从而管理负载均衡和故障转移。
它默认为 .
自选。Ordered.LOWEST_PRECEDENCE |
| 11 | 的实例 用于获取 的实例 ,用于解析查询中参数的值。
如果您使用 JPA 实体执行操作,则忽略。
子元素与属性互斥,必须在提供的 .
自选。o.s.i.jpa.support.parametersource.ParameterSourceFactoryo.s.i.jpa.support.parametersource.ParameterSourceparameterparameter-source-factoryParameterSourceFactory |
| 12 | 接受以下选项之一: , , 或 .
指示适配器需要执行的操作。
仅当您将实体用于 JPA 操作时才相关。
如果您提供 JPA QL、命名查询或本机查询,则忽略。
它默认为 .
自选。
从 Spring Integration 3.0 开始,要 persist 或 merge 的有效负载也可以是 type 。
在这种情况下,返回的每个对象都被视为一个实体,并使用基础 .
迭代器返回的 Null 值将被忽略。PERSISTMERGEDELETEMERGEjava.lang.IterableIterableEntityManager |
| 13 | 如果要在执行 persist、merge 或 delete 操作后立即刷新持久性上下文,并且不想依赖 的 ,请将此值设置为 .
它默认为 .
仅在未指定属性时适用。
如果此属性设置为 ,则隐式设置为 ,如果没有其他值对其进行配置。trueflushModeEntityManagerfalseflush-sizetrueflush-size1 |
| 14 | 如果要在执行持久化、合并或删除操作后立即刷新持久性上下文,并且不想依赖 .
默认值设置为 ,这意味着 “'no flush'”。
此属性适用于具有有效负载的消息。
例如,如果设置为 ,则在每三个实体之后调用一次。
此外,在整个循环之后再次调用。
如果 'flush-size' 属性指定的值大于 '0',则无需配置该属性。flushModeEntityManager0Iterableflush-size3entityManager.flush()entityManager.flush()flush |
| 15 | 如果要在每次刷新操作后立即清除持久性上下文,请将此值设置为 'true'。
仅当属性设置为 或属性设置为大于 的值时,才会应用该属性的值。flushtrueflush-size0 |
| 16 | 如果设置为 ,则消息的有效负载将用作参数的源。
但是,如果设置为 ,则 entire 可用作参数的源。
自选。truefalseMessage |
| 17 | 定义事务管理属性和对 JPA 适配器要使用的事务管理器的引用。 自选。 |
| 18 | 一个或多个属性 — 查询中使用的每个参数对应一个属性。
计算值或表达式以计算参数的值。
自选。parameter |
使用 Java 配置进行配置
Spring 下面的 Boot 应用程序显示了如何使用 Java 配置出站适配器的示例:
@SpringBootApplication
@EntityScan(basePackageClasses = StudentDomain.class)
@IntegrationComponentScan
public class JpaJavaApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(JpaJavaApplication.class)
.web(false)
.run(args);
}
@Autowired
private EntityManagerFactory entityManagerFactory;
@MessagingGateway
interface JpaGateway {
@Gateway(requestChannel = "jpaPersistChannel")
@Transactional
void persistStudent(StudentDomain payload);
}
@Bean
public JpaExecutor jpaExecutor() {
JpaExecutor executor = new JpaExecutor(this.entityManagerFactory);
jpaExecutor.setEntityClass(StudentDomain.class);
jpaExecutor.setPersistMode(PersistMode.PERSIST);
return executor;
}
@Bean
@ServiceActivator(channel = "jpaPersistChannel")
public MessageHandler jpaOutbound() {
JpaOutboundGateway adapter = new JpaOutboundGateway(jpaExecutor());
adapter.setProducesReply(false);
return adapter;
}
}
使用 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 outboundAdapterFlow() {
return f -> f
.handle(Jpa.outboundAdapter(this.entityManagerFactory)
.entityClass(StudentDomain.class)
.persistMode(PersistMode.PERSIST),
e -> e.transactional());
}
}