Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/database/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么我需要Hibernate中的事务来执行只读操作?_Java_Database_Hibernate_Transactions_Database Connection - Fatal编程技术网

Java 为什么我需要Hibernate中的事务来执行只读操作?

Java 为什么我需要Hibernate中的事务来执行只读操作?,java,database,hibernate,transactions,database-connection,Java,Database,Hibernate,Transactions,Database Connection,为什么我需要Hibernate中的事务来执行只读操作 以下事务是否在数据库中设置了锁 从数据库获取的示例代码: Transaction tx = HibernateUtil.getCurrentSession().beginTransaction(); // why begin transaction? //readonly operation here tx.commit() // why tx.commit? I don't want to write anything 我是否可以使用s

为什么我需要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
    中工作
  • 但是不能保证您的方法不会写入数据库。如果将方法标记为
    @Transactional(readonly=true)
    ,Spring将把JDBC事务设置为只读模式,因此您将指示是否可以在该事务的范围内写入DB。如果您的体系结构很麻烦,并且一些团队成员可能会选择将修改查询放在不期望的地方,那么这个标志会将您指向有问题的地方
  • 只读事务也可以由DBs优化,但这当然是特定于DB的。例如,MySQL仅从5.6.4版开始在InnoDB中添加了对此的支持
  • 如果您不是直接使用JDBC,而是使用ORM,那么可能会有问题。例如,Hibernate社区说,在事务之外工作可能会导致不可预测的行为。这是因为Hibernate将打开事务,但它不会自己关闭它,因此连接将返回到连接池,而事务未提交。然后呢?JDBC保持沉默,因此这是特定于实现的(MySQL回滚事务,Oracle afair提交事务)。这也可以在连接池级别进行配置(例如,C3P0为您提供了这样一个选项,默认情况下为回滚)
  • 另一件事是,在Hibernate中,Spring将只读事务的FlushMode设置为MANUAL,这会导致其他优化,比如不需要脏检查
  • 您可能希望覆盖或显式设置事务隔离级别。这也会影响读取事务,因为您确实或不想读取未提交的更改、暴露于幻象读取等

  • 总而言之,您可以选择两种方式,但您需要了解结果。

    事务确实会在数据库上设置锁-好的数据库引擎会以合理的方式处理并发锁-并且对于只读使用非常有用,可以确保没有其他事务会添加导致视图不一致的数据。您总是想要一个事务(尽管有时调整隔离级别是合理的,但最好不要这样做);如果您在事务期间从未向数据库写入数据,那么提交和回滚事务都是一样的(而且非常便宜)


    现在,如果幸运的话,您对数据库的查询是这样的,ORM总是将它们映射到单个SQL查询,那么您可以不用显式事务,依靠数据库的内置自动提交行为,但是ORMs是相对复杂的系统,因此依赖这种行为是不安全的,除非你做更多的工作来检查实现的实际功能。在中编写显式事务边界要容易得多(特别是如果您可以使用AOP或类似的ORM驱动技术;从Java 7开始,我想也可以使用try with resources)。

    无论您是否只阅读,数据库都必须跟踪您的结果集,因为其他数据库客户端可能希望写入会更改结果集的数据


    我见过错误的程序杀死大型数据库系统,因为它们只读取数据,但从不提交,迫使事务日志增长,因为DB不能在提交或回滚之前释放事务数据,即使客户端数小时不做任何操作。

    所有数据库语句都在物理事务的上下文中执行,即使我们没有明确声明事务边界(例如,开始、提交、回滚)

    如果没有明确声明事务边界,则每个语句都必须在单独的事务中执行(
    autocommit
    模式)。这甚至可能导致每个语句打开和关闭一个连接,除非您的环境可以处理每个线程的连接绑定

    将服务声明为
    @Transactional
    将在整个事务期间为您提供一个连接,并且所有语句都将使用该单一隔离连接。这比一开始不使用显式事务要好得多

    在大型应用程序上,您可能会有许多并发请求,降低数据库连接获取请求率肯定会提高应用程序的整体性能


    JPA不会对读取操作强制执行事务。只有当您忘记启动事务上下文时,写入操作才会抛出一个
    TransactionRequiredException
    。然而,即使对于只读事务,也最好声明事务边界(在Spring中
    @Transactional
    允许您标记只读事务,这对性能有很大的好处)。

    事务是数据库本身所必需的。您可以在此处阅读有关自动提交模式的内容:@BheshGurung我想我们只需要为写入操作进行转换。您是否阅读了链接中的“揭穿自动提交神话”部分?感谢您的回复。我使用的是hibernate(本机hibernate,而不是jpa)。但是hibernate强制我在执行任何db操作之前启动一个transaction。如果我不启动它,它会抛出错误,说没有活动跟踪。我可以将transaction标记为只读吗?如果是,怎么做?readonly标志实际上是为连接设置的,而不是为事务本身设置的,您不能像那样通过hibernate访问它。你需要使用弹簧