2013-02-23 71 views
0

我正在尝试开发一个演示来强化我对REPEATABLE_READ隔离级别的理解。我尝试过使用hibernate和jdbc进行演示。 JDBC按预期工作,但休眠不。事务隔离级别REPEATABLE_READ使用休眠和jdbc

我的期望是,如果我在一个会话中读取数据库行,并尝试从另一个会话写入同一行,它应该阻塞,直到第一个会话结束。当我在线程0和睡眠中获得一个对象(行),并且在线程1中我们尝试更新同一个对象(行)时,线程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"); 
    } 
} 

hibernate.connection.url是JDBC:德比:隔离;创建=真和hibernate.connection.isolation是。我创建了HibernateExample7_IsolationRR_Thread的两个对象,并创建了Thread 0获取车辆并长时间睡眠的场景。同时线程1试图获取和更新车辆。它甚至在线程0提交之前成功提交。

由于REPEATABLE_READ隔离级别,T1不应等待提交。如果不是,那么它是READ_COMMITED隔离级别而不是REPEATABLE_READ隔离级别。

+0

您正在使用什么版本,如果HSQLDB? – sharakan 2013-02-23 03:56:42

+0

hsqldb 2.2.8版 – 2013-02-23 04:41:51

回答

1

你的期望是错的。可重复读取并不意味着一个事务应该阻塞,而另一个事务读取同一行。这意味着即使另一个事务在第一次读取和第二次读取之间提交了对该行的更改,在同一事务中读取同一行两次也应该返回相同的数据。

由于第二次读取将从第一级缓存中返回数据而根本不需要访问数据库,因此可以免费使用Hibernate(或多或少)。

http://en.wikipedia.org/wiki/Isolation_%28database_systems%29#Non-repeatable_reads

而且,你让你的测试与不支持此隔离级别数据库:

http://www.hsqldb.org/doc/2.0/guide/dbproperties-chapt.html#N15385

+0

Nitpicky:他会达到二级缓存,对吧?每个线程都有自己的会话。 – sharakan 2013-02-23 13:50:00

+0

@sharakan:没有。一个单线程,在同一事务中获得两次相同的实体,将首次触及数据库,第二次触及第一级缓存。因此,它将具有可重复的读取,因为第一级缓存将返回第一次返回的相同数据(当然,除非在读取之间对实体进行了一些更改)。 – 2013-02-23 13:52:49

+0

同意,但他有两个独立的线程,每个线程调用.openSession,因此有单独的第一级缓存。 – sharakan 2013-02-23 15:07:46