2012-06-18 3 views
3

Я пытаюсь понять уровни изоляции весенних транзакций. Вот пример, я использую:Уровень изоляции READ_UNCOMMITTED не работает

@Component 
public class BookShop { 

    private Object lockObj = new Object(); 

    @Autowired 
    private BookDao bookDao; 

    @Transactional 
    public void increaseStock(int isbn, int increment){ 
     String threadName = Thread.currentThread().getName(); 
     synchronized (lockObj) { 
      Book book = bookDao.findByIsbn(isbn); 
      System.out.println(threadName+" about to increment the stock"); 
      bookDao.updateStock(book, 5); 
     } 
     System.out.println(threadName+" has increased the stock "); 
     sleep(threadName); 
     System.out.println(threadName+" rolled back stock"); 
     throw new RuntimeException("Stock increased by mistake"); 
    } 

    @Transactional 
    public int checkStock(int isbn){ 
     int stock = 0; 
     String threadName = Thread.currentThread().getName(); 
     synchronized (lockObj) { 
      System.out.println(threadName+" checking for the stock"); 
      stock = bookDao.getStock(isbn); 
     } 
     System.out.println(threadName+": Stock is: "+stock); 
     sleep(threadName); 
     return stock; 
    } 

    private void sleep(String threadName){ 
     System.out.println(threadName+" sleeping"); 
     try{ 
      Thread.sleep(1000); 
     }catch (InterruptedException e) { 
     } 
     System.out.println(threadName+" wakeup!"); 
    } 

} 

И это так, как я вызова выше:

public void testIsolationLevels(final BookShop bookShop, final int isbn){ 
     Thread t1 = new Thread(){ 
      public void run() { 
       bookShop.increaseStock(isbn, 5); 
      }; 
     }; 
     t1.setPriority(Thread.MAX_PRIORITY); 
     t1.start(); 

     Thread t2 = new Thread(){ 
      public void run() { 
       bookShop.checkStock(isbn); 
      }; 
     }; 
     t2.setPriority(Thread.MIN_PRIORITY); 
     t2.start(); 
    } 

А вот сделка конфигурации:

<tx:advice id="bookTxn" transaction-manager="transactionManager"> 
     <tx:attributes> 
      <tx:method name="updateStock" isolation="READ_UNCOMMITTED"/> 
      <tx:method name="getStock" isolation="READ_UNCOMMITTED"/> 
     </tx:attributes> 
    </tx:advice> 

    <aop:config> 
     <aop:pointcut expression="execution(* com.pramati.springIdol.dao.BookDao+.*(..))" id="bookPC"/> 
     <aop:advisor advice-ref="bookTxn" pointcut-ref="bookPC"/> 
    </aop:config> 

Но когда я выполните приведенный ниже пример: здесь находится o/p:

Thread-2 about to increment the stock// Initially it is 99 
Thread-2 has increased the stock // Now it is 104(99+5) 
Thread-2 sleeping 
Thread-3 checking for the stock 
Thread-3: Stock is: 99//Why is it not 104 even if isolation level is read_uncommitted?? 
Thread-3 sleeping 
Thread-2 wakeup! 
Thread-2 rolled back stock 
Thread-3 wakeup! 
Exception in thread "Thread-2" java.lang.RuntimeException: Stock increased by mistake 

Я думал, что Thread-3 сможет прочитать обновленное значение. Но это не так. Может кто-нибудь, пожалуйста, сообщите мне, где я ошибаюсь?

Спасибо заранее!

+0

Какие базы данных вы используете? – axtavt

+0

Я использую MySql – PrasanthNath

ответ

2

Проблема заключается в том, что я вызываю транзакционные методы DAO из другого транзакционного метода (методы BookShop).

Поскольку я не указывал уровень изоляции для метода BookShop, уровнем изоляции по умолчанию является Isolation.READ_COMMITTED.

Также обратите внимание, что я не указал поведение распространения для метода Дао, а поведение по умолчанию - распространение. ПРЕДУПРЕЖДЕНИЕ. Следовательно, методы dao используют ту же транзакцию, что и в BookShop. Поэтому для транзакции применяется изоляция Isolation.READ_COMMITTED.

Решение: Укажите уровень изоляции методов BOOKSHOP как READ_UNCOMMITTED