是否有必要开始事务以在数据库中查找对象?

Is it necessary to begin a transaction to find an object in the data base?

我知道以下是与数据库中的对象交互所必需的:

db.getTransaction().begin();
//Code to modify objects in the data base
db.getTransaction().commit();

但是当我使用函数 find(object.class, object.id) 时有必要吗?

Is it necessary to begin a transaction to find an object in the data base?

取决于您所说的 'transaction'。

数据库做事务中的一切。时期。因此,很简单,'yes',开始一个事务是必要的,因为如果不这样做你就无法与数据库进行交互。

但是,数据库有一个 'convenience' 功能,您可以在其中工作,就好像事务不存在一样。这是个谎言;它仅仅意味着 您发送给数据库的每条语句 都被默默地包裹在 'START TRANSACTION;' 和 'COMMIT;' 调用中。这称为 'auto commit' 模式(而不是 'transactionless mode'),因为这是它的正确词:它在每个事务后自动提交。

因此,在基本 JDBC 中(java 中所有基于 SQL 的数据库交互通常都建立在基础层上,但请注意,您正在使用某种建立在它之上的库!),你可以 运行 一个 select 查询,没有 'need' 通过使用自动提交模式来打扰事务。

但是,自动提交模式通常不是一个好主意。

事务是数据库设计的基础。即使您只进行 'read' 查询,事务仍然很重要。它们保证一致性和原子性。这是一个例子:

假设您想知道 Jane 和 Jack 的银行余额,例如检查余额是否足以租用房屋或诸如此类的东西。

看起来很简单:

SELECT balance FROM bankaccounts WHERE user = 'Jack';
SELECT balance FROM bankaccounts WHERE user = 'Jane';

把他们加起来,对吧?

错误.

如果您 运行 在自动提交模式下,那么 Jack 可能有 50k,Jane 有 100k,但是总和似乎是 200k。这是通过 jack 设法在两个语句之间将他的 50k 转移给 jane 来完成的,给你一个 50k+150k = 200k 的总和,尽管这是一个谎言。

事务因此也适用于只读会话;假设您使用了正确的隔离级别(SERIALIZABLE 是明智的级别),它们甚至会导致重试。通过交易,您每次都会得到 150k 的正确答案,无论 jane 和 jack 何时或多久来回转移资金以试图欺骗您。

JDBC本身没有这个'getTransaction()'的东西,或者'begin',一般来说这不是'do'交易的正确方式。因此,不清楚您在这里使用的是什么第三方库。

适当的数据库抽象类似于:

int sum = dbAccess.executeInt(db -> {
  // query or modify things here:
  return
  db.select("SELECT balance FROM bankaccount WHERE user = ?", "Jack").singleInt() +
  db.select("SELECT balance FROM bankaccount WHERE user = ?", "Jane").singleInt();
};

它需要在 lambda 中处理重试,并且它与 所有 与数据库的交互都是事务性的事实很好地吻合。

您可能想仔细阅读文档;这种策略(使用 lambdas)可能 post-date 你的数据库库的开始(lambdas 是在 java8 中添加的;诚然,那是十年前的事了)。