java 使用休眠锁定表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/30323459/
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-11-02 16:54:21  来源:igfitidea点击:

Locking a table with hibernate

javamysqlhibernate

提问by user2162550

I have a Client-Server app, and in my server I'm using hibernate for database handling. Now, my app requires among all the database tables, a simple table with only one row of one Bigintegerfield (which is the key in this row) in it. This table will actually contain only a global number (starting from 1) which I use every time a user performing some action, and when he does, I need to get this value, and increment the value in the database. (the table shoud contain only one row with only one value all the time)

我有一个客户端-服务器应用程序,在我的服务器中我使用 hibernate 进行数据库处理。现在,我的应用程序需要在所有数据库表中,一个简单的表,其中只有一行一个Biginteger字段(这是该行中的键)。这个表实际上只包含一个全局数字(从 1 开始),我每次用户执行某些操作时都会使用它,当他这样做时,我需要获取这个值,并增加数据库中的值。(该表应该只包含一行,并且始终只有一个值)

I'm using the following code to accomplish that:

我正在使用以下代码来完成它:

 Biginteger func() {
        Session s = null;
        Biginteger idToReturn=null;
        try{
           s=factory.openSession();
           s.beginTransaction();
           Query queryResult =  s.createQuery("from GlobalId");
           List<GlobalID> theId=queryResult.list();
           idToReturn=theId.get(0).get_id();                     //getting the value from db to return
           GlobalID toSave=new GlobalId();
           toSave.set_id(idToReturn.add(BigInteger.valueOf(1))); //incrementing the id from db inorder to save it
           s.delete(theId.get(0));                               //deleting old id
           s.save(toSave);                                       //saving new id
           s.getTransaction().commit();
        }
        catch(Exception e){
            throw e;
        }
        finally{
            if (s!=null)
               s.close();
            return idToReturn;
        }
 }

This code works fine. My concern is about if I'll need to use more than one server to approach a central database. In that case, if two seperate servers will run this function, I need to eliminate the case that the two of them will get the same value. I need to make sure the entire read and write will be "atomic", I need to lock this table so no more than one session will be able to read the value, and I also need to make sure in case the session ended unexpectedly, the lock will be removed.

这段代码工作正常。我担心的是我是否需要使用多个服务器来访问中央数据库。在这种情况下,如果两个单独的服务器将运行此功能,我需要消除它们两个将获得相同值的情况。我需要确保整个读写都是“原子的”,我需要锁定这个表,这样只有一个会话才能读取该值,我还需要确保会话意外结束,锁将被移除。

I'm using the xampp bundle including MySQL 5.6 database.

我正在使用包含 MySQL 5.6 数据库的 xampp 包。

The informationI found online regarding this issue is confusing to me- the information I found is "high level" and I could not find any examples.

我在网上找到的关于这个问题的信息让我感到困惑——我找到的信息是“高级”的,我找不到任何例子。

采纳答案by rghome

You need to use pessimistic locking, which can be achieved by

您需要使用悲观锁定,这可以通过

setLockMode(String alias, LockMode lockMode) 

on the query and use LockMode.UPGRADE.

关于查询和使用LockMode.UPGRADE

See Query.setLockMode

参见Query.setLockMode

However, this will certainly kill scalability and performance if you are doing a lot of access on this table. You are better either using a sequence or another strategy is to create a service to allocate numbers (e.g., an SSB) which grabs 100 numbers at a time, updates the database, and hands them out. That saves you 198 database accesses.

但是,如果您对该表进行大量访问,这肯定会扼杀可扩展性和性能。您最好使用序列或另一种策略是创建一个服务来分配号码(例如,SSB),该服务一次抓取 100 个号码,更新数据库,然后将它们分发出去。这为您节省了 198 次数据库访问。

UPDATE:

更新:

You will also have to modify your table design slightly. It is better to have a single row with a known ID and to store the number you are incrementing in another column. Then you should update the row rather than deleting the old row and adding a new one. Otherwise, the row locking strategy won't work.

您还必须稍微修改您的表格设计。最好有一个具有已知 ID 的单行,并将您要增加的数字存储在另一列中。然后您应该更新该行而不是删除旧行并添加新行。否则,行锁定策略将不起作用。

UPDATE2:

更新2:

OP found that the following worked:

OP发现以下方法有效:

session.get(class.Class, id, lockOption)