使用hibernate和jdbc的事务隔离级别可重复读取
我正试图开发一个演示来巩固我对可重复读取隔离级别的理解。我尝试过使用hibernate和jdbc进行演示。JDBC按预期工作,但hibernate没有 我的期望是,如果我在一个会话中读取一个数据库行,并尝试从另一个会话中写入同一行,那么它将阻塞,直到第一个会话完成 Hibernate:-当我在线程0中“获取”一个对象(行)并休眠时,在线程1中我们尝试更新相同的对象(行),线程1应该等待线程0提交使用hibernate和jdbc的事务隔离级别可重复读取,hibernate,jdbc,transactions,Hibernate,Jdbc,Transactions,我正试图开发一个演示来巩固我对可重复读取隔离级别的理解。我尝试过使用hibernate和jdbc进行演示。JDBC按预期工作,但hibernate没有 我的期望是,如果我在一个会话中读取一个数据库行,并尝试从另一个会话中写入同一行,那么它将阻塞,直到第一个会话完成 Hibernate:-当我在线程0中“获取”一个对象(行)并休眠时,在线程1中我们尝试更新相同的对象(行),线程1应该等待线程0提交 class HibernateExample7_IsolationRR_Read_Write_Thr
class HibernateExample7_IsolationRR_Read_Write_Thread implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(HibernateExample7_IsolationRR_Read_Write_Thread.class);
SessionFactory sessionFactory;
int sleep;
int newnumberplate;
public HibernateExample7_IsolationRR_Read_Write_Thread(SessionFactory sessionFactory, int sleep, int newnumberplate) {
this.sessionFactory = sessionFactory;
this.sleep = sleep;
this.newnumberplate = newnumberplate;
}
public void run() {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
logger.info("TRYING TO GET VEHICLE 1");
Vehicle vid1 = (Vehicle) session.get(Vehicle.class, Integer.valueOf(1));
logger.info("GOT VEHICLE 1");
vid1.setNumberplate(this.newnumberplate);
logger.info("SET NUMBERPLATE FOR 1");
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
tx.commit();
session.close();
logger.info("COMMITED");
}
}
hibernate.connection.urljdbc:derby:isolation;create=true,hibernate.connection.isolation为2。我创建了两个HibernateExample7_IsolationRR_线程的对象,并创建了一个场景,其中线程0获取车辆并长时间睡眠。同时线程1尝试获取并更新车辆。它甚至在线程0提交之前就已成功提交
class HibernateExample7_IsolationRR_Read_Write_Thread implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(HibernateExample7_IsolationRR_Read_Write_Thread.class);
SessionFactory sessionFactory;
int sleep;
int newnumberplate;
public HibernateExample7_IsolationRR_Read_Write_Thread(SessionFactory sessionFactory, int sleep, int newnumberplate) {
this.sessionFactory = sessionFactory;
this.sleep = sleep;
this.newnumberplate = newnumberplate;
}
public void run() {
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
logger.info("TRYING TO GET VEHICLE 1");
Vehicle vid1 = (Vehicle) session.get(Vehicle.class, Integer.valueOf(1));
logger.info("GOT VEHICLE 1");
vid1.setNumberplate(this.newnumberplate);
logger.info("SET NUMBERPLATE FOR 1");
try {
Thread.sleep(sleep);
} catch (InterruptedException e) {
e.printStackTrace();
}
tx.commit();
session.close();
logger.info("COMMITED");
}
}
由于可重复读取隔离级别,T1不应该等待提交。如果不是,那么它是一个读承诺的隔离级别,而不是一个可重复的读隔离级别。您的期望是错误的。可重复读取并不意味着一个事务应该在另一个事务读取同一行时阻塞。这意味着在同一事务中读取同一行两次应该返回相同的数据,即使另一个事务在第一次读取和第二次读取之间提交了对此行的更改 您可以通过Hibernate免费获得(或多或少),因为第二次读取将从一级缓存返回数据,而根本不进入数据库 看 此外,您正在使用不支持此隔离级别的数据库进行测试:
如果您使用的是hsqldb,那么您会使用什么版本?挑剔:他会使用二级缓存,对吗?每个线程都有自己的会话。@sharakan:否。单个线程在同一事务中两次获取同一实体,第一次命中数据库,第二次命中一级缓存。因此,它将具有可重复的读取,因为一级缓存将返回第一次返回的相同数据(当然,除非在读取之间对实体进行了一些更改)。同意,但他有两个单独的线程,每个线程调用.openSession,因此有单独的一级缓存。这正是我的观点。每个线程都有自己的一级缓存,因此不受其他线程的影响,这将导致在单个线程内可重复读取,因为一级缓存没有与其他线程共享。啊,我明白你的意思了。当您这样说时,我想:“……因为第二次读取将从一级缓存返回数据,而根本不去数据库。”在他的示例中,您指的是从第二个线程读取的数据。我的错误。