美文网首页
【脏读】Spring事务的并发问题(脏读,不可重复读、幻读)

【脏读】Spring事务的并发问题(脏读,不可重复读、幻读)

作者: 凡哥爱丽姐 | 来源:发表于2020-11-04 14:07 被阅读0次
    图片.png

    脏读

    脏读指一个事务读取了另外一个事务未提交的数据。如果第一个事务这时候回滚了,那么第二个事务就读到脏数据了。

    脏读又称无效数据的读出,是指在数据库访问中,事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的。

    读脏数据.png

    示例:

    1、UserDao接口

    public interface UserDao {
       //读脏数据测试
        public void insert1();
    
        public List find1();
    }
    

    2、UserDaoImpl实现类

    public class UserDaoImpl extends JdbcDaoSupport implements UserDao {
     //读脏数据测试
        @Transactional
        public void insert1() {
            String sql="insert into user(id,name,money) values(3,'王五',2222)";
            getJdbcTemplate().update(sql);
    
            try {
                Thread.sleep(6000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("新增结束!");
            System.out.println(5/0);
        }
    
        //测试读脏数据
        @Transactional(isolation = Isolation.READ_UNCOMMITTED)
       //解决脏读: @Transactional(isolation = Isolation.READ_COMMITTED)
        public List find1(){
            List list = getJdbcTemplate().queryForList("select * from user");
            return list;
        }
    
    }
    

    3、applicationContext.xml

    <?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:p="http://www.springframework.org/schema/p"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans 
                               http://www.springframework.org/schema/beans/spring-beans.xsd
                               http://www.springframework.org/schema/tx
                               http://www.springframework.org/schema/tx/spring-tx.xsd">
    
        <!--1、指定数据源-->
        <bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/weifan"></property>
            <property name="user" value="root"></property>
            <property name="password" value="root"></property>
        </bean>
    
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <constructor-arg index="0" ref="datasource"></constructor-arg>
        </bean>
    
        <bean id="userDao" class="dao.impl.UserDaoImpl">
            <property name="jdbcTemplate" ref="jdbcTemplate"></property>
        </bean>
    
        <!--1、创建事务管理器对象-->
        <bean id="tx"  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="datasource"/>
        </bean>
    
        <!--① 对标注@Transactional注解的Bean进行加工处理,以织入事物管理切面 -->
        <tx:annotation-driven transaction-manager="tx" />
    </beans>
    

    4、测试类

    public class Test1 {
        ApplicationContext app=
                new ClassPathXmlApplicationContext("applicationContext.xml");
    
        class  A extends  Thread{
            public void run(){
                System.out.println("查询线程开始");
                UserDao dao=(UserDao) app.getBean("userDao");
    
                for (int i = 0; i < 5; i++) {
                    List list=dao.find1();
                    System.out.println("list="+list);
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        class  B extends  Thread{
            public void run(){
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("新增线程开始");
                UserDao dao=(UserDao) app.getBean("userDao");
                dao.insert1();
            }
        }
    
        public static void main(String[] args) {
            //脏读
            Test1 test1=new Test1();
            Test1.A a=test1.new A();
            Test1.B b=test1.new B();
            a.start();
            b.start();
        }
    }
    

    测试结果

    读脏数据结果.png

    解决脏读:

    @Transactional(isolation = Isolation.READ_COMMITTED)
    
    解决读脏数据.png

    相关文章

      网友评论

          本文标题:【脏读】Spring事务的并发问题(脏读,不可重复读、幻读)

          本文链接:https://www.haomeiwen.com/subject/myrnmktx.html