刘悦栋SSH史上最牛逼的SSH三大框架讲解之Hibernate(学习笔记)——(一)

刘悦栋SSH史上最牛逼的SSH三大框架讲解之Hibernate

https://www.kanbilibili.com/video/av21895930/index_11.html

 

IDEA自动生数据库中table对应的实体类和hibernate的映射文件

注意有坑:这样会修改你的hibernate.cfg.xml文件。

 

sql99:

DDL:数据库定义(Definition)语言,database table column的crud

DML:数据库操纵(Manipulation)语言,table中行的crud

DCL:数据库控制(Control)语言,权限,事务

 

sessionFactory

① 耗费资源较大

从Hibernate配置文件可以看出主要就是配置sessionFactory

 

 

② 线程安全的(获得的各个session独立)

new Configuration().buildSessionFactory().openSession()得到一个新session

getCurrentSession()就是获得当前线程绑定的session

 

 

 

hibernate提供的增删改查:

save(Object)

对应sql的一次insert,相当于把对象的各个属性拿出来,对应到insert语句中:

INSERT into tableName(col1,col2...coln) values(value1,value2...valuen);

上面的tableName通过解析entity.hbm.xml或者注解得到,(col1,col2...coln) 和(value1,value2...valuen)的映射关系也通过entity.hbm.xml得到(一个对象的各个属性(getter得到)insert到表中哪些列中去),不过对于主键列要看entity.hbm.xml的generator的策略,一般都是native或identity,即使用数据库的自增属性,那么插入时候的sql (col1,col2...coln)的列中是没有id列的,让数据库自动自增。

 

 

 

select(args)

对应sql的一次select

一般而言使用的都是id查询,过程和save差不多

 

 

update(Object)

注意参数是Object类型,没有id选项!!

真正实现修改需要session.get方法,和session.update方法

所以对应sql的一次select和一次update

因为本身hibernate update的过程就是先get(具体哪种参数的get不定),用对象接收,利用setter方法修改对象属性,再save对象:

Student stu = session.get(Student.class,5);

stu.setCity("Beijing");

session.save(stu);

这样做的性能太差了:

① get的过程复杂性就未知,需求是修改特定id用户的信息还好,因为get的过程直接调用session的getById(int id)这个API即可,但是如果是修改所有城市为Shanghai的用户,那么get的过程可能就很复杂

当然有个思路:前台无论需要什么数据,只要会设计到后续修改的,全都把id传过去,这样在修改时可以传回id,get过程保证都能用getById(int id)这个API,但是这样做的坏处是:一来信息冗余,多处理了信息(其实可以忽略嘛,一个id而已),二来这个信息肯定一直到了前台,暴露了用户在数据库中的真实信息,这个就特别不好了

② 通过session.get拿到该对象之后,是使用实体类的setter方法“修改”该值,再调用session.update()方法,过程肯定和select和delete方法一样,拿着修改之后的对象,到数据库使用sql语句的update

这个过程中,明显发现,原本一条简单的update的语句,变成了先session.get()原始数据库row——封装成对象(反射机制)——使用该对象的setter方法完成“修改”——session.update()方法传入相应修改值到数据库——执行update方法。

开销太大了,使用Mybatis只用做最后一步的工作——送sql——update语句过去,而hibernate来来回回做了很多“开销”工作,为的就是所谓的面向对象编程。

 

 

delete(Object)

和update类似,需要先get出来,再delete。。。

Student stu = session.get(Student.class,5);

session.delete(stu);

 

 

 

换个思路,看下hibernate在上述代码执行的sql:

 

hibernate执行的sql:

可以看到,get主要是找到该记录的id,接下来delete其实就只用到了id这个参数。而其实当时get的时候就是利用id来get的(当然可以使用其他get API),这给了一点提示——我们直接拿着id自己创建对象去delete这个对象不就行了,动手:

表:

代码:

sql和结果:

表:

竟然真的删除了,而且由于我们上面没有设置name属性,执行delete时该属性应该还是默认null。这又提示我们:即使设置一个数据库表中没有对应name的Student对象,一样可以删除,动手:

结果:

表:

我们new 出来的temp设置的是id = 2,name = "这个name不存在",数据库中并没有这样的一条记录,但是session.delete()执行的sql记录可以看到,delete只用了id这个属性,故一样可以删除id = 2的属性。

明显这个方法可以减少一个数据库查询操作

 

 

主键:

自然主键:如身份证号

代理主键:本身没有任何实际意义,只是用来标识唯一性而已(满足主键要求)

 

类的属性:

有setter和getter方法就是属性,没有的就不是属性,这是充要条件

 

 

对象的三种状态:

 

 

 

使用getCurrentSession()的注意点:

① 在hibernate.cfg.xml中配置hibernate_current_session_context_class属性:thread

不然直接使用getCurrentSession()可能获得的不是绑定的session

② 使用getCurrentSession()获得的session,在事务提交后不用手动关闭(不同于openSession()得到的session),一旦事务提交hibernate会自动关闭session。

 

配置数据库隔离级别和getCurrentSession()的线程绑定:

 

 

 

session仅有的几个API都只是“等值查询”——例如getById,对于批量查询,hibernate使用下面三种策略:

 

先看hql查询;

hql思想:面向对象的操作,hql中全是类名,属性名。不会涉及到表,由hibernate作到表的映射:

① from类的全限定名,而不是表

② 如果是select * (行的全部列)则select *可以省略

条件查询:

可以看到,cust_id也是Customer类的属性名。

明显,坏处是hql还要经解析xml才能转化为数据库能识别的sql,好处就是返回结果就是对象,而不是字符串。

当然,还有传入参数的hql:问好占位符+setParameter完成传参:

当然,还有一种方式:

这种方式不用管参数在hql中的位置,利用起的名字(随便起,只要几个参数名不重复即可)去set,达到传入参数的目的。

hql分页:

 

criteria:

基本查询,传入Class对象:

条件查询:

将原本的sql语句换成Restrictions的各种静态方法,具体对应关系如下:

 

criteria的分页:

和hql差不多,具体为什么hql和criteria不支持原生sql语法+setParameter()我也不知道。。。

使用Projections的静态方法调用聚合函数:

 

 

原生sql;

基本查询:

注意用List<Object[]>接收query.list()(其实就是执行sql)的结果,因为hibernate无法识别cst_customer是什么,也不会尝试去解析,只是而且会把执行sql的结果(从数据库接收)的每一行封装成一个对象数组,n行放在List。我们接收时也只能用Object[]来接收,因为一行中的不同列类型是不一样的。

当然,我们可以手动告诉hibernate把每一行(Object[])装进什么类型中:

 

条件查询:

其实关键问题就是怎么进行参数传入而已:

跟hql一样,都是使用setParameter()方法,而且下标一样从0开始(不同于JDBC的条件查询,从1开始)。

分页查询:

很舒服,就是使用limit+setParameter完成参数传递。

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值