我有一个客户端服务器应用程序,并且在我的服务器中,我正在使用hibernate模式进行数据库处理。现在,我的应用程序需要所有数据库表中的一个简单表,其中仅一个行包含一个Biginteger字段(这是该行的键)。该表实际上仅包含一个全局编号(从1开始),我在用户每次执行某些操作时都会使用该编号,当他执行此操作时,我需要获取该值并在数据库中递增该值。(表应该只包含一行,并且始终只有一个值)
Biginteger
我正在使用以下代码来完成该任务:
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; } }
此代码可以正常工作。我担心的是,是否需要使用多台服务器来访问中央数据库。在这种情况下,如果两个单独的服务器将运行此功能,则我需要消除两个服务器将获得相同值的情况。我需要确保整个读取和写入都是“原子的”,我需要锁定该表,以便不超过一个会话能够读取该值,并且我还需要确保万一会话意外结束,锁将被移除。
我正在使用包括MySQL 5.6数据库的xampp软件包。
我在网上找到的有关此问题的信息使我感到困惑-我发现的信息是“高级”的,我找不到任何示例。
您需要使用悲观锁定,这可以通过
setLockMode(String alias, LockMode lockMode)
关于查询和使用LockMode.UPGRADE。
LockMode.UPGRADE
请参阅Query.setLockMode
但是,如果您对此表进行大量访问,那么这肯定会破坏可伸缩性和性能。您最好使用序列或另一种策略来创建一个分配数字的服务(例如,SSB),该服务一次可以获取100个数字,更新数据库并将其分发出去。这样可以节省198次数据库访问。
更新:
您还必须稍微修改表格设计。最好有一个具有已知ID的单行,然后将要递增的数字存储在另一列中。然后,您应该更新该行,而不是删除旧行并添加新行。否则,行锁定策略将不起作用。
UPDATE2:
OP发现以下工作有效:
session.get(class.Class, id, lockOption)