此版本仍在开发中,尚不被认为是稳定的。对于最新的稳定版本,请使用 Spring LDAP 3.3.3! |
交易支持
习惯于使用 LDAP 世界的关系数据库的程序员经常对没有事务概念这一事实表示惊讶。 协议中未指定它,并且没有 LDAP 服务器支持它。 认识到这可能是一个主要问题,Spring LDAP 为客户端提供了对 LDAP 资源的补偿事务的支持。
LDAP 事务支持由ContextSourceTransactionManager
一个PlatformTransactionManager
管理 LDAP作的 Spring 事务支持的实现。它与其合作者一起跟踪事务中执行的 LDAP作,记录每次作之前的状态,并在事务需要回滚时采取措施恢复初始状态。
除了实际的事务管理外,Spring LDAP 事务支持还确保了DirContext
实例在同一事务中使用。也就是说,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 数据库的一些特殊特征,其他作需要不同的、更复杂的方法。
具体来说,并不总是能够获得所有Attributes
,使得上述策略不足以(例如)一个unbind
操作。
这就是为什么在 Spring LDAP 托管事务中执行的每个修改作在内部都分为四个不同的作:记录作、 准备作、提交作和回滚作。下表描述了每个 LDAP作:
LDAP作 | 录音 | 制备 | 犯 | 反转 |
---|---|---|---|---|
|
记录要绑定的条目的DN。 |
绑定条目。 |
没有作。 |
使用记录的 DN 取消绑定条目。 |
|
记录原始 DN 和目标 DN。 |
重命名条目。 |
没有作。 |
将条目重命名回其原始 DN。 |
|
记录原始DN并计算临时DN。 |
将条目重命名为临时位置。 |
解绑临时条目。 |
将条目从临时位置重命名回其原始 DN。 |
|
记录原始 DN 和新 |
将条目重命名为临时位置。 |
绑定新的 |
将条目从临时位置重命名回其原始 DN。 |
|
记录条目的DN以修改和计算补偿 |
执行 |
没有作。 |
执行 |
Javadoc 中提供了 Spring LDAP 事务支持的内部工作原理的更详细描述。
重命名策略
如上一节的表所述,某些作的事务管理需要暂时重命名受作影响的原始条目,然后才能在提交中进行实际修改。计算条目的临时 DN 的方式由TempEntryRenamingStrategy
在<ldap:transaction-manager >
声明。Spring LDAP 包括两个实现:
-
DefaultTempEntryRenamingStrategy
(默认值):通过使用<ldap:default-renaming-strategy />
元素。向条目 DN 的最低有效部分添加后缀。例如,对于 DN 为cn=john doe, ou=users
,则此策略返回临时 DNcn=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
.请注意,配置的子树节点需要存在于 LDAP 树中。
这DefaultTempEntryRenamingStrategy 在某些情况下不起作用。例如,如果您计划进行递归删除,则需要使用DifferentSubtreeTempEntryRenamingStrategy .这是因为递归删除作实际上包括对子树中每个节点的深度优先删除。由于您无法重命名具有任何子项和DefaultTempEntryRenamingStrategy 将每个节点保留在同一个子树中(具有不同的名称)而不是实际删除它,则此作将失败。如有疑问,请使用DifferentSubtreeTempEntryRenamingStrategy . |