假设我有两个不同的线程T1和T2,同时访问同一数据库并从同一张表中提取数据。
现在在线程启动时,我需要从表中获取数据并将行存储到集合中,然后在其他地方使用该集合执行一些工作。我不希望这两个线程能够处理相同的数据,因为这将导致重复(而且很长)的工作。更具体地说,这是一个企业应用程序,需要在启动时加载一些记录并将其存储在集合中以执行一些额外的工作。问题是,在群集环境中,这可能会导致两个不同的实例加载相同的数据,因此工作可能会重复。因此,我希望行只由单个实例加载一次。
如何避免这种情况?
我目前正在使用Hibernate和Oracle 10g。这些是我迄今为止的解决方案:
通过编程锁定行。第一个读取它的人将某个“锁定”列设置为true,但如果第一个线程死亡而没有将行设置为“处理”,则非常容易发生死锁。
使用悲观锁。我尝试使用LockMode.UPGRADE,但似乎无济于事,因为我仍然能够同时从两个线程读取数据。
public List<MyObject> getAllNtfFromDb() {
Session session = HibernateUtil.getOraclesessionfactory().openSession();
Query q = session.createQuery(
"from MyObject n where n.state = 'NEW'");
List<MyObject> list = (List<MyObject>) q.list();
for (int i=0; i<list.size(); i++)
session.lock(list.get(i), LockMode.UPGRADE);
return list;
}
还有其他提示吗?我做错了什么吗?谢谢。
Session session = HibernateUtil.getOraclesessionfactory().openSession();
? - Orby