使用 nolock 的 Java Hibernate HQL 查询

Posted

技术标签:

【中文标题】使用 nolock 的 Java Hibernate HQL 查询【英文标题】:Java Hibernate HQL queries with nolock 【发布时间】:2010-08-17 07:11:20 【问题描述】:

有没有办法像我向它们添加 (NOLOCK) 提示一样运行这些查询?

【问题讨论】:

【参考方案1】:

如果你真的需要这个,那么你想做这样的事情:

session.connection().setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);

这与 nolock 相同。

在您这样做之前,请仔细考虑是否要进行脏读。大多数时候人们这样做是因为这是他们一直在做的事情,而不是因为这是正确的做法。特别是,这不适用于缓存。

实际上,this thread 有点涉及问题。在决定之前仔细阅读。

【讨论】:

谢谢,加里。是的,我在寻找脏读。我们的 DBA 已为该项目区域中的所有“选择”推荐了 NOLOCK。问题是,部分 SQL 处于休眠状态。 在最新版本的 Hibernate 中,connection() 似乎已从 API 中删除。关于在没有连接对象的情况下如何实现类似效果的任何想法? 如果使用@Transactional-注解,可以指定为isolation-property。 @Tobb - 为了清楚起见,我假设您的意思是 Spring Transactional 注释,它不是 Hibernate 的一部分。【参考方案2】:

在最新版本的 Hibernate 中,您必须这样做:

  Session session = (Session) em.getDelegate();
        session.doWork(new Work() 
            @Override
            public void execute(Connection connection) throws SQLException 
                connection.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
            
        );

【讨论】:

我已经使用这种方法在某些查询上设置了 read_uncommitted 事务隔离级别,但我确实意识到连接量比没有它时增加了数倍。在 read_uncommitted 事务之前,我们拥有应用程序的 Websphere 服务器上的连接数是 4,之后变成 80。这正常吗?还是我应该寻找其他东西和其他地方来找到问题?【参考方案3】:

如果你是原生的,你可以做“with (nolock)”。这是极端的,但如果替代方案是更改事务隔离级别,您可能更愿意这样做。

请注意,此示例适用于 MSSQL。

String sqlQueryString = "SELECT * FROM my_classes_table WITH (nolock) WHERE columnName = :columnValue";

SQLQuery sqlQuery= session.createSQLQuery(sqlQueryString).addEntity(MyClass.class);
sqlQuery.setLong("columnValue", value);
List<MyClass> out = sqlQuery.list();

【讨论】:

以上是关于使用 nolock 的 Java Hibernate HQL 查询的主要内容,如果未能解决你的问题,请参考以下文章

使用 nolock 和独占锁

使用 WITH (NOLOCK) 和事务

什么时候适合使用 NOLOCK?

SQL Server 中的“with (nolock)”是啥?

使用 Nolock 提示更新查询

Hibernat 原生SQL运行结果集处理方法