• 013 session_flush


    在hibernate中也存在flush这个功能,在默认的情况下session.commit()之前时,其实执行了一个flush命令。

    Session.flush功能:

    ②理缓存;

         ②执行sql(确定是执行SQL语句(确定生成update、insert、delete语句等),然后执行SQL语句。)

    Session在什么情况下执行flush:

    ① 默认在事务提交时执行;

    ②可以显示的调用flush;

    ③在执行查询前,如:iterate.

    注:

    如果主键生成策略是uuid等不是由数据库生成的,则session.save()时并不会发出SQL语句,只有flush时才会发出SQL语句

    ,但如果主键生成策略是native由数据库生成的,则session.save的同时就发出SQL语句。在flush时会满不在缓存。实体对象只有发出SQL语句保存在数据库中时,session缓存中的一个existsInDatabase才会为true.

    uuid主键生成策略:

     //利用Hibernate将实体类对象保存到数据库中
    
                //因为user主键生成策略采用的是uuid,所以调用完成save后,只是将user纳入session的管理
    
                //不会发出insert语句,但是id已经生成,session中的existsInDatabase状态为false
    
                session.save(user);
    
                   
    
                //调用flush,hibernate会清理缓存,执行sql
    
                //如果数据库的隔离级别设置为未提交读,那么我们可以看到flush过的数据,并且session中的exitsInDatabase为true
    
                session.flush();
    
               
    
                //提交事务
    
                //默认情况下commit操作会先执行flush清理缓存,所以不用显示调用flush
    
                //commit后数据是无法回滚的。
    
                tx.commit();

    native主键生成策略:

     //利用Hibernate将实体类对象保存到数据库中
    
                //因为user的主键生成策略为native(自动添加),所以调用session.save()后,将执行insert语句,返回由数据库生成的id
    
                //纳入了session的管理,修改了session中existsInDatabase状态为true。
    
                //如果数据库的隔离级别设置为未提交读,那么我们可以看到save过的数据  
    
                session.save(user);
    
                   
    
                //提交事务
    
                tx.commit();

    数据库的隔离级别:并发性作用。

    1、  Read Uncommited(未提交读):没有提交就可以读取到数据(发出了Insert,但没有commit就可以读取到。)很少用

    2、  Read Commited(提交读):只有提交后才可以读,常用,

    3、  Repeatable Read(可重复读):mysql默认级别, 必需提交才能见到,读取数据时数据被锁住。

    4、  Serialiazble(序列化读):最高隔离级别,串型的,你操作完了,我才可以操作,并发性特别不好,

    隔离级别

    是否存在脏读

    是否存在不可重复读

    是否存在幻读

    Read Uncommitted(未提交读)

    Y

    Y

    Y

    Read Commited(提交读)

    N

    Y(可采用悲观锁解决)

    Y

    Repeatable Read(可重复读)

    N

    N

    Y

    Serialiazble(序列化读)

     

     

     

    脏读:没有提交就可以读取到数据称为脏读

    不可重复读:再重复读一次,数据与你上的不一样。称不可重复读。

    幻读:在查询某一条件的数据,开始查询的后,别人又加入或删除些数据,再读取时与原来的数据不一样了。

    Mysql查看数据库隔离级别:

    方法:select @@tx_isolation;

    Mysql数据库修改隔离级别:

    方法:set transaction isolation level 隔离级别名称;

    例如:修改为未提交读:set transaction isolation level read uncommitted;

    Session.evict(user)方法:

    作用:从session缓存(EntityEntries属性)中逐出该对象

    但是与commit同时使用,会抛出异常
                session = HibernateUtils.getSession();
                tx = session.beginTransaction();
                User1 user = new User1();
                user.setName("李四");
                user.setPassword("123");
                user.setCreateTime(new Date());
                user.setExpireTime(new Date());           
                //利用Hibernate将实体类对象保存到数据库中
    
                //因为user主键生成策略采用的是uuid,所以调用完成save后,只是将user纳入session的管理
    
                //不会发出insert语句,但是id已经生成,session中的existsInDatabase状态为false
    
                session.save(user);               
                session.evict(user);//从session缓存(EntityEntries属性)中逐出该对象
    
            //无法成功提交,因为hibernate在清理缓存时,在session的临时集合(insertions)中取出user对象进行insert操作后需要更新entityEntries属性中的existsInDatabase为true,而我们采用evict已经将user从session中逐出了,所以找不到相关数据,无法更新,抛出异常。           
                tx.commit();

    解决在逐出session缓存中的对象不抛出异常的方法:

    在session.evict()之前进行显示的调用session.flush()方法就可以了。

    /利用Hibernate将实体类对象保存到数据库中
    
                //因为user主键生成策略采用的是uuid,所以调用完成save后,只是将user纳入session的管理
    
                //不会发出insert语句,但是id已经生成,session中的existsInDatabase状态为false
    
                session.save(user);
    
                   
    
                //flush后hibernate会清理缓存,会将user对象保存到数据库中,将session中的insertions中的user对象清除,并且会设置session中的existsInDatabase状态为false
    
                session.flush();
    
               
    
                session.evict(user);//从session缓存(EntityEntries属性)中逐出该对象
    
               
    
                //可以成功提交,因为hibernate在清理缓存时,在Session的insertions中集合中无法找到user对象所以不会发出insert语句,也不会更新session中existsInDatabase的状态。
    
                tx.commit();
  • 相关阅读:
    实验五——循环结构学习总结
    实验七——函数定义及调用总结
    实验九——基本数据类型存储及应用总结
    实验六——循环结构程序练习总结
    第二次作业及总结——数据类型和运算符
    实验八——函数定义及调用总结
    实验四——多分支结构及本章总结
    开篇随笔
    第三次作业——for 语句及分支结构elseif
    第二次作业
  • 原文地址:https://www.cnblogs.com/crazylqy/p/4078686.html
Copyright © 2020-2023  润新知