此版本仍在开发中,尚未被视为稳定版本。对于最新的稳定版本,请使用 Spring LDAP 3.2.8! |
事务支持
习惯于使用关系数据库进入 LDAP 世界的程序员经常对没有事务概念的事实表示惊讶。 协议中未指定它,并且没有 LDAP 服务器支持它。 认识到这可能是一个主要问题, Spring LDAP 提供了对 Client 端的支持,补偿 LDAP 资源上的事务。
LDAP 事务支持由ContextSourceTransactionManager
一个PlatformTransactionManager
管理 Spring 事务对 LDAP作的支持的实现。它与协作者一起跟踪事务中执行的 LDAP作,在每次作之前记录状态,并在事务需要回滚时采取措施恢复初始状态。
除了实际的事务管理之外, Spring LDAP 事务支持还确保相同的DirContext
instance 在整个事务中使用。也就是说,DirContext
在事务完成之前实际上不会关闭,从而可以更高效地使用资源。
虽然 Spring LDAP 用来提供事务支持的方法在许多情况下就足够了,但它绝不是传统意义上的“真正的”事务。 服务器完全不知道事务,因此(例如),如果连接断开,则无法回滚事务。 虽然应该仔细考虑这一点,但也应该注意,另一种选择是在没有任何交易支持的情况下运行。Spring LDAP 的事务支持几乎是最好的。 |
除了原始作所需的工作之外,客户端事务支持还增加了一些开销。
虽然在大多数情况下,这种开销不应该是一件需要担心的事情,
如果您的应用程序没有在同一事务中执行多个 LDAP作(例如,modifyAttributes 其次rebind ),
或者,如果不需要与 JDBC 数据源进行事务同步(请参阅 JDBC 事务集成),则使用 LDAP 事务支持几乎没有什么好处。 |
配置
如果您习惯于配置 Spring 事务,那么配置 Spring LDAP 事务应该看起来非常熟悉。您可以使用@Transactional
,创建一个TransactionManager
实例,并包含一个<tx:annotation-driven>
元素。以下示例显示了如何执行此作:
<ldap:context-source
url="ldap://localhost:389"
base="dc=example,dc=com"
username="cn=Manager"
password="secret" />
<ldap:ldap-template id="ldapTemplate" />
<ldap:transaction-manager>
<!--
Note this default configuration will not work for more complex scenarios;
see below for more information on RenamingStrategies.
-->
<ldap:default-renaming-strategy />
</ldap:transaction-manager>
<!--
The MyDataAccessObject class is annotated with @Transactional.
-->
<bean id="myDataAccessObject" class="com.example.MyRepository">
<property name="ldapTemplate" ref="ldapTemplate" />
</bean>
<tx:annotation-driven />
...
虽然此设置适用于大多数简单的使用案例,但一些更复杂的场景需要额外的配置。
具体来说,如果需要在事务中创建或删除子树,则需要使用替代方法TempEntryRenamingStrategy ,如 重命名策略中所述。 |
在实际情况下,您可能会在服务对象级别而不是存储库级别应用事务。前面的示例演示了一般思路。
JDBC 事务集成
使用 LDAP 时的一个常见用例是,某些数据存储在 LDAP 树中,但其他数据存储在关系数据库中。在这种情况下,事务支持变得更加重要,因为不同资源的更新应该同步。
虽然不支持实际的 XA 事务,但通过提供data-source-ref
属性设置为<ldap:transaction-manager>
元素。这将创建一个ContextSourceAndDataSourceTransactionManager
,然后,它几乎像管理一个事务一样管理这两个事务。执行提交时,始终首先执行作的 LDAP 部分,如果 LDAP 提交失败,则允许回滚两个事务。事务的 JDBC 部分的管理方式与DataSourceTransactionManager
,但不支持嵌套事务。以下示例显示了ldap:transaction-manager
元素中带有data-source-ref
属性:
<ldap:transaction-manager data-source-ref="dataSource" >
<ldap:default-renaming-strategy />
<ldap:transaction-manager />
提供的支持都是客户端的。 包装的事务不是 XA 事务。不执行两阶段提交,因为 LDAP 服务器无法对其结果进行投票。 |
您可以通过提供session-factory-ref
属性设置为<ldap:transaction-manager>
元素,如下所示:
<ldap:transaction-manager session-factory-ref="dataSource" >
<ldap:default-renaming-strategy />
<ldap:transaction-manager />
LDAP 补偿事务说明
Spring LDAP 通过在每次修改作 (bind
,unbind
,rebind
,modifyAttributes
和rename
).
这允许系统在需要回滚事务时执行补偿作。
在许多情况下,补偿作非常简单。例如,对bind
作是解绑该条目。
但是,由于 LDAP 数据库的某些特定特性,其他作需要不同的、更复杂的方法。
具体来说,并不总是能够获取 all 的值Attributes
,使得上述策略不足以达到(例如)一个unbind
操作。
这就是为什么在 Spring LDAP 托管事务中执行的每个修改作在内部都分为四个不同的作:一个记录作、 准备作、提交作和回滚作。下表描述了每个 LDAP作:
LDAP作 | 录音 | 制备 | 犯 | 反转 |
---|---|---|---|---|
|
记录要绑定的条目的 DN。 |
绑定条目。 |
无作。 |
使用记录的 DN 取消绑定条目。 |
|
记录原始 DN 和目标 DN。 |
重命名该条目。 |
无作。 |
将条目重命名回其原始 DN。 |
|
记录原始 DN 并计算临时 DN。 |
将条目重命名为临时位置。 |
取消绑定临时条目。 |
将临时位置的条目重命名回其原始 DN。 |
|
记录原始 DN 和新的 |
将条目重命名为临时位置。 |
绑定新的 |
将临时位置的条目重命名回其原始 DN。 |
|
记录要修改和计算补偿的条目的 DN |
执行 |
无作。 |
执行 |
Javadoc 中提供了 Spring LDAP 事务支持内部工作原理的更详细描述。
重命名策略
如上一节的表格所述,某些作的事务管理需要暂时重命名受该作影响的原始条目,然后才能在 commit 中进行实际修改。条目的临时 DN 的计算方式由TempEntryRenamingStrategy
在<ldap:transaction-manager >
声明。Spring LDAP 包括两种实现:
-
DefaultTempEntryRenamingStrategy
(默认):使用<ldap:default-renaming-strategy />
元素。将后缀添加到条目 DN 的最低有效部分。例如,对于cn=john doe, ou=users
,则此策略将返回cn=john doe_temp, ou=users
.您可以通过设置temp-suffix
属性。 -
DifferentSubtreeTempEntryRenamingStrategy
:使用<ldap:different-subtree-renaming-strategy />
元素。它将子树 DN 附加到 DN 的最低重要部分。这样做会使所有临时条目都放置在 LDAP 树中的特定位置。临时子树 DN 是通过设置subtree-node
属性。例如,如果subtree-node
是ou=tempEntries
条目的原始 DN 为cn=john doe, ou=users
,则临时 DN 为cn=john doe, ou=tempEntries
.请注意,配置的 subtree 节点需要出现在 LDAP 树中。
这DefaultTempEntryRenamingStrategy 在某些情况下不起作用。例如,如果您计划执行递归删除,则需要使用DifferentSubtreeTempEntryRenamingStrategy .这是因为递归删除作实际上包括单独对子树中每个节点的深度优先删除。由于您无法重命名具有任何 children 和DefaultTempEntryRenamingStrategy 将每个节点保留在同一子树中(具有不同的名称),而不是实际删除它,此作将失败。如有疑问,请使用DifferentSubtreeTempEntryRenamingStrategy . |