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

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

作者: 凡哥爱丽姐 | 来源:发表于2020-11-12 14:22 被阅读0次

    幻读

    幻读是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。幻读是指当事务不是独立执行时发生的一种现象。事务A读取与搜索条件相匹配的若干行。事务B以插入或删除行等方式来修改事务A的结果集,然后再提交。

    幻读

    示例:

    1、UserDao接口

    public interface UserDao {
         public void update3();
         public void insert3();
         public List find3();
    }
    

    2、UserDaoImpl实现类

    public class UserDaoImpl extends JdbcDaoSupport implements UserDao{
      //幻读(虚读)
    public void update3() {
        String sql="update user set money=888";
        getJdbcTemplate().update(sql);
    }
    
    public void insert3() {
        String sql="insert into user(id,money) values(3,8888)";
        getJdbcTemplate().update(sql);
    }
    
    //出现幻读:@Transactional(isolation = Isolation.REPEATABLE_READ)
    @Transactional(isolation = Isolation.SERIALIZABLE)
    public List find3() {
        System.out.println("查询进入");
        List before=getJdbcTemplate().queryForList("select * from user");
    
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        update3();
        List after=getJdbcTemplate().queryForList("select * from user");
    
        List list2=new ArrayList();
        list2.add(before);
        list2.add(after);
        return list2;
    }
    }
    

    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 Test3 {
        ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
    
        class  A extends  Thread{
            public void run(){
                System.out.println("查询线程开始");
                UsersDao dao=(UsersDao) app.getBean("userdao");
                List list=dao.find3();
                System.out.println("before:"+list.get(0));
                System.out.println("after:"+list.get(1));
            }
        }
        class  B extends  Thread{
            public void run(){
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("新增线程开始");
                UsersDao dao=(UsersDao) app.getBean("userdao");
                dao.insert3();
            }
        }
        //A线程先查询一次结果,B线程新增一条新的数据,然后A线程更新当前表中的数据,
    //A线程查询第二次结果
        public static void main(String[] args) {
            Test3 test1=new Test3();
            Test3.A a=test1.new A();
            Test3.B b=test1.new B();
            a.start();
            b.start();
        }
    }
    

    相关文章

      网友评论

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

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