在Hibernate中使用COUNT(*)并且Read_Uncommitted始终被阻止

时间:2014-04-05 18:27:57

标签: mysql spring hibernate transactions

我正在使用MYSQL和Hibernate + Spring和Annotation Transaction。为了测试read_uncommitted,我运行了两个线程,一个用于在表上修改一行20次,另一个用于计算该表的总行数。虽然我将事务级别设置为read_uncommitted,但始终阻止读取总计数线程,直到修改线程完成。

public static void main(String[] args) {

        ApplicationContext ctx = new ClassPathXmlApplicationContext("spring-hibernate.xml");

        WarehouseService service = ctx.getBean("warehouseServiceImpl", WarehouseService.class);

        System.out.println("Table initialized");

        int prodId = 3;

       //By default, increment product inventory 5 at a time, repeat 10 times
        IncreaseInventoryThread thrdIncInvent = new IncreaseInventoryThread(service, prodId, 10);
        thrdIncInvent.start();
        System.out.println("Total product: "+service.countAllProducts());
}

我的IncreaseInventoryThread只需调用increaseInventory方法20次

public class IncreaseInventoryThread extends Thread {

    WarehouseService service;
    int prodId;
    int iteration;


    public IncreaseInventoryThread(WarehouseService service, int prodId, int iteration) {
        this.service = service;
        this.prodId = prodId;
        this.iteration = iteration;
    }


    @Override
    public void run() {
        for(int i=0; i<iteration; i++){
            service.increaseInventory(prodId);          
        }
    }
}

我的服务类只是修改,并读取总计数。所有交易都在这里定义

@Override
    @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_COMMITTED, readOnly=false)
    public void increaseInventory(int prodId) {
        productDao.addInvetory(prodId, DEFAULT_INC_INVENTORY);
        Product product = productDao.getProductById(prodId);
        System.out.println(product.getName()+" now has " + product.getStock());         
    }

    @Override
    @Transactional(propagation=Propagation.REQUIRED, isolation=Isolation.READ_UNCOMMITTED, readOnly=true)
    public int countAllProducts() {
        System.out.println("Transaction begins for counting");
        return (productDao.getTotalProduct());
    }

我的DAO如下:

@Repository
public class HibernateProductDao implements ProductDao {

    @Autowired 
    private SessionFactory sessionFactory;

    @Override
    public Session currentSession() {
        return this.sessionFactory.getCurrentSession();
    }

    @Override
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    @Override
    public void addInvetory(int id, int quantity) {

        Product product = getProductById(id);
        int newStock = product.getStock()+quantity;
        product.setStock(newStock);
        addProduct(product);

    }

    @Override
    public int getTotalProduct() {
        int total = 0;
        String hql = "SELECT count(product.id) FROM Product product ";
        Query query = currentSession().createQuery(hql);
        total = ((Number)query.uniqueResult()).intValue();
        return total;
    }

}

但是在我的结果中,总计数总是等到所有increaseInventory事务完成。

Table initialized
Transaction begins for counting
TV Set now has 105
TV Set now has 110
TV Set now has 115
TV Set now has 120
TV Set now has 125
TV Set now has 130
TV Set now has 135
TV Set now has 140
TV Set now has 145
TV Set now has 150
Total product: 7

有人知道为什么吗?不是read_uncommitted不需要X-lock

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"

    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

    <context:annotation-config />    

    <context:component-scan base-package="com.cmpt.project.persistence"/>
    <context:component-scan base-package="com.cmpt.project.service"/>

    <bean id="dataSource"
        class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/test_db"></property>
        <property name="username" value="xxxx"></property>
        <property name="password" value="xxxx"></property> 
        <property name="initialSize" value="5"></property>
        <property name="maxActive" value="10"></property>
    </bean>


    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="packagesToScan"
            value="com.cmpt.project.model">
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="dialect">org.hibernate.dialect.MySQLDialect</prop> 
                <prop key="hibernate.show_sql">false</prop>
                <prop key="hibernate.hbm2ddl.auto">create</prop>
                <prop key="hibernate.connection.autocommit">false</prop>
            </props>
        </property>
    </bean>


    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"></property>
    </bean>

    <tx:annotation-driven/>

</beans>

0 个答案:

没有答案