java - Hibernate - 锁问题

标签 java hibernate

我对锁在各种情况下的实现提出疑问,我希望得到比我更专家的用户的一些建议。 我使用两个支持类,名为 HibernateUtil 和 StorageManager。

HibernateUtil

简单地返回 session 工厂的单例实例;显然,它在第一次调用时创建 session 工厂。

存储管理器

包含各个实体之间的公共(public)操作。在创建时,它从 HibernateUtil 获取 session 工厂并将其存储到静态变量中。 此类实现了每个请求的 session (或者可能是每个操作的 session )模式,因此对于每种类型的请求,它基本上按顺序执行以下操作:

  1. 打开一个新 session (从之前存储的 session 工厂)
  2. 开始新交易
  3. 执行具体请求(取决于调用的StorageManager的具体方法
  4. 提交交易
  5. 结束 session

当然,非常感谢对这种风格的评论。

那么,实现第3点的操作基本上有3类

插入、更新或删除实体

session.save(entity); 
// OR session.update(entity) OR session.delete(entity)
session.buildLockRequest(LockOptions.UPGRADE).lock(entity);

获取实体

T entity = (T) session.byId(type).with(LockOptions.READ).load(id);
// There are other forms of get, but they are pretty similar

获取列表

List<T> l = session.createCriteria(type).list();
// Same here, various but similar forms of get list

同样,不知道这是否是实现各种操作的正确方法。 另外,这才是真正的问题,每当发生错误时,都无法以任何方式访问数据存储,即使是从命令行也是如此,直到我手动停止导致问题的应用程序。我该如何解决这个问题?

提前致谢。


编辑

更多代码 这是上面列出的部件的代码。

private void createTransaction()  // Parts 1 and 2 of the above list
{
    session = sessionFactory.openSession();
    transaction = null;
    try
    {
        transaction = session.beginTransaction();
    }
    catch (HibernateException exception)
    {
        if (transaction != null) transaction.rollback();
        exception.printStackTrace();
    }
}

private void commitTransaction() // Part 4 of the above list
{
    try
    {
        transaction.commit();
    }
    catch (HibernateException exception)
    {
        if (transaction != null) transaction.rollback();
        exception.printStackTrace();
    }
}

private void closeSession() // Part 5 of the above list
{
    try
    {
        // if (session != null)
        {
            session.clear();
            session.close();
        }
    }
    catch (HibernateException exception)
    {
        exception.printStackTrace();
    }
}

public void update(T entity) // Example usage for part 3 of the above list
{
    try
    {
        this.createTransaction();
        session.update(entity);
        // session.buildLockRequest(LockOptions.UPGRADE).lock(entity);
        this.commitTransaction();
    }
    catch (HibernateException exception)
    {
        exception.printStackTrace();
    }
    finally
    {
        this.closeSession();
    }
}

最佳答案

您的错误情况(真正的问题)表明您没有遵循典型的事务使用习惯用法(来自 Session Javadoc ):

Session sess = factory.openSession();
Transaction tx = null;
try {
    tx = sess.beginTransaction();
    //do some work, point 3
    tx.commit();
} catch (Exception e) {
    if (tx!=null) tx.rollback();
    throw e;
} finally {
    sess.close();
}

请注意 catch 和 finally block ,它们确保在发生错误时释放所有数据库资源。 (*)

我不确定为什么在更改数据库记录(插入、更新或删除实体)后要锁定数据库记录(LockOptions.UPGRADE)。通常,您在(读取和)更新数据库记录之前锁定该记录,以便确保获得最新数据,并且使用同一数据库记录的其他打开事务不会干扰(读取和)更新。

锁定对于插入操作没有什么意义,因为默认事务隔离级别是“已提交读”(1),这意味着当事务插入记录时,该记录仅在插入该记录的事务之后对其他数据库事务可见 promise 。 IE。在事务提交之前,其他事务无法选择和/或更新新的“尚未提交”插入的记录。

(1) 仔细检查以确保。在 Hibernate configuration 中搜索“hibernate.connection.isolation”章节。值应为“2”,如 Java Connection 中所示。恒定字段值。

(*) 当数据库记录锁定后数据库连接丢失时,存在一种令人讨厌的极端情况。在这种情况下,客户端无法提交或回滚(因为连接已断开),并且数据库服务器可能会永远保留对记录的锁定。良好的数据库服务器将解锁由损坏和丢弃的数据库连接锁定的记录(并回滚该损坏的数据库连接的任何打开的事务),但不能保证(例如,数据库服务器如何以及何时会发现损坏的数据库连接? )。这是稀疏使用数据库记录锁的原因之一:仅当使用数据库记录的应用程序无法阻止对同一数据库记录的并发/同时更新时才尝试使用它们。

关于java - Hibernate - 锁问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27202203/

相关文章:

java - 如何将基于时间的 java.util.UUID 转换为 DateTIme

sql - 如何通过Hibernate获取数据库版本?

java - hibernate 。多对多。双向关联。楼主是什么意思?

java - 这个 HQL 查询有什么问题?

java - 带有 jdbc 的 Spring Security 3.0

java - 没有从 Servlet 页面收到任何响应

java - bytebuffer.flip() 和 bytebuffer.rewind() 的区别

Java教科书: "the size of an array must be known at compile time"

java - Hibernate多对多映射到同一实体单向

hibernate - 如何使用@NotNull