Spring数据访问和数据访问层与业务或服务层之间的交互
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring数据访问和数据访问层与业务或服务层之间的交互相关的知识,希望对你有一定的参考价值。
4. 使用 R2DBC 访问数据
R2DBC(“反应式关系数据库连接”)是一个社区驱动的 规范工作,以使用反应模式标准化对 SQL 数据库的访问。
4.1. 软件包层次结构
Spring 框架的 R2DBC 抽象框架由两个不同的包组成:
-
core
:包包含类以及各种相关类。请参阅 使用 R2DBC核心类控制基本 R2DBC 处理和错误处理。org.springframework.r2dbc.core
DatabaseClient
-
connection
:包包含实用程序类 便于访问和各种简单实施 可用于测试和运行未修改的 R2DBC。请参阅控制数据库连接。org.springframework.r2dbc.connection
ConnectionFactory
ConnectionFactory
4.2. 使用 R2DBC 核心类来控制基本的 R2DBC 处理和错误处理
本节介绍如何使用 R2DBC 核心类来控制基本的 R2DBC 处理, 包括错误处理。它包括以下主题:
- 使用数据库客户端
- 执行语句
- 查询 (选择)
- 使用数据库客户端更新(插入、更新和删除)
- 语句筛选器
- 检索自动生成的密钥
4.2.1. 使用DatabaseClient
DatabaseClient
是 R2DBC 核心包中的中心类。它处理 创建和释放资源,这有助于避免常见错误,例如 忘记关闭连接。它执行核心R2DBC的基本任务 工作流(例如语句创建和执行),保留应用程序代码以提供 SQL 并提取结果。班级:DatabaseClient
- 运行 SQL 查询
- 更新语句和存储过程调用
- 执行迭代覆盖实例
Result
- 捕获 R2DBC 异常并将其转换为通用的、信息量更大的异常 包中定义的层次结构。(请参阅一致的异常层次结构。
org.springframework.dao
客户端有一个功能强大、流畅的 API,使用反应式类型进行声明性组合。
当你使用for代码时,你只需要实现接口,给它们一个明确定义的契约。 给定由类提供的 a,acallback 创建一个。映射函数也是如此 提取结果。DatabaseClient
java.util.function
Connection
DatabaseClient
Function
Publisher
Row
您可以通过直接实例化在 DAO 实现中使用 带有引用,或者您可以在Spring IoC容器中配置它 并把它作为豆子参考给DAO。DatabaseClient
ConnectionFactory
创建对象的最简单方法是通过静态工厂方法,如下所示:DatabaseClient
DatabaseClient client = DatabaseClient.create(connectionFactory);
上述方法使用默认设置创建 a。DatabaseClient
您还可以从中获取实例。 您可以通过调用以下方法自定义客户端:Builder
DatabaseClient.builder()
-
….bindMarkers(…)
:提供名为 参数到数据库绑定标记转换。BindMarkersFactory
-
….executeFunction(…)
:设置如何对象获取 跑。ExecuteFunction
Statement
-
….namedParameters(false)
:禁用命名参数扩展。默认启用。
目前支持的数据库有:
- H2
- 玛丽亚数据库
- 微软SQL Server
- mysql
- 波斯特格雷斯
此类发出的所有 SQL 都记录在类别下的级别 对应于客户端实例的完全限定类名(通常)。此外,每次执行都会在 用于帮助调试的反应序列。DEBUG
DefaultDatabaseClient
以下各节提供了一些用法示例。这些例子 不是公开的所有功能的详尽列表。 请参阅随之而来的javadoc了解这一点。DatabaseClient
DatabaseClient
执行语句
DatabaseClient
提供运行语句的基本功能。 以下示例显示了最小但功能齐全需要包含的内容 创建新表的代码:
Mono<Void> completion = client.sql("CREATE TABLE person (id VARCHAR(255) PRIMARY KEY, name VARCHAR(255), age INTEGER);")
.then();
DatabaseClient
专为方便、流畅的使用而设计。 它公开了中间方法、延续方法和终端方法在 执行规范。上面的示例用于返回一个完成,一旦查询(或查询,如果 SQL 查询包含 多个语句)完成。then()
Publisher
查询 (SELECT
)
SQL 查询可以通过对象或受影响的行数返回值。可以返回更新的行数或行本身, 取决于发出的查询。Row
DatabaseClient
以下查询从表中获取 theandcolumns:id
name
Mono<Map<String, Object>> first = client.sql("SELECT id, name FROM person")
.fetch().first();
以下查询使用绑定变量:
Mono<Map<String, Object>> first = client.sql("SELECT id, name FROM person WHERE first_name = :fn")
.bind("fn", "Joe")
.fetch().first();
您可能已经注意到在示例中使用 above.is 用于指定要使用的数据量的延续运算符。fetch()
fetch()
调用返回结果中的第一行并丢弃剩余的行。 您可以使用以下运算符使用数据:first()
-
first()
返回整个结果的第一行。它的 Kotlin 协程变体 为不可为空的返回值命名,并且如果该值是可选的。awaitSingle()
awaitSingleOrNull()
-
one()
只返回一个结果,如果结果包含更多行,则失败。 使用 Kotlin 协程,对于正好一个值,或者如果该值可能是。awaitOne()
awaitOneOrNull()
null
-
all()
返回结果的所有行。使用 Kotlin 协程时,请使用。flow()
-
rowsUpdated()
返回受影响的行数 (//count)。它的 Kotlin 协程变体被命名。INSERT
UPDATE
DELETE
awaitRowsUpdated()
如果不指定进一步的映射详细信息,查询将返回表格结果 asits 键是不区分大小写的列名,映射到其列值。Map
您可以通过提供 athat get 来控制结果映射 调用 Eachso 它可以返回任意值(奇异值, 集合和地图以及对象)。Function<Row, T>
Row
下面的示例提取列并发出其值:name
Flux<String> names = client.sql("SELECT name FROM person")
.map(row -> row.get("name", String.class))
.all();
怎么样?
null
关系数据库结果可以包含值。 反应式流规范禁止释放值。 该要求要求在提取器功能中进行适当的处理。 虽然可以从 a 获取值,但不得发出值。您必须将任何值包装在对象中(例如,对于单数值),以确保永远不会直接返回 avalue 通过您的提取器函数。
null
null
null
null
Row
null
null
Optional
null
更新(,和)与INSERT
UPDATE
DELETE
DatabaseClient
修改语句的唯一区别是这些语句通常 不返回表格数据,以便用于使用结果。rowsUpdated()
下面的示例演示返回数字的语句 更新的行数:UPDATE
爪哇岛
科特林
Mono<Integer> affectedRows = client.sql("UPDATE person SET first_name = :fn")
.bind("fn", "Joe")
.fetch().rowsUpdated();
将值绑定到查询
典型的应用程序需要参数化 SQL 语句来选择或 根据某些输入更新行。这些是典型的陈述 受接受的从句或陈述的约束 输入参数。参数化语句承担 SQL 注入的风险,如果 参数未正确转义。利用 R2DBC 的 API 消除查询参数的 SQL 注入风险。 您可以使用运算符提供参数化的 SQL 语句 并将参数绑定到实际值。然后运行您的 R2DBC 驱动程序 使用预准备语句和参数替换的语句。SELECT
WHERE
INSERT
UPDATE
DatabaseClient
bind
execute(…)
Statement
参数绑定支持两种绑定策略:
- 按索引,使用从零开始的参数索引。
- 按名称,使用占位符名称。
以下示例显示查询的参数绑定:
db.sql("INSERT INTO person (id, name, age) VALUES(:id, :name, :age)")
.bind("id", "joe")
.bind("name", "Joe")
.bind("age", 34);
R2DBC 本机绑定标记
R2DBC 使用依赖于实际数据库供应商的数据库本机绑定标记。 例如,Postgres 使用索引标记,例如,,. 另一个示例是 SQL Server,它使用前缀为前缀的命名绑定标记。
$1
$2
$n
@
这与 JDBC 不同,JDBC 需要绑定标记。 在 JDBC 中,实际驱动程序将绑定标记转换为数据库本机 标记作为其语句执行的一部分。
?
?
Spring Framework 的 R2DBC 支持允许您使用本机绑定标记或命名绑定。 带有语法的标记。
:name
命名参数支持利用实例扩展命名 查询执行时本机绑定标记的参数,这为您提供了 跨各种数据库供应商的一定程度的查询可移植性。
BindMarkersFactory
查询预处理器将命名参数展开到一系列绑定中 标记,无需根据参数数创建动态查询。 嵌套对象数组被扩展为允许使用(例如)选择列表。Collection
请考虑以下查询:
SELECT id, name, state FROM table WHERE (name, age) IN ((John, 35), (Ann, 50))
上述查询可以参数化并按如下方式运行:
List<Object[]> tuples = new ArrayList<>();
tuples.add(new Object[] "John", 35);
tuples.add(new Object[] "Ann", 50);
client.sql("SELECT id, name, state FROM table WHERE (name, age) IN (:tuples)")
.bind("tuples", tuples);
以下示例显示了使用谓词的更简单变体:IN
client.sql("SELECT id, name, state FROM table WHERE age IN (:ages)")
.bind("ages", Arrays.asList(35, 50));
语句筛选器
有时,您需要在实际运行之前微调选项。注册过滤器 () 通过拦截和 修改语句的执行,如以下示例所示:Statement
Statement
StatementFilterFunction
DatabaseClient
client.sql("INSERT INTO table (name, state) VALUES(:name, :state)")
.filter((s, next) -> next.execute(s.returnGeneratedValues("id")))
.bind("name", …)
.bind("state", …);
DatabaseClient
还公开了简化的重载接受:filter(…)
Function<Statement, Statement>
client.sql("INSERT INTO table (name, state) VALUES(:name, :state)")
.filter(statement -> s.returnGeneratedValues("id"));
client.sql("SELECT id, name, state FROM table")
.filter(statement -> s.fetchSize(25));
StatementFilterFunction
实现允许过滤对象和过滤对象。Statement
Result
DatabaseClient
最佳实践
一旦配置,类的实例是线程安全的。这是 很重要,因为这意味着您可以配置 aand 的单个实例,然后将此共享引用安全地注入多个 DAO(或存储库)。 Theis 有状态的,因为它保持对 a 的引用, 但此状态不是会话状态。DatabaseClient
DatabaseClient
DatabaseClient
ConnectionFactory
使用类时的一个常见做法是在 Spring 配置文件中配置 a,然后注入依赖项 将豆子共享到您的 DAO 类中。泰斯创建于 二传手。这会导致类似于以下内容的 DAO:DatabaseClient
ConnectionFactory
ConnectionFactory
DatabaseClient
ConnectionFactory
public class R2dbcCorporateEventDao implements CorporateEventDao
private DatabaseClient databaseClient;
public void setConnectionFactory(ConnectionFactory connectionFactory)
this.databaseClient = DatabaseClient.create(connectionFactory);
// R2DBC-backed implementations of the methods on the CorporateEventDao follow...
用注释类。 |
注释方法。 |
创建一个新的。 |
显式配置的替代方法是使用组件扫描和注释 支持依赖注入。在这种情况下,您可以使用(这使其成为组件扫描的候选者)对类进行注释并注释这些内容。 方法。以下示例演示如何执行此操作:@Component
ConnectionFactory
@Autowired
@Component
public class R2dbcCorporateEventDao implements CorporateEventDao
private DatabaseClient databaseClient;
@Autowired
public void setConnectionFactory(ConnectionFactory connectionFactory)
this.databaseClient = DatabaseClient.create(connectionFactory);
// R2DBC-backed implementations of the methods on the CorporateEventDao follow...
用注释类。 |
构造函数注入的。 |
创建一个新的。 |
无论您选择使用上述哪种模板初始化样式(或 not),很少需要为每个类创建一个新的实例 您想要运行 SQL 的时间。配置后,实例是线程安全的。 如果应用程序访问多个 数据库,您可能需要多个实例,这需要多个实例,随后需要多个不同配置的实例。DatabaseClient
DatabaseClient
DatabaseClient
ConnectionFactory
DatabaseClient
4.3. 检索自动生成的密钥
INSERT
语句可能会在表中插入行时生成键 定义自动增量或标识列。完全控制 要生成的列名,只需注册一个 请求为所需列生成的密钥。StatementFilterFunction
Mono<Integer> generatedId = client.sql("INSERT INTO table (name, state) VALUES(:name, :state)")
.filter(statement -> s.returnGeneratedValues("id"))
.map(row -> row.get("id", Integer.class))
.first();
// generatedId emits the generated key once the INSERT statement has finished
4.4. 控制数据库连接
本节涵盖:
- 使用ConnectionFactory
- 使用ConnectionFactoryUtils
- 使用SingleConnectionFactory
- 使用TransactionAwareConnectionFactoryProxy
- 使用R2dbcTransactionManager
4.4.1. 使用ConnectionFactory
Spring 通过 a 获得与数据库的 R2DBC 连接。 A是R2DBC规范的一部分,是一个常见的入口点 对于司机。它允许容器或框架隐藏连接池 以及应用程序代码中的事务管理问题。作为开发人员, 您不需要知道如何连接到数据库的详细信息。那就是 设置管理员的责任。你 最有可能在开发和测试代码时同时担任这两个角色,但您不会 必须知道生产数据源是如何配置的。ConnectionFactory
ConnectionFactory
ConnectionFactory
当你使用Spring的R2DBC层时,你可以配置你自己的一个 由第三方提供的连接池实现。一个流行的 实现是 R2DBC 池 ()。春季实施 分发仅用于测试目的,不提供池化。r2dbc-pool
要配置:ConnectionFactory
- 获取连接,因为您通常获得 R2DBC。
ConnectionFactory
ConnectionFactory
- 提供 R2DBC 网址 (有关正确的值,请参阅驱动程序的文档)。
以下示例演示如何配置:ConnectionFactory
ConnectionFactory factory = ConnectionFactories.get("r2dbc:h2:mem:///test?options=DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE");
4.4.2. 使用ConnectionFactoryUtils
Theclass 是一个方便而强大的辅助类 这提供了从中获取连接和关闭连接的方法(如有必要)。ConnectionFactoryUtils
static
ConnectionFactory
例如,它支持订阅者绑定连接。Context
R2dbcTransactionManager
4.4.3. 使用SingleConnectionFactory
Theclass 是接口的实现,它包装一个每次使用后都不会关闭的单曲。SingleConnectionFactory
DelegatingConnectionFactory
Connection
如果任何客户端代码调用池连接的假设(如使用 持久性工具),应将属性设置为。此设置 返回包装物理连接的关闭抑制代理。请注意,您可以 不再将其强制转换为本机或类似对象。close
suppressClose
true
Connection
SingleConnectionFactory
主要是一个测试类,可用于特定要求 例如流水线(如果您的 R2DBC 驱动程序允许此类使用)。 与池化相比,它始终重复使用相同的连接,避免 过度创建物理连接。ConnectionFactory
4.4.4. 使用TransactionAwareConnectionFactoryProxy
TransactionAwareConnectionFactoryProxy
是目标的代理。 代理包装该目标以增加对 Spring 管理事务的感知。ConnectionFactory
ConnectionFactory
有关更多详细信息,请参阅TransactionAwareConnectionFactoryProxyjavadoc。
4.4.5. 使用R2dbcTransactionManager
该类是实现 单个 R2DBC 数据源。它绑定来自指定连接工厂的 R2DBC 连接 到订阅者,可能允许每个订阅者连接一个订阅者连接 连接工厂。R2dbcTransactionManager
ReactiveTransactionManager
Context
需要应用程序代码才能通过 R2DBC 连接而不是 R2DBC 的标准来检索。ConnectionFactoryUtils.getConnection(ConnectionFactory)
ConnectionFactory.create()
所有框架类(例如)都隐式使用此策略。 如果不与此事务管理器一起使用,则查找策略的行为与通用策略完全相同。 因此,它可以在任何情况下使用。DatabaseClient
该类支持应用于连接的自定义隔离级别。R2dbcTransactionManager
5. 对象关系映射 (ORM) 数据访问
本节介绍使用对象关系映射 (ORM) 时的数据访问。
5.1. 使用弹簧的ORM简介
Spring 框架支持与 Java Persistence API (JPA) 和 支持本机休眠资源管理、数据访问对象 (DAO) 实现、 和交易策略。例如,对于Hibernate,有一流的支持 几个方便的 IoC 功能,可解决许多典型的 Hibernate 集成问题。 您可以为 OR(对象关系)映射配置所有支持的功能 工具通过依赖注入。他们可以参与春天的资源和 交易管理,他们遵守Spring的通用交易和DAO 异常层次结构。推荐的集成风格是针对普通 DAO 编写代码 休眠或 JPA API。
Spring 在您创建时为您选择的 ORM 层添加了重要的增强功能 数据访问应用程序。您可以尽可能多地利用集成支持 希望,您应该将此集成工作与构建的成本和风险进行比较 内部类似的基础设施。您可以像使用一样使用大部分ORM支持 库,无论技术如何,因为一切都被设计为一组可重用的 爪哇豆。Spring IoC容器中的ORM有助于配置和部署。因此 本节中的大多数示例都显示了 Spring 容器内的配置。
使用Spring框架创建ORM DAO的好处包括:
- 更易于测试。Spring 的 IoC 方法使交换实现变得容易 以及休眠实例、JDBC 实例、事务管理器和映射对象实现(如果需要)的配置位置。这 反过来,可以更轻松地测试每段与持久性相关的代码 隔离。
SessionFactory
DataSource
- 常见数据访问异常。Spring 可以从您的 ORM 工具中包装异常, 将它们从专有(可能检查的)异常转换为通用运行时层次结构。此功能可让您处理大多数持久性 异常,这些异常不可恢复,仅在适当的层中,没有 烦人的样板捕获、抛出和异常声明。你仍然可以陷阱 并根据需要处理异常。请记住,JDBC 例外(包括 特定于数据库的方言)也转换为相同的层次结构,这意味着您可以 在一致的编程模型中使用 JDBC 执行一些操作。
DataAccessException
- 常规资源管理。Spring 应用程序上下文可以处理位置 以及休眠实例、JPA实例、JDBC实例和其他相关资源的配置。这使得这些 值易于管理和更改。弹簧提供高效、简单和安全的处理 持久性资源。例如,使用 Hibernate 的相关代码通常需要 使用相同的休眠以确保效率和适当的事务处理。 Spring 可以轻松透明地创建并绑定当前线程, 通过暴露通过冬眠的电流。因此,春天 解决了任何本地或JTA的典型Hibernate使用的许多长期问题 事务环境。
SessionFactory
EntityManagerFactory
DataSource
Session
Session
Session
SessionFactory
- 集成事务管理。您可以使用声明式代码包装您的 ORM 代码, 面向方面的编程 (AOP) 样式的方法拦截器,通过注释或显式配置事务 AOP 建议 一个 XML 配置文件。在这两种情况下,事务语义和异常处理 (回滚等)将为您处理。如资源和事务管理中所述, 您还可以交换各种事务管理器,而不会影响您的ORM相关代码。 例如,您可以在本地事务和JTA之间交换,使用相同的完整服务 (如声明性事务)在这两种情况下都可用。此外 JDBC 相关的代码可以与您用于执行 ORM 的代码完全事务集成。 这对于不适合ORM的数据访问(例如批处理和 BLOB 流),但这仍然需要与 ORM 操作共享公共事务。
@Transactional
5.2. 一般 ORM 集成注意事项
本节重点介绍适用于所有ORM技术的注意事项。 休眠部分提供了更多详细信息,并显示了这些功能和 具体上下文中的配置。
Spring 的 ORM 集成的主要目标是清晰的应用程序分层(包含任何数据) 访问和事务技术)和应用程序对象的松散耦合 — 否 对数据访问或事务策略的更多业务服务依赖,不再有 硬编码资源查找,不再有难以替换的单例,不再有自定义服务 登记处。目标是有一种简单而一致的方法来连接应用程序对象,保持 它们尽可能可重用且不受容器依赖关系的影响。所有个人 数据访问功能可以单独使用,但与Spring的集成得很好 应用程序上下文概念,提供基于 XML 的配置和交叉引用 不需要 Spring 感知的普通 JavaBean 实例。在典型的弹簧应用中, 许多重要的对象都是JavaBeans:数据访问模板,数据访问对象, 事务管理器,使用数据访问对象和事务的业务服务 管理器、Web 视图解析程序、使用业务服务的 Web 控制器等。
5.2.1. 资源和事务管理
典型的业务应用程序充斥着重复的资源管理代码。 许多项目试图发明自己的解决方案,有时会牺牲适当的处理方式 为方便编程而出现的故障。弹簧倡导简单的解决方案,以适当的 资源处理,即在 JDBC 的情况下通过模板化和应用 AOP 进行 IoC ORM技术的拦截器。
基础结构提供适当的资源处理和适当的转换 未经检查的基础架构异常层次结构的特定 API 例外。春天 引入了适用于任何数据访问策略的 DAO 异常层次结构。对于直接 JDBC,上一节中提到的类提供了连接处理和到层次结构的正确转换,包括数据库特定SQL错误的转换 代码到有意义的异常类。对于ORM技术,请参阅下一节,了解如何获取相同的异常 翻译优势。JdbcTemplate
SQLException
DataAccessException
当涉及到事务管理时,类与 Spring 挂钩 事务支持,并通过各自的 JTA 和 JDBC 事务支持 春季事务管理器。对于支持的ORM技术,Spring提供了Hibernate。 以及通过Hibernate和JPA事务管理器以及JTA支持的JPA支持。 有关事务支持的详细信息,请参阅事务管理一章。JdbcTemplate
5.2.2. 异常翻译
当你在DAO中使用Hibernate或JPA时,你必须决定如何处理持久性 技术的本机异常类。DAO 抛出 aor 的子类,具体取决于技术。这些异常都是运行时 例外,不必声明或捕获。您可能还必须处理和。这意味着呼叫者只能 将异常视为通常是致命的,除非它们想要依赖于持久性 技术自身的异常结构。抓住具体原因(如乐观 锁定失败)如果不将调用方绑定到实现策略,则是不可能的。 对于强基于 ORM 或 不需要任何特殊的例外处理(或两者兼而有之)。然而,春天让例外 翻译应通过注释透明地应用。以下 示例(一个用于 Java 配置,一个用于 XML 配置)显示了如何执行此操作:HibernateException
PersistenceException
IllegalArgumentException
IllegalStateException
@Repository
@Repository
public class ProductDaoImpl implements ProductDao
// class body here...
<beans>
<!-- Exception translation bean post processor -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<bean id="myProductDao" class="product.ProductDaoImpl"/>
</beans>
后处理器自动查找所有异常转换器(实现 界面),并建议所有标有注释的 bean,以便发现的翻译人员可以拦截并应用 对引发的异常进行适当的翻译。PersistenceExceptionTranslator
@Repository
总之,您可以基于普通持久技术的 API 实现 DAO,并且 注释,同时仍然受益于 Spring 管理的交易、依赖关系 注入,以及透明异常转换(如果需要)到 Spring 的自定义 异常层次结构。
5.3. 休眠
我们从Hibernate 5在 Spring 环境中的报道开始, 使用它来演示 Spring 集成 OR 映射器的方法。 本节详细介绍了许多问题,并展示了DAO的不同变体 实现和事务划分。这些模式中的大多数可以直接 翻译成所有其他受支持的ORM工具。然后,本章的后面部分 涵盖其他ORM技术并显示简要示例。
5.3.1.在弹簧容器中设置SessionFactory
若要避免将应用程序对象绑定到硬编码的资源查找,可以定义 资源(例如 JDBCor Hibernate)作为 弹簧容器。需要访问资源的应用程序对象接收引用 通过 Bean 引用到此类预定义实例,如 DAO 中所述 下一节中的定义。DataSource
SessionFactory
以下摘自 XML 应用程序上下文定义的摘录演示如何设置 JDBC和它的Hibernateon顶部:DataSource
SessionFactory
<beans>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
<property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
<bean id="mySessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
<property name="dataSource" ref="myDataSource"/>
<property name="mappingResources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.HSQLDialect
</value>
</property>
</bean>
</beans>
从本地 Jakarta Commons DBCP 切换到位于 JNDI(通常由应用程序服务器管理)只需 配置,如以下示例所示:BasicDataSource
DataSource
<beans>
<jee:jndi-lookup id="myDataSource" jndi-name="java:comp/env/jdbc/myds"/>
</beans>
您还可以使用 Spring 的 / 访问位于 JNDI 的位置,以检索和公开它。 但是,这在 EJB 上下文之外通常并不常见。SessionFactory
JndiObjectFactoryBean
<jee:jndi-lookup>
5.3.2. 基于普通休眠 API 实现 DAO
Hibernate有一个称为上下文会话的功能,其中Hibernate本身管理 每个事务一个当前。这大致相当于春天的 同步一个休眠事务。相应的 DAO 实现类似于以下示例,基于普通的 Hibernate API:Spring数据访问和数据访问层与业务或服务层之间的交互