java - 是否需要开始事务才能在数据库中查找对象?

标签 java database object persist

我知道与数据库中的对象交互需要以下内容:

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?

取决于您所说的“交易”一词的含义。

数据库完成事务中的所有事情。时期。因此,简单来说,"is",有必要开始事务,因为如果不这样做,您就无法与数据库交互。

但是,数据库有一个“方便”的功能,您可以像不存在事务一样工作。这是个谎言;它仅仅意味着您发送到数据库的每条语句都默默地包含在“START TRANSACTION;”中和“提交”;来电。这称为“自动提交”模式(而不是“无事务模式”),因为这是正确的词:它在每个事务后自动提交。

因此,在基本的 JDBC 中(java 中所有基于 SQL 的数据库交互通常构建于其上的基础层,但请注意,您正在使用构建在其之上的某种库!),您可以只运行选择查询,通过使用自动提交模式,“不需要”处理事务。

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

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

假设您想知道 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 的总和,尽管这是一个谎言。

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

JDBC 本身没有“getTransaction()”这个东西,或者“开始”,一般来说,这不是“执行”事务的正确方法。因此,不清楚您在这里使用的是哪个第三方库。

正确的数据库抽象看起来像:

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 中来处理重试,并且它与数据库的所有交互都是事务性的这一事实非常吻合。

您可能想再仔细阅读一下文档;这种(使用 lambda 表达式)策略可能会晚于您的数据库库的开始(lambda 表达式是在 java8 中添加的;诚然,那是十年前的事了)。

关于java - 是否需要开始事务才能在数据库中查找对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67269332/

相关文章:

c++ - SQLite 真的很慢

Java HtmlUnit 点击 anchor

database - 数据库事务中的时间顺序

javascript - 在界面上显示从数据库获取的结果(JavaScript/HTML/SQLite)

java - 在类方法中包含 this 关键字是个好习惯吗?

Javascript - 在一个循环中,在正确 6 个月后添加 1 周到日期对象行为不端

java - Java 数组有最大大小吗?

java - Android - 在 WebView 中实现 findOnPage

java - 在 Thymeleaf 中格式化日期

javascript - 如何从 ng-repeat 内的对象中删除元素?