为什么只读操作需要Hibernate中的事务?

下面的事务是否在数据库中设置了锁?

从数据库获取的示例代码:

Transaction tx = HibernateUtil.getCurrentSession().beginTransaction(); // why begin transaction?
//readonly operation here

tx.commit() // why tx.commit? I don't want to write anything

我能用session.close()而不是tx.commit()吗?

推荐答案

用于读取的事务可能看起来确实很奇怪,在这种情况下,人们通常不会为事务标记方法.但JDBC无论如何都会创建事务,只是如果没有明确设置不同的选项,它将在autocommit=true分钟内工作.但将交易标记为只读是有实际原因的:

对数据库的影响

  1. 只读标志可以让DBMS优化此类事务或并行运行的事务.
  2. 拥有跨越多个SELECT语句的事务可确保从可重复读取或快照开始的级别得到适当隔离(例如,请参见PostgreSQL's Repeatable Read).否则,如果另一个事务并行提交,两个SELECT语句可能会看到不一致的画面.当使用READ COMMITTED时,这是不相关的.

对ORM的影响

  1. 如果不明确开始/完成事务,ORM可能会导致不可预测的结果.Hibernate将在第一条语句之前打开事务,但不会完成它.因此,连接将与未完成的事务一起返回到连接池.然后呢?JDBC保持沉默,因此这是特定于实现的:MySQL、PostgreSQL驱动程序回滚此类事务,Oracle提交事务.请注意,这也可以在连接池级别进行配置,例如C3P0为您提供了这样一个选项,默认情况下为回滚.
  2. Spring在只读事务中设置FlushMode=MANUAL,这会导致其他优化,比如不需要脏判断.这可能会带来巨大的性能提升,具体取决于加载了多少对象.

Impact on architecture & clean code

不能保证您的方法不会写入数据库.如果您将method标记为@Transactional(readonly=true),您将决定是否可以在此事务范围内写入DB.如果您的体系 struct 很笨重,并且一些团队成员可能 Select 将修改查询放在不需要的地方,那么这个标志将把您带到有问题的地方.

Database相关问答推荐

重新运行后未找到 Taipy 场景

无法向 SiriDB 添加新副本

sql-dump 有什么用?

PostgreSQL 嵌套 INSERTs / WITHs 用于外键插入

在 SQL Server 中以编程方式创建数据库

如何将 PHP 会话数据保存到数据库而不是文件系统中?

WAMP 的 MySQL 数据库文件位于何处?

基于邮政编码的纬度和经度

数据验证是否应该在数据库级别进行?

如何在 Products 表的主键和自然键之间做出决定?

Meteor 如何执行数据库迁移?

数据库表中的索引有什么缺点?

归档实时 MySQL 数据库的最佳方式

从旧数据 struct 到新数据 struct 的数据迁移

数据库 - 设计 Events事件表

MongoDB中的数据库数据大小

如何在 PostgreSQL 事务中获得实时?

App=EntityFramework 在 Sql 连接字符串中有什么作用?

xampp phpmyadmin,格式参数不正确

使用 Sinatra 时与数据库对话的最佳方式是什么?