java Hibernate JPA悲观。写不起作用
我正在使用JPA2.0的Hibernate实现在表行中创建一个计数器。我在InnoDB引擎中使用MySQL 5.5。我试图锁定计数器行,以便JVM之外的进程在我的代码增加计数器之前都无法查看该计数器。我的代码如下所示:
//inside a Transaction....
//key is an enum
final PropertyKey key = PropertyKey.DEPLOY_COUNTER;
final Query query =
entityManager.createQuery("FROM Property s where propertyKey = :key").setParameter("key", key);
query.setLockMode(LockModeType.PESSIMISTIC_WRITE);
LOG.debug("Blocking (maybe) while waiting to update deploy counter");
final Property counterAsProperty = (Property) query.getSingleResult();
try
{
Thread.sleep(15000);
//while sleeping I use MySQL cli to check value of property in database
}
catch (InterruptedException e)
{
e.printStackTrace();
}
//in java, increment counter by one and then save in db
//...
我用线。SLIP()在事务中间暂停代码。当线程处于睡眠状态时,我使用MySQL CLI客户端登录数据库并检查属性的值。该课程看起来是这样的:
user@mypc [user]> begin work;
Query OK, 0 rows affected (0.00 sec)
user@mypc [user]> select * from property where property_key = 'DEPLOY_COUNTER';
+----+---------+-----------+--------------------+----------------+
| id | version | encrypted | property_key | property_value |
+----+---------+-----------+--------------------+----------------+
| 10 | 0 | 0 | DEPLOY_COUNTER | 66 |
+----+---------+-----------+--------------------+----------------+
请注意,当我预计查询将被阻止,直到线程停止睡眠并完成事务时,查询将立即返回(0.00秒)。我对LockModeType的理解。悲观的_WRITE是,它应该将检索到的行置于独占锁中,不可由另一个事务读取或写入
注意:当线程处于睡眠状态时,不会阻止对此行的更新
如果我设置了悲观写锁定模式,为什么另一个DB连接在另一个事务运行时可以查看数据
# 1 楼答案
对于select查询,这不起作用
如果您查询“选择更新”,它将起作用 然后,您的查询将等待应用程序不释放锁的时间
上面的查询将等待锁被释放
# 2 楼答案
默认的InnoDB隔离级别是REPEATABLE READ,它允许没有独占锁的事务读取(但不更新)锁定的记录。这允许其他事务对记录进行非脏读。SERIALIZABLE可防止对锁定记录进行任何读取。您可以在使用hibernate.connection.isolation设置hibernate连接属性时设置隔离级别,尽管这会影响所有连接,而不是我愿意支付的成本。这篇SO帖子指出了一种针对每个连接执行此操作的方法,但该方法需要弃用的方法:JPA and MySQL transaction isolation level
最后我用了一个
这里引用的方法:http://tedyoung.me/2011/04/14/jpa-counters-and-sequences/,不需要任何锁定