hibernate学习笔记

hibernate课程安排
第一天:hibernate入门和基本操作
第二天:hibernate概念和api使用
第三天:hibernate配置一对多和多对多
第四天:hibernate查询操作

第一天内容简介:
1、web内容回顾
(1)javaee三层结构
(2)mvc思想
2、hibernate概述
3、hibernate框架入门案例
4、hibernate配置文件
5、hibernate最基本的api使用

web内容回顾:
javaEE有三层结构
1、web层:struts2框架
2、service层:spring框架
3、dao层:hibernate框架
(1)对数据库进行crud操作
MVC思想
1、m:model,模型
2、v:view,视图
3、c:controller,控制器

Hibernate概述
什么是框架
1、写一个程序,使用框架之后,帮我们实现一部分的功能,使用框架的好处在于少写一部分代码实现功能。

什么是hibernate框架(重点)
1、Hibernate的意思是冬眠,应用在JavaEE三层结构的dao层框架
2、在dao层里面做对数据库crud操作,Hibernate底层代码就是jdbc,Hibernate对jdbc进行封装,使用Hibernate好处,不需要写复杂的jdbc代码了,不需要写sql语句实现。
3、Hibernate开源轻量级框架
4、Hibernate版本:
Hibernate3.x
Hibernate4.x
Hibernate5.x
lib:hibernate相关jar包

什么是ORM思想
1、Hibernate使用ORM思想对数据库进行CRUD操作
2、在Web阶段学习javabean,更正确的叫法——实体类
3、ORM:Object Relational Mapping,对象关系映射
文字描述:
(1)让实体类与数据库表一一对应的关系
让实体类首先与数据库表对应
让实体类属性和表里面的字段对应
(2)不需要直接操作数据库表,而操作表对应实体类对象
画图描述:
hibernate学习笔记_第1张图片

//加载驱动
Class.forName("com.mysql.jdbc.Driver");
//创建连接
Connection conn = DriverManager.getConnection(url,username,password);
//对sql进行预编译操作
String sql = "select * from user";
PreparedStatement psmt = conn.preparedStatement(sql);
//执行sql 查询sql
ResultSet rs = pstm.executeQuery();
//遍历结果集
......
//释放资源
......

public class User{
	private int uid;
	private String username;
	private String password;
	//setter getter
}
create table t_user(
	uid int,
	username varchar(100),
	password varchar(100)
);

让实体类User与表t_user一一对应
让类和表对应,让类属性和表字段对应。使用配置文件方式完成这种对应关系。不需要操作表,而操作表对应的实体类对象就可以了。hibernate封装的对象session。

//创建实体类对象
User user = new User();
user.setUsername("lucy");
session.save(user);

Hibernate的入门
搭建一个Hibernate环境
第一步:导入Hibernate的Jar包
注意,required文件夹下的jar包必须添加,jpa文件夹下的jar包也必须添加
(1)因为使用hibernate时候,会有一些日志信息输出,hibernate本身没有日志输出的jar包,导入其他日志的jar包,不要忘记还有mysql驱动的jar包。
log4j-x.x.x.jar
mysql-connector-java-x.x.x-bin.jar
slf4j-api-x.x.x.jar
slf4j-log4j12-x.x.x.jar
第二步 创建实体类
(1)使用hibernate时候,不需要自己手动创建表,hibernate帮助创建表
第三步 配置实体类和数据库表一一对应关系(映射关系)
使用配置文件来实现映射关系
(1)使用xml格式的配置文件
映射配置文件名称和位置没有固定要求
建议:在实体类所在包里面创建,实体类名称.hbm.xml
(2)配置文件是xml格式,在配置文件中首先引入xml约束
学过的约束dtd、schema,在hibernate中引入的约束dtd约束

(3)配置映射关系

<hibernate-mapping>
	
	<class name="cn.itcast.entity.User" table="t_user">
		
		
		<id name="uid" column="uid">
			
			<generator class="native">generator>
		id>
		
		<property name="username" column="username">property>
		<property name="password" column="password">property>
		<property name="address" column="address">property>
	class>
hibernate-mapping>

第四步 创建hibernate核心的配置文件
(1)核心配置文件的格式xml,但是核心配置文件的名称和位置是固定的。
位置:必须在src下
名称:必须hibernate.cfg.xml
(2)引入dtd约束

(3)hibernate操作过程中,只会加载核心配置文件,其他配置文件不会加载
第一部分 配置数据库的信息
第二部分 配置Hibernate的信息
第三部分 把映射文件放到核心的配置文件中

<hibernate-configuration>
	<session-factory>
		
		<property name="hibernate.connection.driver.class">com.mysql.cj.jdbc.Driverproperty>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8property>
		<property name="hibernate.connection.username">rootproperty>
		<property name="hibernate.connection.password">ljh_5098_CHDproperty>
		
		
		<property name="hibernate.show_sql">trueproperty>
		<property name="hibernate.format_sql">trueproperty>
		
		<property name="hdm2ddl.auto">updateproperty>
		
		<property name="hibernate.dialect">property>
		
		<mapping resource="cn/itcast/entity/User.hbm.xml"/>
	session-factory>
hibernate-configuration>

实现添加操作
第一步 加载hibernate核心配置文件
第二步 创建SessionFactory对象
第三步 使用SessionFactory创建session对象
第四步 开启事务
第五步 写具体逻辑crud操作
第六步 提交事务
第七步 关闭资源
看到的效果:
(1)是否生成表(2)是否添加记录

public class HibernateDemo {
    public static void main(String[] argv){
        //第一步 加载hibernate核心配置文件
        //到src下面找到hibernate.cfg.xml
        //在hibernate里面封装对象
        Configuration cfg = new Configuration();
        cfg.configure();

        //第二步 创建SessionFactory对象
        //读取hibernate核心配置文件内容,创建SessionFactory
        //在该过程之中,根据映射关系创建表
        SessionFactory sessionFactory=cfg.buildSessionFactory();

        //第三步 使用SessionFactory创建session对象
        //类似于连接
        Session session = sessionFactory.openSession();

        //第四步 开启事务
        Transaction tx = session.beginTransaction();

        //第五步 写具体逻辑crud操作
        //添加功能
        User user = new User();
        user.setUsername("LJH");
        user.setPassword("5098");
        user.setAddress("China");
        //调用session
        session.save(user);

        //第六步 提交事务
        tx.commit();

        //第七步 关闭资源
        session.close();
        sessionFactory.close();
    }
}

hibernate配置文件详解
hibernate映射配置文件
1、映射配置文件名称和位置没有固定要求
2、映射配置文件中,标签name属性值写实体类相关内容
(1)class标签name属性值实体类全路径
(2)id标签和property标签name属性值 实体类属性名称
3、id标签和property标签,column属性可以省略
(1)不写值和name属性值一样
4、property还有一个type属性,设置生成表字段的类型,缺省时会自动对应属性。

hibernate核心配置文件
1、配置写的位置要求

<hibernate-configuration>
    <session-factory>
    session-factory>
hibernate-configuration>

2、配置三部分要素
(1)数据库部分是必须的
(2)hibernate部分是可选的
(3)映射文件是必须的
3、核心配置文件名称和位置是固定的
(1)位置:src下
(2)名称:hibernate.cfg.xml

hibernate核心api
Configuration
1、代码

Configuration cfg = new Configuration();
cfg.configure();

(1)到src下面找到名称为hibernate.cfg.xml配置文件,创建对象,把配置文件放到对象里面(加载核心配置文件)
(2)还有其他几种配置方法,一般不使用

SessionFactory(重点)
1、使用Configuration对象可以创建SessionFactory对象
(1)创建sessionFactory过程中做事情
根据核心配置文件中,有数据库配置,有映射文件部分,到数据库中根据映射关系建表,但必须指定update。
2、创建sessionFactory过程中,这个过程非常耗资源。
(1)在hibernate操作中,建议一个项目一般创建一个sessionFactory对象
3、具体实现
(1)写工具类,写静态代码块实现
静态代码块在类加载时候执行,执行一次

public class HibernateUtils {
    private static final Configuration cfg;
    private static final SessionFactory sessionFactory;
    //静态代码块实现
    static{
        //加载核心配置文件
        Configuration cfg = new Configuration();
        cfg.configure();
        SessionFactory sessionFactory = cfg.buildSessionFactory();
    }

    //提供方法返回sessionFactory
    public static SessionFactory getSessionFactory(){
        return sessionFactory;
    }
}

Session(重点)
1、session类似于jdbc中connection
2、调用session里面不同的方法实现crud操作
(1)添加save方法
(2)修改update方法
(3)删除delete方法
(4)根据id查询get方法
3、session对象单线程对象
(1)不可共享只能独占

Transaction
1、事务对象
Transaction tx = beginTransaction();
2、事务提交和创建方法
tx.commit();
tx.rollback();
3、事务相关的概念
(1)事务四个概念ACID
原子性:事务中的操作不可分割
一致性:执行事务前后数据库状态不变
隔离性:不同事务相互独立,互不干扰
持久性:事务一经提交永久修改

解决配置文件没有提示的问题
1、可以上网
2、把约束文件引入项目
在Intelij idea中打开File->Settings,搜索xml catalog;
复制dtd约束文件的uri

第二天内容简介
1、实体类编写规则
2、hibernate主键生成策略
3、实体类中的操作
(1)crud操作
(2)实体类对象状态
4、hibernate一级缓存
5、hibernate事务操作
(1)事物代码的规范写法
6、hibernate的其他api

实体类的编写规则
1、属性私有
2、私有属性get/set方法公有
3、要求有一个属性作为唯一值
4、实体类里面的属性建议不使用基本数据类型,使用基本数据类型对应的包装类
(1)八个基本数据类型对应的包装类
int-Integer
char-Character
其他-首字母大写
(2)比如 表示学生的分数,假如int score
如果学生得了0分 int score = 0;
如果学生没有参加考试 int score = 0的写法不能准确表示这种情况
解决:使用包装类就可以,Integer score = null表示学生没有参加考试

hibernate主键生成策略
1、hibernate要求实体类中有一个属性作为唯一的值,对应表主键,主键可以有不同生成策略
2、hibernate主键生成策略
3、在class属性里面有很多值
(1)native:根据数据库类型灵活选择identity、sequence、hilo
(2)uuid:hibernate运用uuid算法生成一个32位十六进制字符串唯一标识一个元组
4、演示生成策略值uuid
(1)使用uuid的生成策略,实体类id属性必须是字符串类型
(2)配置部分修改为uuid策略

实体类操作
对实体类crud操作
添加操作
1、调用session中的save方法

//添加功能
User user = new User();
user.setUsername("QQX");
user.setPassword("5100");
user.setAddress("UK");
//调用session
session.save(user);

根据id查询
1、调用session里面的get方法

//根据id做查询
//调用session中的get方法
//第一个参数:实体类的Class
//第二个参数:id值
User user = session.get(User.class,1);
System.out.println("user = " + user);

底层查询语句

Hibernate: 
    select
        user0_.uid as uid1_0_0_,
        user0_.username as username2_0_0_,
        user0_.password as password3_0_0_,
        user0_.address as address4_0_0_ 
    from
        user user0_ 
    where
        user0_.uid=?

修改操作
1、首先查询,修改值
(1)先根据id查询,后返回

//修改操作
//根据id进行查询
User user = session.get(User.class,2);
//向返回的User对象中设置值
user.setUsername("YP");
//调用session的方法update修改
session.update(user);
//到user对象中找到uid的值,根据uid进行修改

底层SQL语句

Hibernate: 
    select
        user0_.uid as uid1_0_0_,
        user0_.username as username2_0_0_,
        user0_.password as password3_0_0_,
        user0_.address as address4_0_0_ 
    from
        user user0_ 
    where
        user0_.uid=?
Hibernate: 
    update
        user 
    set
        username=?,
        password=?,
        address=? 
    where
        uid=?

删除操作
1、调用session里面的delete方法实现
第一种方式:

//第一种方式:先查后删
User user = session.get(User.class,2);
session.delete(user);
Hibernate: 
    select
        user0_.uid as uid1_0_0_,
        user0_.username as username2_0_0_,
        user0_.password as password3_0_0_,
        user0_.address as address4_0_0_ 
    from
        user user0_ 
    where
        user0_.uid=?
Hibernate: 
    delete 
    from
        user 
    where
        uid=?

第二种方式:

//第二种方式:先创建对象再删除
User user = new User();
user.setUid(3);
session.delete(user);
Hibernate: 
    delete 
    from
        user 
    where
        uid=?

注意,使用update修改时,所有属性都会被修改。

实体类对象的状态(概念)
1、实体类的状态有三种
(1)瞬时态,对象里面没有id值,对象与session没有关系

User user = new User();
user.setUsername("QQX");
user.setPassword("5100");
user.setAddress("UK");

(2)持久态,对象里面有id值,对象与session也有关系

User user = session.get(User.class,1);

(3)托管态,对象里面有id值,对象与session无关

User user = new User();
user.setUid(3);

2、演示操作实体类对象的方法
(1)saveOrUpdate方法,实现添加或修改

//saveOrUpdate
User user = new User();
user.setUsername("LB");
user.setPassword("520");
user.setAddress("France");
//实体类对象是瞬时态时做添加操作
session.saveOrUpdate(user);

User user = new User();
user.setUid(2);
user.setUsername("LB");
user.setPassword("520");
user.setAddress("France");
//实体类对象是托管态,做修改操作
session.saveOrUpdate(user);

User user = session.get(User.class,1);
user.setUsername("ZC");
//实体类对象是持久态,做修改操作
session.saveOrUpdate(user);

Hibernate的一级缓存
什么是缓存?
1、数据存到数据库里面,数据库的底层存储介质就是文件系统,使用流方式操作文件效率不高
(1)把数据存到内存中,不需要使用流方式,可以直接读取内存中数据
(2)把数据存到内存中,提供读取效率

Hibernate缓存
1、Hibernate框架中提供很多优化方式,hibernate中的缓存就是一种优化的方式
2、hibernate缓存特点
第一类 hibernate中的一级缓存
(1)hibernate的一级缓存默认就是打开的
(2)hibernate中的一级缓存使用范围,是session范围。

session.beginTransaction();
...(session范围)
session.close();

(3)hibernate的一级缓存中,存储数据必须持久态数据
第二类 hibernate中的二级缓存
(1)目前已经不使用,替代技术redis
(2)二级缓存默认不是打开状态,需要配置
(3)二级缓存的适用范围是sessionFactory范围

验证一级缓存的存在
1、验证的方式
(1)首先根据uid=1查询,返回对象
(2)其次再根据uid=1查询,返回对象

//测试一级缓存
//执行第一个查询后有SQL语句输出
User user = session.get(User.class,1);
System.out.println("user = " + user);
//执行第二个查询后没有SQL语句输出
User user2 = session.get(User.class,1);
System.out.println("user2 = " + user2);

输出结果:

Hibernate: 
    select
        user0_.uid as uid1_0_0_,
        user0_.username as username2_0_0_,
        user0_.password as password3_0_0_,
        user0_.address as address4_0_0_ 
    from
        user user0_ 
    where
        user0_.uid=?
user = User{uid=1, username='ZC', password='456', address='England'}
user2 = User{uid=1, username='ZC', password='456', address='England'}

结论:第一次查询使用SQL语句,第二次执行get方法之后没有执行sql语句而是访问一级缓存中的内容。

Hibernate一级缓存执行过程
hibernate学习笔记_第2张图片
第一次查询:查询一级缓存发现没有数据,查询数据库,返回持久态对象并将其放到一级缓存中。
第二次查询:从一级缓存中直接返回持久态对象。
注意:两次返回的并不是同一个对象。

hibernate一级缓存的特性
1、持久态对象会自动更新数据库

User user=session.get(User.class,1);
user.setUsername(“张三”);
//session.update(user);

执行过程:

把返回的持久态对象放到一级缓存中
把持久态对象放到一级缓存对应的快照区中
修改持久态对象的值,同时修改一级缓存中内容,但不会修改一级缓存对应的快照区
最后要提交事务时,比较一级缓存与一级缓存对应快照区的内容,如果不相同,把一级缓存中的内容更新到数据库中。

Hibernate事务操作
1、什么是事务?
2、事务特性ACID
3、不考虑隔离性产生的问题:
(1)脏读
(2)不可重复读
(3)虚读(幻读)
4、设置事务隔离级别
(1)MySQL默认隔离级别repeatable read
(2)Hibernate中事务的管理
在hibernate核心配置文件中配置:
hibernate学习笔记_第3张图片

Hibernate事务代码的规范写法
1、代码结构
try{
开启事务
提交事务
}catch(异常){
回滚事务
}finally{
关闭事务
}

代码
hibernate学习笔记_第4张图片

Hibernate绑定线程session
1、session类似于jdbc的connection,之前在web阶段学习过threadLocal
2、帮助用户实现本地线程绑定session
3、获取与本地线程绑定session
(1)在hibernate配置文件中配置
在这里插入图片描述
(2)调用sessionFactory里面的方法得到
在这里插入图片描述
4、获取与本地线程绑定的session变量后,不再需要关闭了,否则就会报错
在这里插入图片描述

Hibernate中一些api的使用
Query对象
1、使用Query对象不需要写SQL语句,但是要写HQL语句
(1)hql:Hibernate Query Language
(2)hql与sql相似,但有区别
sql操作的是表和字段,hql操作实体类和实体类里面的属性
2、查询所有的hql语句
(1)from 实体类名称
3、query对象的使用
(1)创建一个Query对象
(2)调用Query对象的方法得到结果
hibernate学习笔记_第5张图片
Criteria对象
1、使用Criteria对象查询操作,不用写查询语句,直接调用方法实现
2、实现过程
(1)创建Criteria对象
(2)调用Criteria对象的方法得到结果
hibernate学习笔记_第6张图片
SQLQuery对象
1、使用hibernate时候,调用底层的SQL语句来实现
2、实现过程
(1)创建SQLQuery对象
(2)调用对象的方法得到结果,结果以数组list的形式返回
hibernate学习笔记_第7张图片
(3)返回list每一项是对象
hibernate学习笔记_第8张图片

表与表之间的关系回顾
1、一对多
(1)分类和商品之间的关系,一个分类中可以有多个商品,一个商品中只能有一个分类
(2)客户与联系人是一对多的关系
客户:与公司有业务往来
联系人:公司员工分别负责联系不同的客户
(3)一对多关系,“多”的一方创建字段作为外键,存储“一”的一方的主键,参照数据库知识
2、多对多
(1)订单和商品之间的关系是多对多,一个订单中有多个商品,一个商品可以出现在订单中
(2)多对多关系,创建中间表
3、一对一
(1)配偶

hibernate的一对多操作
一对多映射配置
以客户与联系人为例,客户是一,联系人是多
第一步:创建实体类,客户与联系人
第二步:让这两个实体类之间先互相进行表示
(1)在客户实体类里面表示多个联系人
一个客户里面有多个联系人
hibernate学习笔记_第9张图片

(2)在联系人实体类里面表示所属的客户
hibernate学习笔记_第10张图片
第三步:配置映射关系
(1)一般一个实体类都要对应一个映射文件
(2)把映射最基本的部分完成
hibernate学习笔记_第11张图片
hibernate学习笔记_第12张图片
(3)在映射文件中配置一对多的关系
在客户映射文件中,表示所有的联系人
hibernate学习笔记_第13张图片
在联系人映射文件中表示所有的客户
在这里插入图片描述
一个联系人只能属于一个客户
第四步:在核心配置文件中引用实体类的配置文件
在这里插入图片描述
测试:
hibernate学习笔记_第14张图片

一对多的级联操作
级联操作
1、级联保存
2、级联删除

一对多级联保存:
1、添加客户,为客户添加一个联系人
(1)复杂写法
hibernate学习笔记_第15张图片
测试结果:
在这里插入图片描述
在这里插入图片描述
(2)简化写法
一般根据客户添加联系人
第一步 在客户映射文件中进行配置
在客户映射文件中set标签上进行配置
hibernate学习笔记_第16张图片
第二步 创建客户和联系人对象,把联系人放到客户中即可,最终只需要保存客户就行了
hibernate学习笔记_第17张图片

一对多级联删除
1、删除某个客户,把客户里面的所有联系人都删除
2、具体实现
第一步 在客户的映射文件中set标签,进行配置
(1)使用属性cascade值为delete
hibernate学习笔记_第18张图片
第二步 在代码中删除客户
(1)根据id查询对象
hibernate学习笔记_第19张图片
(2)根据外键的id值查询联系人
hibernate学习笔记_第20张图片
(3)把联系人的外键设为NULL
hibernate学习笔记_第21张图片
(4)删除联系人与客户
hibernate学习笔记_第22张图片

一对多修改
1 让联系人所属客户不再是baidu而是tencent
hibernate学习笔记_第23张图片
2 inverse属性
(1)LinkMan被修改了两次。因为hibernate双向维护外键,当修改联系人时修改了一次外键,当修改客户时又修改了一次外键。
hibernate学习笔记_第24张图片
(2)解决方式:让其中一方放弃外键的维护
一对多里面,让“一”的一方(也就是客户)放弃外键
一个国家有总统和平民,总统不可能认识所有平民,平民都认识总统
(3)具体实现
在放弃外键维护的一方的配置文件中进行配置,在set标签上使用inverse属性,默认为false表示不放弃,将其设置为true
在这里插入图片描述

hibernate多对多的操作
hibernate学习笔记_第25张图片
多对多映射配置
以用户与角色为例演示
第一步 创建实体类,用户和角色
第二步 让两个实体类之间互相表示
(1)用户里边表示所有的角色,使用set集合
hibernate学习笔记_第26张图片
(2)一个角色中有多个用户,使用set集合
hibernate学习笔记_第27张图片
第三步 配置映射关系
(1)配置基本关系
(2)配置多对多关系

  • 在用户中表示所有相关的角色,使用set标签
    hibernate学习笔记_第28张图片
  • 在角色中表示所有相关的用户,使用set标签
    hibernate学习笔记_第29张图片
    hibernate学习笔记_第30张图片
    第四步 在核心配置文件中引入配置文件
    在这里插入图片描述
    测试
    在这里插入图片描述
    多对多级联保存
    根据用户保存角色
    第一步 在用户配置文件中set标签进行配置,cascade属性值设为save-update
    在这里插入图片描述
    第二步 写代码实现
    (1)创建用户和角色对象,把角色放到用户里面,最终保存用户就可以了
    hibernate学习笔记_第31张图片
    多对多级联删除
    第一步 在set标签中进行配置,cascade属性值中添加delete
    在这里插入图片描述
    第二步 删除对象
    在这里插入图片描述
    注意:了解即可,一般不使用

维护中间表
1、用户和角色是多对多的关系,通过中间表维护
2、让某个用户具备某种角色
第一步 根据id查询用户和角色
第二步 把角色放到用户的set集合中
在这里插入图片描述
3、让某个用户不再具备某种角色
第一步 根据id查询用户和角色
第二步 把角色从用户的set集合中移除
在这里插入图片描述
hibernate查询方式
1、对象导航查询
(1)根据id查询客户,再根据客户查询所有的联系人
2、OID查询
(1)根据id查询某一条记录,返回对象
3、hql查询
(1)创建Query对象,写HQL语句
4、QBC查询
(1)创建Criteria对象
5、本地sql查询
(1)创建SQLQuery对象,写SQL语句

对象导航查询
1 查询某个客户里面所有联系人过程,使用对象导航过程
2 代码
在这里插入图片描述

OID查询
1 根据id查询记录
(1)调用session里面的get方法
在这里插入图片描述

HQL查询
1 hql = hibernate query language
hibernate提供一种数据库查询语言,hql语言yusql语言很相似
区别:普通SQL语句操作的是数据库表和字段,hql语句操作的是实体类和属性
2 常用的hql语句
(1)查询所有:from 实体类名称
【注意】是实体类名称,不是实体类对象名称,也不是数据库表名称
(2)条件查询:from 实体类名称 where 属性名称=? and 属性名称=?
(3)排序查询:from 实体类名称 order by 属性名称 asc/desc
3 使用hql语句查询操作的时候,使用Query对象
(1)创建Query对象,写hql语句
(2)调用Query对象方法得到查询结果

查询所有
1 查询所有的客户记录
(1)创建Query对象,写hql语句
(2)调用Query对象方法得到查询结果
2 查询所有:from 实体类名称
hibernate学习笔记_第32张图片

条件查询
1 hql条件查询的语句写法
(1)from 实体类名称 where 实体类属性名称=? and 实体类属性名称=?
from 实体类名称 where 实体类属性名称 like ?
2 代码
hibernate学习笔记_第33张图片
【注意】新版本HQL占位符:?0 ?1 ?2 …
使用setParameter方法
引用别名必须在前面加冒号
3 字符串匹配查询
hibernate学习笔记_第34张图片

排序查询
1 hql排序语句写法
(1)from 实体类名称 order by 属性名称 asc/desc
2 代码
hibernate学习笔记_第35张图片
分页查询
1 mysql实现分页
(1)使用limit关键字
sql语句 SELECT * FROM t_customer LIMIT 0,50
2 hql实现分页
(1)在hql语句中不能使用limit关键字
3 分页操作
hibernate学习笔记_第36张图片

投影查询
1 投影查询
2 投影查询的hql语句写法
(1)select 属性名称列表 from 实体类名称
(2)select后面不支持*
3 代码
hibernate学习笔记_第37张图片

聚集函数的使用
1 常用的聚集函数
(1)count sum max min avg
2 hql聚集函数的写法
(1)查询表记录数
select count(*) from 实体类名称
hibernate学习笔记_第38张图片
QBC查询
1 使用hql查询需要写hql查询语句,使用qbc不需要写查询语句,使用方法实现
2 使用qbc时,操作的是实体类对象和属性
3 使用qbc需要首先创建Criteria对象

查询所有
1 创建JPA 的CriteriQuery对象
2 调用CriteriaQuery对象方法配置查询条件
3 根据CriteriaQuery对象创建Criteria对象
4 调用方法得到结果
hibernate学习笔记_第39张图片

条件查询
hibernate学习笔记_第40张图片

排序查询
hibernate学习笔记_第41张图片
分页查询
hibernate学习笔记_第42张图片
统计查询
hibernate学习笔记_第43张图片

离线查询

HQL实现多表查询
HQL多表查询
(1)内连接
(2)左外连接
(3)右外连接
(4)迫切内连接
(5)迫切左外连接

HQL内连接
1 内连接查询hql语句写法
(1)from Customer c inner join c.linkManSet
hibernate学习笔记_第44张图片
返回List,List里面每一个元素都是一个数组
2 演示迫切内连接
(1)迫切内连接的底层实现与内连接一样
(2)区别:使用内连接返回List中每一个元素都是一个数组,使用迫切内连接返回List每一个元素都是对象
(3)hql语句写法:
from Customer c inner join fetch c.linkManSet
hibernate学习笔记_第45张图片
HQL左外连接
1 左外连接的hql语句写法
(1)左外连接:from Customer c left outer join c.linkManSet
(2)迫切左外连接:from Customer c left outer join fetch c.linkManSet
hibernate学习笔记_第46张图片

Hibernate检索策略
检索策略的概念
1 hibernate检索策略分为两类
(1)立即查询 根据id查询,调用get方法,一调用get方法马上发送语句查询数据库
(2)延迟查询 根据id查询,还有load方法,调用load方法不会,马上发送语句查询数据,只有得到对象里面的值时才会发送语句查询数据库。
在这里插入图片描述
hibernate学习笔记_第47张图片
2 延迟查询又分为两类
(1)类级别的延迟:根据id查询返回实体类,调用load方法不会马上发送语句
(2)关联级别的延迟:
查询某个客户,再查询这个客户的所有联系人,查询客户所有联系人的过程是否需要延迟。这个延迟就称为关联级别的延迟。
hibernate学习笔记_第48张图片
关联级别的延迟操作
1 在映射文件中进行配置
(1)根据客户得到所有的联系人,在客户的映射文件中进行配置
hibernate学习笔记_第49张图片
2 在set标签上使用属性
(1)fetch:值select
(2)lazy:值

  • true:延迟(默认),要什么就从数据库读取全部数据
  • false:不延迟
  • extra:极其延迟,要什么就给什么,绝不读取不要的数据,及其懒惰

批量抓取
1 查询所有的客户,返回list集合,遍历list集合,得到每个客户的所有联系人
hibernate学习笔记_第50张图片
发送了很多次SQL语句
hibernate学习笔记_第51张图片

2 在客户的配置文件中的set标签中配置batch-size属性
在这里插入图片描述
只发送了一次sql语句
hibernate学习笔记_第52张图片

补充:采用注解方式配置实体类

//1 一对多关系

@Entity//实体类
@Table(name="t_customer")//数据库表名称
public class Customer {
	@Id//主键
	@GeneratedValue(strategy=GenerationType.IDENTITY)//主键生成策略
	@Column(name="cid")//数据库表字段名称
	private Integer cid;
	@Column(name="cust_name")
	private String custName;
	@Column(name="cust_level")
	private String custLevel;
	@Column(name="cust_source")
	private String custSource;
	@Column(name="cust_phone")
	private String custPhone;
	@Column(name="cust_mobile")
	private String custMobile;
	
	//一对多关系的配置
	//targetEntity表示关联实体类
	//@Cascade用于配置级联操作
	@OneToMany(targetEntity=LinkMan.class,mappedBy="customer")
	@Cascade({CascadeType.SAVE_UPDATE,CascadeType.DELETE})
	private Set<LinkMan> linkManSet = new HashSet<LinkMan>();
	//省略get、set、toString方法
}


@Entity
@Table(name="t_linkman")
public class LinkMan {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="lkm_id")
	private Integer lkmId;
	@Column(name="lkm_name")
	private String lkmName;
	@Column(name="lkm_gender")
	private String lkmGender;
	@Column(name="lkm_phone")
	private String lkmPhone;
	
	//配置一对多的关联
	@ManyToOne(targetEntity=Customer.class,cascade= {CascadeType.PERSIST,CascadeType.REMOVE})
	//配置外键,name表示外键数据库表字段名
	@JoinColumn(name="clid")
	private Customer customer;
	//省略get、set、toString方法
}

//2 多对多关系

@Entity
@Table(name="t_role")
public class Role {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="role_id")
	private Integer roleId;
	@Column(name="role_name")
	private String roleName;
	@Column(name="role_memo")
	private String roleMemo;

	//配置多对多关联,targetEntity是关联的实体类
	@ManyToMany(targetEntity=cn.ljh.hibernate.entity.User.class)
	//配置中间表,name表示中间表的名称,joinColumns表示本实体类在中间表的外键,inverseJoinColumns表示其他实体类在中间表的外键
	@JoinTable(
		name="t_user_role",
		joinColumns={
			//配置外键,name是在中间表中的字段名,referencedColumnName是被外键引用的字段名
			@JoinColumn(name="role_id",referencedColumnName="role_id")},
		inverseJoinColumns={
			//配置外键,name是在中间表中的字段名,referencedColumnName是被外键引用的字段名
			@JoinColumn(name="user_id",referencedColumnName="user_id")}	
	)
	//配置级联操作
	@Cascade(CascadeType.SAVE_UPDATE)
	private Set<User> userSet=new HashSet<>();
}

@Entity
@Table(name = "t_user")
public class User {
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "user_id")
	private Integer userId;
	@Column(name = "user_name")
	private String userName;
	@Column(name = "user_password")
	private String userPassword;

	//配置多对多关联,targetEntity表示关联实体类,
	//mappedBy表示放弃维护外键,指定在其他实体类中被引用的属性名
	@ManyToMany(targetEntity = cn.ljh.hibernate.entity.Role.class, mappedBy = "userSet")
	private Set<Role> roleSet = new HashSet<>();
}

//3 一对一关系

@Entity
@Table(name="t_id_card")
public class IdCard {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="i_id")
	private Integer iId;
	@Column(name="i_name")
	private String iName;
	@Column(name="i_gender")
	private String iGender;
	@Column(name="i_address")
	private String iAddress;
	
	//配置一对一关系
	@OneToOne(targetEntity=StudentCard.class)
	//配置外键,name表示外键的数据库字段名
	@JoinColumn(name="stu_id")
	//配置级联操作
	@Cascade(CascadeType.SAVE_UPDATE)
	private StudentCard studentCard;
	//省略get、set、toString方法
}

@Entity
@Table(name="t_student_card")
public class StudentCard {
	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	@Column(name="stu_id")
	private Integer stuId;
	@Column(name="stu_name")
	private String stuName;
	@Column(name="stu_class")
	private Integer stuClass;
	
	//配置一对一关系并放弃维护外键
	@OneToOne(targetEntity=IdCard.class,mappedBy="studentCard")
	private IdCard idCard;
	//省略get、set、toString方法
}

//主键映射是另一种一对一关系的配置方法,但实际开发中不经常使用,
//具体做法是将上面的OneToOne中的targetEntity删除,
//将@JoinColumn改为@PrimaryKeyJoinColumn即可。

你可能感兴趣的:(hibernate学习笔记)