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)不需要直接操作数据库表,而操作表对应实体类对象
画图描述:
在这里插入图片描述

//加载驱动
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>
	<!-- 1 配置类和表对应 
		class标签
		name属性:实体类全路径
		table属性:数据库表名称
	-->
	<class name="cn.itcast.entity.User" table="t_user">
		<!-- 2 配置实体类id和表id对应
			hibernate要求实体类有一个属性值唯一值
			hibernate要求表有字段作为唯一值
		-->
		<!-- id标签
			name属性:实体类里面id属性名称
			column属性:生成的表字段名称
		-->
		<id name="uid" column="uid">
			<!-- 设置数据库表id增长策略
				native:生成表id值就是主键自动增长
			-->
			<generator class="native"></generator>
		</id>
		<!-- 配置其他属性和表字段对应
			name属性:实体类属性名称
			colume属性:生成表字段名称
			
		-->
		<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.Driver</property>
		<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate?useUnicode=true&amp;characterEncoding=utf8&amp;serverTimezone=GMT%2B8</property>
		<property name="hibernate.connection.username">root</property>
		<property name="hibernate.connection.password">ljh_5098_CHD</property>
		
		<!-- 第二部分 配置hibernate信息 可选的 -->
		<property name="hibernate.show_sql">true</property>
		<property name="hibernate.format_sql">true</property>
		<!-- hibernate帮创建表,需要配置之后
			update:如果已经有表,更新,如果没有,创建
		-->
		<property name="hdm2ddl.auto">update</property>
		<!-- 配置数据库方言
			在mysql里面实现分页 关键词limit,只能使用mysql里面
			在oracle数据库中,实现分页rownum
			让hibernate框架识别不同数据库特有的语句
		-->
		<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一级缓存的特性
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事务代码的规范写法
1、代码结构
try{
开启事务
提交事务
}catch(异常){
回滚事务
}finally{
关闭事务
}

代码
在这里插入图片描述

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对象的方法得到结果
在这里插入图片描述
Criteria对象
1、使用Criteria对象查询操作,不用写查询语句,直接调用方法实现
2、实现过程
(1)创建Criteria对象
(2)调用Criteria对象的方法得到结果
在这里插入图片描述
SQLQuery对象
1、使用hibernate时候,调用底层的SQL语句来实现
2、实现过程
(1)创建SQLQuery对象
(2)调用对象的方法得到结果,结果以数组list的形式返回
在这里插入图片描述
(3)返回list每一项是对象
在这里插入图片描述

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

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

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

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

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

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

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

hibernate多对多的操作
在这里插入图片描述
多对多映射配置
以用户与角色为例演示
第一步 创建实体类,用户和角色
第二步 让两个实体类之间互相表示
(1)用户里边表示所有的角色,使用set集合
在这里插入图片描述
(2)一个角色中有多个用户,使用set集合
在这里插入图片描述
第三步 配置映射关系
(1)配置基本关系
(2)配置多对多关系

  • 在用户中表示所有相关的角色,使用set标签
    在这里插入图片描述
  • 在角色中表示所有相关的用户,使用set标签
    在这里插入图片描述
    在这里插入图片描述
    第四步 在核心配置文件中引入配置文件
    在这里插入图片描述
    测试
    在这里插入图片描述
    多对多级联保存
    根据用户保存角色
    第一步 在用户配置文件中set标签进行配置,cascade属性值设为save-update
    在这里插入图片描述
    第二步 写代码实现
    (1)创建用户和角色对象,把角色放到用户里面,最终保存用户就可以了
    在这里插入图片描述
    多对多级联删除
    第一步 在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 实体类名称
在这里插入图片描述

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

排序查询
1 hql排序语句写法
(1)from 实体类名称 order by 属性名称 asc/desc
2 代码
在这里插入图片描述
分页查询
1 mysql实现分页
(1)使用limit关键字
sql语句 SELECT * FROM t_customer LIMIT 0,50
2 hql实现分页
(1)在hql语句中不能使用limit关键字
3 分页操作
在这里插入图片描述

投影查询
1 投影查询
2 投影查询的hql语句写法
(1)select 属性名称列表 from 实体类名称
(2)select后面不支持*
3 代码
在这里插入图片描述

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

查询所有
1 创建JPA 的CriteriQuery对象
2 调用CriteriaQuery对象方法配置查询条件
3 根据CriteriaQuery对象创建Criteria对象
4 调用方法得到结果
在这里插入图片描述

条件查询
在这里插入图片描述

排序查询
在这里插入图片描述
分页查询
在这里插入图片描述
统计查询
在这里插入图片描述

离线查询

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

HQL内连接
1 内连接查询hql语句写法
(1)from Customer c inner join c.linkManSet
在这里插入图片描述
返回List,List里面每一个元素都是一个数组
2 演示迫切内连接
(1)迫切内连接的底层实现与内连接一样
(2)区别:使用内连接返回List中每一个元素都是一个数组,使用迫切内连接返回List每一个元素都是对象
(3)hql语句写法:
from Customer c inner join fetch c.linkManSet
在这里插入图片描述
HQL左外连接
1 左外连接的hql语句写法
(1)左外连接:from Customer c left outer join c.linkManSet
(2)迫切左外连接:from Customer c left outer join fetch c.linkManSet
在这里插入图片描述

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

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

批量抓取
1 查询所有的客户,返回list集合,遍历list集合,得到每个客户的所有联系人
在这里插入图片描述
发送了很多次SQL语句
在这里插入图片描述

2 在客户的配置文件中的set标签中配置batch-size属性
在这里插入图片描述
只发送了一次sql语句
在这里插入图片描述

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

//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即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值