天天看点

hibernate以及mybatis的缓存、预编译、延迟加载(也就是懒加载)和批处理的含义和区别

说到这几个概念,不知道大家有没有和我一样的感觉,刚开始学习框架的时候总是傻傻的分不清,甚至在刚学习jdbc的PreparedStatement的时候,就只知道它是预编译的,更加安全,效率更高。并不知道为什么。但是在这篇文章中,我将尝试着将这几个概念和其中的原理描述出来,如果我有什么不对的地方,请大家帮我提出来,

首先从最开始的时候开始吧

            预编译:预编译的原理就是先将一个带占位符的SQL语句,发送到数据库的缓存中去,但是不执行,然后等到用户或者将占位符替换成变量并且执行的时候在从数据库的缓存中拿出来进行DQL,或者DML操作,这样不用每次改变条件的时候都要发送一次SQL语句,实现了一次发送动态修改。并且还防止了SQL注入的风险

String sql = "insert into emp values(?,?)";
			PreparedStatement ps =conn.prepareStatement(sql);//发送到数据库缓存
			ps.setString(1, emp.getEname());//替换变量
			ps.setString(2, emp.getJob());
                        ps.executeUpdate();//执行操作
           

        批处理:所谓批处理,就是一次执行很多个SQL语句,并不是一次一次的执行,原理也是将多个SQL语句发送到数据库缓存中,然后执行的时候,一次执行所欲的sql语句,这样的话,减少了操作数据库的次数,减轻了数据库的压力,自然速度就变快了

        hibernate和mybaits中的缓存:、

    一级缓存就是在一个连接对象中,hibernate是session,mybaits是sqlsession,就拿session来代替这两个了,在session中有一个hashmap的数据结构,当你第一次查询数据的时候,把查到的数据放到这个hashmap中,这个hashmap就是,一级缓存,当第二次查询同样的数据的时候,就不会向数据库发送SQL语句了,而是直接从这个hashmap中查到数据,并且显示出来,但是这里面有一个问题就是,当我们进行DML操作,也就是增删改的时候,数据表中的数据查询到的数据就会变化,此时hashmap中的数据可能是不对的,也就是我们通常称为的脏读,所以在这两个框架的中,当进行DML操作的时候,session中的hashmap的数据就会清空。二级缓存是什么呢?二级缓存通常是dao类或者mapper对象,将查到的数据序列化到硬盘上面,然后就是同样的道理了

        延迟加载

                我们都知道在做项目的时候,通常会写实体类,而实体类就避免不了有多表关联的情况,比如一个表中有一个外键,这个外键关联另一个表的主键,那么在Java程序中怎么表示这种关系呢?就是在一个实体类中存在另一个实体类,在另一个实体类中存在这个类的集合。比如user类和order(订单)类,一个user中可以含有多个订单,一个订单只能被一个用户所拥有,这是典型的多表关联,当我们查询订单所属的用户的时候,这个时候就会进行关联查询。那么在数据库中该怎么写呢?写个简单的例子把:select user.*,orders.* from user,orders where user.uid = orders.uid 。这就得到了两张表的信息,然后将其分别封装到两个Java类中,就得到了订单所属的用户,可是这怎么实现延迟加载呢?答案是这种方式不能实现延迟加载,只不过通常我们的思维是这样的,而延迟加载在数据库中所执行的SQL语句应该是这样的,select orders.*, (select user.* from user where orders.uid=user.uid) from orders;这个时候该是延迟加载上场的时候了,我们先查询订单select orders.* from orders,如果使用者需要用户的信息,在进行查询 select user.* from user where orders.uid=user.uid,如果暂时不需要,那么这句话就免了,即不查询了,这不就减少了一查询操作了吗,就没必要将orders类中user对象也封装了。如此就可以高度利用数据库了