java 选择使用休眠

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3713829/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 03:07:43  来源:igfitidea点击:

Select using hibernate

javahibernateorm

提问by Soft

I saw few examples over internet of Hibernate using transaction.commit()for select statements. Below is the example code.

我在互联网上看到了几个使用transaction.commit()for select 语句的 Hibernate 示例。下面是示例代码。

public static List<?> list(Class<?> className,int start,int limit,SearchFilter[] searchFilter){
    Session session = HibernateUtil.getSessionFactory().openSession();
    Transaction transaction = null; 

    try {
        transaction = session.beginTransaction();

        Criteria criteria = session.createCriteria(className);
        criteria.setFirstResult(start);
        criteria.setMaxResults(limit);

        for(SearchFilter sf : searchFilter){
            String[] values = sf.getValue();
            if(values != null){
                if(values.length == 1) {
                    criteria.add(Restrictions.eq(sf.getField(), values[0]));
                }else{
                    criteria.add(Restrictions.in(sf.getField(), values));
                }
            }
        }

        List<?> Objects = criteria.list();
        transaction.commit();

        return Objects;
    }catch (Exception e) {
        transaction.rollback();
        e.printStackTrace();
    }finally{
        session.close();
    }

    return null;
}

Why do we do beginning and committing a transaction for select statement?

为什么我们要为 select 语句开始和提交事务?

采纳答案by pstanton

everything happens within the scope of a transaction.sometimes software automatically manages a transaction for you, but hibernate does not. whether read-only or not, in hibernate you must open and close transactions.

一切都发生在交易范围内。有时软件会自动为您管理事务,但休眠不会。无论是否只读,在休眠状态下您必须打开和关闭事务。

回答by Pascal Thivent

I highly recommend reading Non-transactional data access and the auto-commit mode. Let me quote a small part:

我强烈建议阅读非事务性数据访问和自动提交模式。让我引用一小部分:

(...)

Many more issues must be considered when you introduce nontransactional data access in your application. We've already noted that introducing a new type of transaction, namely read-only transactions, can significantly complicate any future modification of your application. The same is true if you introduce nontransactional operations.

You would then have three different kinds of data access in your application: in regular transactions, in read-only transactions, and now also nontransactional, with no guarantees. Imagine that you have to introduce an operation that writes data into a unit of work that was supposed to only read data. Imagine that you have to reorganize operations that were nontransactional to be transactional.

Our recommendation is to not use the autocommit mode in an application, and to apply read-only transactions only when there is an obvious performance benefitor when future code changes are highly unlikely. Always prefer regular ACID transactions to group your data-access operations, regardless of whether you read or write data.

Having said that, Hibernate and Java Persistence allow nontransactional data access. In fact, the EJB 3.0 specification forces you to access data nontransactionally if you want to implement atomic long-running conversations. We'll approach this subject in the next chapter. Now we want to dig a little deeper into the consequences of the autocommit mode in a plain Hibernate application. (Note that, despite our negative remarks, there are some good use cases for the autocommit mode. In our experience autocommit is often enabled for the wrong reasons and we wanted to wipe the slate clean first.)

Working nontransactionally with Hibernate

Look at the following code, which accesses the database without transaction boundaries:

Session session = sessionFactory.openSession(); 
session.get(Item.class, 123l); 
session.close(); 

By default, in a Java SE environment with a JDBC configuration, this is what happens if you execute this snippet:

  1. A new Session is opened. It doesn't obtain a database connection at this point.
  2. The call to get() triggers an SQL SELECT. The Session now obtains a JDBC Connection from the connection pool. Hibernate, by default, immediately turns off the autocommit mode on this connection with setAutoCommit(false). This effectively starts a JDBC transaction!
  3. The SELECT is executed inside this JDBC transaction. The Session is closed, and the connection is returned to the pool and released by Hibernate — Hibernate calls close() on the JDBC Connection. What happens to the uncommitted transaction?

The answer to that question is, “It depends!” The JDBC specification doesn't say anything about pending transactions when close() is called on a connection. What happens depends on how the vendors implement the specification. With Oracle JDBC drivers, for example, the call to close() commits the transaction! Most other JDBC vendors take the sane route and roll back any pending transaction when the JDBC Connection object is closed and the resource is returned to the pool.
Obviously, this won't be a problem for the SELECT you've executed (...)

(...)

在应用程序中引入非事务性数据访问时,必须考虑更多问题。我们已经注意到,引入一种新类型的事务,即只读事务,可能会使您的应用程序的任何未来修改显着复杂化。如果您引入非事务性操作,情况也是如此。

然后,您的应用程序中将拥有三种不同类型的数据访问:常规事务、只读事务和现在还没有保证的非事务性事务。想象一下,您必须引入一个将数据写入应该只读取数据的工作单元的操作。想象一下,您必须将非事务性操作重新组织为事务性操作。

我们的建议是不要在应用程序中使用自动提交模式,并且仅在有明显的性能优势或未来代码更改的可能性很小时才应用只读事务。无论您是读取数据还是写入数据,始终倾向于使用常规 ACID 事务来对您的数据访问操作进行分组。

话虽如此,Hibernate 和 Java Persistence 允许非事务性数据访问。事实上,如果您想实现原子的长时间运行的对话,EJB 3.0 规范会强制您以非事务方式访问数据。我们将在下一章讨论这个主题。现在我们想更深入地了解一个普通 Hibernate 应用程序中自动提交模式的后果。(请注意,尽管我们发表了负面评论,但自动提交模式有一些很好的用例。根据我们的经验,自动提交通常是出于错误的原因启用的,我们想先把石板擦干净。)

使用 Hibernate 以非事务方式工作

看下面的代码,访问数据库没有事务边界:

Session session = sessionFactory.openSession(); 
session.get(Item.class, 123l); 
session.close(); 

默认情况下,在具有 JDBC 配置的 Java SE 环境中,如果您执行以下代码段会发生以下情况:

  1. 一个新的会话被打开。此时它不会获得数据库连接。
  2. 对 get() 的调用会触发 SQL SELECT。会话现在从连接池中获取 JDBC 连接。默认情况下,Hibernate 会立即使用 setAutoCommit(false) 关闭此连接上的自动提交模式。这有效地启动了 JDBC 事务!
  3. SELECT 在此 JDBC 事务中执行。Session 关闭,连接返回到池中并由 Hibernate 释放——Hibernate 在 JDBC 连接上调用 close()。未提交的事务会发生什么?

这个问题的答案是,“这取决于!” JDBC 规范没有说明在连接上调用 close() 时挂起的事务。会发生什么取决于供应商如何实现规范。例如,对于 Oracle JDBC 驱动程序,调用 close() 会提交事务!大多数其他 JDBC 供应商采取理智的路线并在 JDBC Connection 对象关闭并将资源返回到池时回滚任何挂起的事务。
显然,这对于您执行的 SELECT 不会有问题 (...)

回答by Maurice Perry

Well the commit is actually useless, but, as psanton said, everything happens within the scope of a transaction.

好吧,提交实际上是无用的,但是,正如 psanton 所说,一切都发生在事务范围内。

回答by loungerdork

You need to wrap your operations in transactions even for selects due to isolation levels and repeatable reads encountered when you use MySQL's InnoDB engine.

由于隔离级别和使用 MySQL 的 InnoDB 引擎时遇到的可重复读取,您需要将操作包装在事务中,即使是选择也是如此。

Check out the issue that I faced here.

看看我在这里遇到的问题。

Hibernate collection not updated when records inserted externally

外部插入记录时未更新休眠集合