一、Hibernate
书中配置方法:
在eclipse中部署Hibernate开发环境
在线安装方式:
(1)运行Eclipse,选择主菜单Help--Install New Software选项
(2)输入地址:http://download.jboss.org/jbosstools/mars/stable/updates/
(3)选择相关功能:
JBoss Tools 4.3.0.Final下的Hibernate Tools选项
单机next选项
JavaEE三层结构:
1、web层,struts框架。
2、service层:spring框架
3、dao层:hibernate框架
(1)对数据库进行crud操作
MVC思想:
1、m:模型
2、v:视图
3、c:控制器
hibernate概述
1、什么是框架:
(1)写一个程序,使用框架后, 帮我们实现一部分功能,使用框架的好处就是少些一部分代码实现功能
2、什么是hibernate框架
(1)hibernate框架应用在javaee三层接口中dao层框架
(2)在dao层里做对数据库crud操作,使用hibernate实现crud操作,
hibernate底层代码就是jdbc,hibernate对jdbc进行封装,
使用hibernate的好处:
不需要写复制的jdbc代码,不需要使用写sql语句。
(3)hibernate是一个开源的轻量级的框架
(4)hibernate版本,主要使用Hibernate5.x
3、什么是orm思想
1、hibernate使用orm思想对数据库进行crud操作,
2、javabean:实体类
3、orm:Object relational mapping 对象关系映射
(1)描述:
让实体类和数据库进行一一对应关系
让实体类首先和数据库表对象
让实体类属性和表里面字段对象
不需要直接操作数据库,而操作表对应实体类对象
hibernate入门
1、搭建hibernate环境
(1)需要导入的jar包,jpa,required
因为使用hibernatehibernate时候,有日志信息输出,hibernate本身没有日志输出的jar包,
导入其他日志的jar包,
不要忘记还有mysql驱动的jar
(2)创建实体类
使用hibernate的时候,不需要自己手动创建表,hibernate会自动创建表
(3)配置实体类和数据库表一一对应关系(映射关系)
使用配置文件实现映射关系
1.创建xml格式的配置文件
映射配置文件名称和位置没有固定要求
建议:在实体类所在包里面创建,实体类名称.hbm.xml
2.配置文件是xml格式,在配置文件中首先引用xml约束。
eg:
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
3.配置映射关系
eg:
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- 1配置类和表对应
class标签
name属性:实体类全路径,
table属性:数据库表名称
-->
<!-- 要写全路径 -->
<class name="cn/itcast.entity.User" table="tbl_user">
<!-- 2配置实体类id和表id对应
hibernate要求实体类有一个属性唯一值
hibernate要求表有字段作为唯一值
-->
<!-- id标签
name 属性:实体列里面id属性名称
column属性:最终生成的表里面字段名称
-->
<id name="id" column="id">
<!-- 设置数据库表id增长策略 -->
<!-- native:生成id值计时主键自动增长 -->
<generator class="native"></generator>
</id>
<!-- 配置其他的属性和表字段对应 -->
<property name="name" column="name"></property>
<property name="password" column="password"></property>
<property name="email" column="email"></property>
</class>
</hibernate-mapping>
4. 创建hibernate的核心配置文件
(1)核心配置文件格式xml,但是核心文件名称和位置是固定的
-位置:必须在src下面
-名称:必须hibernate.cfg.xml
(2)引入dtd约束
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
(3)hibernate操作过程中,只会加载核心配置文件,其他的配置文件不会加载
第一部分:配置数据库信息
第二部分:配置hibernate信息
第三部分,把映射文件放到核心配置文件中
eg:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- 第一部分:配置数据库信息 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///jsp_db</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<!-- 第二部分:配置hibernate信息 可选 -->
<!-- 输出底层sql语句 -->
<property name="hibernate.show_sql">true</property>
<!-- 输出底层sql语句格式 -->
<property name="hibernate.format_sql">true</property>
<!-- hibernate帮创建表,需要配置之后
update:如果已经有此表会进行更新,没有的话自动创建。
-->
<property name="hibernate.hbm2ddl.auto">update</property>
<!-- 配置数据库方言 在mysql会用分页使用关键字:limit,只能使用mysql里面。在Oracle数据库分页使用rownum
让hibernate框架识别不同数据库的语句
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- 第三部分 把映射文件放到核心配置文件中 -->
<mapping resource="cn/itcast/entity/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
2、实现添加操作:
第一步:加载hibernate核心配置文件
第二步:创建SessionFactory对象
第三部:使用SessionFactory创建Session对象
第四步:开启事务
第五步:写具体逻辑crud操作
第六步:提交事务
第七步:关闭资源
eg:
//第一步:加载hibernate核心配置文件
//到src下面找到名称是hibernate.cfg.xml
Configuration cfg=new Configuration();
cfg.configure();//加载配置文件
// 第二步:创建SessionFactory对象
//读取hibernate核心配置文件内容,在此过程中,
//他会在数据库里根据映射关系在数据库中创建表
SessionFactory sessionFactory=cfg.buildSessionFactory();
//第三部:使用SessionFactory创建Session对象
//类似于连接
Session session=sessionFactory.openSession();
//第四步:开启事务
Transaction tx= session.beginTransaction();
//第五步:写具体逻辑crud操作
User user=new User();
user.setName("小王");
user.setPassword("haha");
user.setEmail("666");
session.save(user);
//第六步:提交事务
tx.commit();
//第七步:关闭资源
session.close();
sessionFactory.close();
3、Hibernate配置文件详解
Hibernate映射配置文件
1.映射配置文件名称和位置没有固定要求;
2.映射配置文件中,标签name属性值写实体类相关内容
(1)class标签name属性值为实体类全路径
(2)id标签和property标签name属性值为实体类属性名称
3.id标签和property标签中 column属性可以省略,省略后自动生成和name一样的名字
4.在property标签中type属性,设置生成表字段的类型,自动生成对应类型
Hibernate核心配置文件
1.配置写位置,必须在session-factory标签内
2.配置三部分要求
(1)数据库部分
(2)hibernate部分是可选的
(3)映射文件是必须的,可引用多个配置文件
Hibernate核心api:
1、Configuration
(1)到src下面找到名称hibernate.cfg.xml配置文件,创建对象,把配置文件放到对象里面
eg:
Configuration cfg=new Configuration();
cfg.configure();//加载配置文件
2、SessionFactory
(1)使用configuration对象创建sessionFactory对象
1.创建SessionFactory过程中会:
-根据核心配置文件在,有数据库配置,映射文件部分,到数据库里面根据映射关系把表创建
eg:
SessionFactory sessionFactory=cfg.buildSessionFactory();
(2)创建SessionFactory过程中,耗费资源
在hibernate操作中,建议一个项目一般创建一个SessionFactory对象
(3)实现
(1)写工具类,写静态代码块,在类加载时执行,执行一次
eg:
public class hibernateUtils {
static Configuration cfg=null;
static SessionFactory sessionFactory=null;
//静态代码块
static {
//加载核心配置文件
cfg=new Configuration();
cfg.configure();
sessionFactory=cfg.buildSessionFactory();
}
public static SessionFactory getsessionFactory() {
return sessionFactory;
}
}
(2)
3、Session
(1)session类似于jdbc中connection
(2)调用session里面不同的方法实现crud操作
1.添加save方法;
2.修改update方法;
3.删除delete方法;
4.根据id查询get方法;
(3)session对象单线程对象,表示session对象不能共用,只能自己使用
4、Transaction
(1)事务对象;
Transaction tx= session.beginTransaction();//开启
(2)事务提交和回滚方法
tx.commit();
tx.rollback();//回滚
(3)事务的概念
1.事务的四个特性:
原子性,一致性,隔离性,持久性
解决配置文件没有提示问题
1、可以上网
2、将约束文件引入到eclipse中
实体类编写规则
1、实体类属性都是私有的;
2、私有属性使用公开的setget方法操作
3、要求实体类里面有属性作为唯一值
4、实体类属性建议不适用基本数据类型,使用基本数据类型对应的包装类
(1)八个基本数据类型对应的包装类
-Int---Integer
-char--Character
-其他的都是首字母大写,比如double--Double
(2)比如,表示学生的分数,加入int score;
-比如学生的了0分,int score=0;
-如果表示学生没有参加考试,int scoure=0;不能准确表示学生是否参加考试
解决:
使用包装类可以,等于null
hibernate主键生成策略
1、hibernate乔秋实体类里面有一个属性作为唯一值,对应表主键,
主键可以不同生成策略
2、hibernate主键生成策略有很多值:
eg:
<generator class="assigned" />
3、在class属性里面有值,
主要两个
(1)natice:根据使用的数据库,自动选择。自动加一
(2)uuid:自动生成32位16字符串,uuid值
uuid:
(1)使用uuid生成策略,实体类id属性类型必须为字符串
(2)配置部分携程uuid值
实体类操作
(1)crud操作
1.添加操作:
eg:
User user=new User();
user.setName("小王");
user.setPassword("haha");
user.setEmail("666");
session.save(user);
2.根据id查询:
User user=session.get(User.class,1)
3.修改
eg:
//修改
//修改id=339记录中name的值
//1、根据id进行查询
User user= session.get(User.class, 339);
//2、向返回的user对象里面设置修改后的值
user.setName("修改后");
//3、调用session里的修改方法
session.update(user);
tx.commit();
session.close();
sessionFactory.close();
4、删除
eg:
//删除
//方法1:根据id查询对象
User user=session.get(User.class, 2);
session.delete(user);
//方法2:
User user=new User();
user.setId(3);;
session.delete(user);
(2)实体类对象状态
1.实体类状态有3种状态
(1)瞬时态:
对象里面没有id值,对象与session没有关联 eg:save
(2)持久态:
对象里有id值,对象与session有关联 eg:get
(3)托管态
对象里面有id值,对象与session没有关联 eg:update
2.操作实体类的方法
savrOrUpdate方法:
实体类对象状态是瞬时态的话做添加
实体类对象状态时托管态做修改
实体类对象状态是持久态的话做修改
hibernate的一级缓存
1、什么是缓存:
(1)数据存到数据库里面,数据库本身就是文件系统,要使用流的方式操作文件,效率低,
解决方法:
1.把数据存到内存里面,不需要使用流方式,可以直接读取内存中数据
(2)吧数据放到内存中,提高读取效率
2、Hibernate缓存:
(1)hibernate框架中提供很多优化方式,Hibernate的缓存就是一个优化方式
(2)hibernate缓存特点:
第一类,hibernate的一级缓存
1.hibernate的一级级缓存默认就是打开的
2.hibernate的一级缓存存在使用范围,是session范围(从session创建到session关闭的范围)
3.hibernate的一级缓存中,储存数据必须是持久态数据
第二类 hibernate的二级缓存
1.目前已经不适用了,替代技术redis
2.二级缓存默认不是打开的,需要配置
3.二级缓存使用范围,是sessionFactory范围
3、验证一级缓存的存在
验证方式
1.首先根据id=1查询,返回对象
2.再根据id=1的查询,返回对象
4、一级缓存的特性
(1)持久态自动更新数据库
(2)执行过程:
Hibernate事务代码规范写法
try{
开启事务
提交事务
}catch{
回滚事务
}finally{
关闭事务
}
eg:
public void testget() {
Transaction tx=null;
SessionFactory sessionFactory=null;
Session session=null;
try {
sessionFactory=hibernateUtils.getsessionFactory();
session=sessionFactory.openSession();
tx=session.beginTransaction();
User user=session.get(User.class, 1);
System.out.println(user.getName());
tx.commit();
} catch (Exception e) {
// TODO: handle exception
tx.rollback();
}finally {
session.close();
sessionFactory.close();
}
Hibernate绑定session
1、session类似于jdbc的connection,之前web阶段学过threadLocal
2、帮实现与本地线程绑定session
3、获取与本地线程session
(1)在hibernate核心配置文件中配置
eg:
<!-- 在hibernate核心配置文件中配置线程 -->
<property name="hibernate.current_session_context_class">thread</property>
(2)调用sessionFactory里面的方法得到
//提供返回与本地线程绑定的session方法
public static Session getSession() {
return sessionFactory.getCurrentSession();
}
public void testget() {
Transaction tx=null;
SessionFactory sessionFactory=null;
Session session=null;
try {
session=hibernateUtils.getSession();
tx=session.beginTransaction();
User user=session.get(User.class, 1);
System.out.println(user.getName());
tx.commit();
} catch (Exception e) {
// TODO: handle exception
tx.rollback();
}
//绑定本地线程session不需要关闭session
hibernate的其他api(查询)
1、Query对象:
(1)使用query对象,不需要写sql语句,但是写hql语句
hql:hibernate query language,hibernate提供查询语句
hql和sql的区别:
-使用sql操作表和表字段
-使用hql操作实体类和属性
(2)查询所有hql语句
from 实体类名称
(3)Query对象使用
1.常见Query对象
2.调用query对象里面的方法
eg:
Query query=session.createQuery("from User");
//2调用query对象里面的方法
List<User> list=query.list();
for(User user:list) {
System.out.println(user);
}
2、Critica对象:
(1)使用这个对象查询操作,但是使用这个对象的时候。
不需要写语句,直接调用方法实现
(2)实现过程
1.创建criteria对象
2.使用此对象得到结果
eg:
Criteria criteria=session.createCriteria(User.class);
List<User> list=criteria.list();
for(User user:list) {
System.out.println(user);
}
3、SQLQuery对象:
(1)使用hibernate的时候,也可以使用底层sql语句。
(2)实现过程:
1.创建对象
2.调用方法
eg:
//查询Critica对象对象
//1创建Critica对象对象
SQLQuery sqlQuery=session.createSQLQuery("select * from tbl_user");
List<Object[]> list=sqlQuery.list();
System.out.println(list.size());
for(Object[] objects:list) {
System.out.println(Arrays.toString(objects));
}
//或者!!
//设置list为对象形式
sqlQuery.addEntity(User.class);
List<User> list2=sqlQuery.list();
for(User user:list2) {
System.out.println(user);
}
表与表之间关系
1、一对多关系
(1)分类和商品关系,一个分类里有多个商品,一个商品只能属于一个分类
(2)一对多建表:
通过外键建立关系
在多的那一方建立字段,作为外键,与一的主键绑定在一起
2、多对多
(1)订单和商品关系,一个订单里面有多个商品,一个商品属于多个订单
(2)一个用户有多个角色,一个角色有多个用户
(3)多对多建表:
创建第三张表来维护其中的关系
至少有两个字段作为外键,指向两个表主键
3、一对一
(1)一个男人只能有一个妻子
Hibernate的一对多操作
1、一对多映射配置
第一步:创建两个实体类
第二步:让两个实体类之间相互表示
(1)在客户实体类里面表示多个联系人
-一个客户里面有多个联系人
private Set<LinkMan> setLinkMan=new HashSet<LinkMan>();
(2)在联系人实体类里面表示所属客户
一个联系人只能属于一个客户
private Customer customer;
第三部:配置映射关系
(1)一般情况下,有几个实体类就要写几个映射文件
(2)映射最基本配置完成
(3)在映射文件中,配置一对多关系
---在客户映射文件中
eg:
<!-- 在客户映射文件中,表示所有联系人
使用set标签表示所有联系人
set标签里面name属性:属性值写在客户实体类表示联系人的set集合名称
-->
<set name="setLinkMan" table="LINKMAN" inverse="false" lazy="true">
<!-- key:hibernate机制:双向维护外键,在一和多哪一方都需要配置外键
key表示外键
-->
<key>
<column name="CID" />
</key>
<!-- 客户所有的联系人,class里面写联系人实体类全路径 -->
<one-to-many class="cn.itcast.entity.LinkMan" />
</set>
---在联系人映射文件中
<!-- 表示联系人所属客户
Name属性:因为在联系疼实体类使用了customer对象表示,写customer名称
class属性:customer全路径
column属性:外键的名称
-->
<many-to-one name="customer" class="cn.itcast.entity.Customer" fetch="join">
<column name="CUSTOMER" />
</many-to-one>
2、一对多的级联操作
级联操作:
(1)级联保存
1.添加一个客户,为这个客户添加多个联系人
(2)级联删除
1.删除某个客户,这个客户里面的所有联系人也都删除
一对多级联保存:
(1)添加客户,为这个客户添加一个联系人
方法1:
eg:
Customer customer=new Customer();
customer.setCustName("name1");
customer.setCustLevel("level1");
customer.setCustSource("source1");
customer.setCustPhone("111");
customer.setCustMobile("mobule1");
LinkMan linkMan=new LinkMan();
linkMan.setLkm_name("lucy");
linkMan.setLkm_gender("男");
linkMan.setLkm_phone("111");
//2在客户里表示所有联系人,在联系人表示客户
//建立客户对象和联系人对象的关系
//2.1把联系人对象放到客户实体类set集合里面
customer.getSetLinkMan().add(linkMan);
//2.2吧客户对象放到联系人里面
linkMan.setCustomer(customer);
//3保存到数据库
session.save(customer);
session.save(linkMan);
tx.commit();
方法2:简化写法
根据客户添加联系人
第一步:
在客户映射文件中进行配置:
在客户映射文件里面set标签进行配置
<set name="setLinkMan" table="LINKMAN" cascade="save-update" >
第二步:
创建客户和联系人对象,只需要把联系人放到客户里面就可以了。
最终只要保存客户联系人就可以了。
eg:
Customer customer=new Customer();
customer.setCustName("name2");
customer.setCustLevel("level2");
customer.setCustSource("source2");
customer.setCustPhone("222");
customer.setCustMobile("mobule2");
LinkMan linkMan=new LinkMan();
linkMan.setLkm_name("小红");
linkMan.setLkm_gender("女");
linkMan.setLkm_phone("222");
//2把联系人放到客户里面
customer.getSetLinkMan().add(linkMan);
//3保存客户
session.save(customer);
一对多级联删除
(1)删除某个客户,把客户里面的所有的联系人删除
(2)实现:
第一步:
在客户映射文件中进行配置:
在客户映射文件里面set标签进行配置
<set name="setLinkMan" table="LINKMAN" cascade="delete,save-updata" >
第二步:
直接删除客户
//删除
Customer customer=session.get(Customer.class, 2);
session.delete(customer);
一对多级联修改
eg:
//修改操作
//1根据id查询联系人,根据id查询客户
Customer customer= session.get(Customer.class, 1);
LinkMan linkMan= session.get(LinkMan.class, 1);
//2设置持久态对象值
//把联系人放到客户里
customer.getSetLinkMan().add(linkMan);
//把客户放到联系人里
linkMan.setCustomer(customer);
inverse属性
(1)因为hibernate双向维护外键,在客户和联系人里面都需要维护外键,修改客户时候修改一次外键,修改联系人时候也修改一次外键,造成效率问题。
(2)解决方式:
让其中的一方不维护外键,
--让一对多里面,让其中一的一方放弃外键的维护。
(3)具体实现:
在放弃关系维护映射文件中,进行配置,在set标签上使用inverse属性
eg:
<!--
inverse属性默认值:
false不放弃关系维护
true表示放弃关系维护
-->
<set name="setLinkMan" table="LINKMAN" cascade="save-update,delete" inverse="true" >
Hibernate的多对多操作
1、多对多映射配置
以用户和角色为例
第一步 创建实体类,用户和角色
第二步 让两个实体类互相表示
(1)一个用户里面要表示所有角色,set集合
(2)一个角色里面有多个用户,set集合
eg: private Set<User> setuser=new HashSet<Us
第三步 配置映射关系
(1)基本配置
(2)配置多对多关系
在用户里面表示所有角色,使用set标签
<set name="setRole" table="ROLE" inverse="false" lazy="true">
<key>
<column name="USER_ID" />
</key>
<many-to-many class="cn.itcast.manytomany.Role" column="ROLE_ID" />
</set>
在角色里面表示所有用户,使用set标签
<set name="setuser" table="USER" inverse="false" lazy="true">
<key>
<column name="ROLE_ID" />
</key>
<one-to-many class="cn.itcast.manytomany.User" />
</set>
**其中table属性表示第三张表名称
key标签里面的column配置当前映射文件在第三张表外键名称
**many-to-many中 class为角色实体类全路径,column表示角色在第三张表外键名称
第四步 在核心配置文件中引入映射文件
<mapping resource="cn/itcast/manytomany/Role.hbm.xml"/>
<mapping resource="cn/itcast/manytomany/User.hbm.xml"/>
2、多对多级联保存
根据用户保存角色
第一步 在用户配置文件中set标签进行配置,cascade
<set name="setRole" table="USER_ROLE" inverse="false" cascade="save-update" lazy="true">
第二步 写代码实现
(1)创建用户和角色对象,把角色放到用户里面,最终保存用户就可以
//对多对级联添加
//添加两个用户,为每个用户添加两个角色
//1创建对象
User user=new User();
user.setUser_name("1");
user.setUser_password("1");
User user2=new User();
user2.setUser_name("2");
user2.setUser_password("2");
Role r1=new Role();
r1.setRole_name("总经理");
r1.setRole_memo("123");
Role r2=new Role();
r2.setRole_name("秘书");
r2.setRole_memo("234");
Role r3=new Role();
r3.setRole_name("保安");
r3.setRole_memo("5667");
//2建立关系
user.getSetRole().add(r1);
user.getSetRole().add(r2);
user2.getSetRole().add(r2);
user2.getSetRole().add(r3);
session.save(user);
session.save(user2);
多对多级联删除
第一步 在set标签配置,cascade值delete
cascade="save-update,delete"
第二步删除用户
session.delete(session.get(User.class, 1));
**很少用,因为直接把角色都删除了
多对多维护第三张表
(1)用户和角色多对多关系,维护关系通过第三张表维护
eg:
(2)让某个用户有某个角色
第一步 根据id查询出用户和角色
第二步 把角色放到用户里
把橘色对象放到用户set集合
eg:
User user= session.get(User.class, 1);
Role role=session.get(Role.class, 1);
//2把角色放到用户的set集合里面
user.getSetRole().add(role);
(3)让某个用户没有某个角色
第一步 根据id查询出用户和角色
第二步 把角色放到用户里
把角色对象放到用户set集合
eg:User user= session.get(User.class, 1);
Role role=session.get(Role.class, 1);
//2从用户里面吧角色去掉
user.getSetRole().remove(role);
Hibernate查询方式;
1、对象导航查询
eg:根据id查询某个客户,再查询这个客户里面所有的联系人
sessionFactory=hibernateUtils.getsessionFactory();
session=sessionFactory.openSession();
tx=session.beginTransaction();
//根据cid=1客户,再查询这个客户里面所有联系人
Customer customer= session.get(Customer.class,1);
//在查询这个客户所有联系人
//直接得到客户里面联系人的set集合
Set<LinkMan> linkMans= customer.getSetLinkMan();
System.out.println(linkMans.size());
tx.commit();
2、OID查询
eg:根据id查询某一条记录,返回对象
(1)调用session里面get方法查询
Customer customer= session.get(Customer.class,1);
3、hql查询
eg:Query对象,写hql语句实现查询
(1)hql:hibernate query language 一种查询语言,和sql相似
区别:普通sql操作数据库表和字段,hql操作实体类和属性
(2)常用的hql语句
1.查询所有:
Query query= session.createQuery("from Customer");
List<Customer> list= query.list();
for(Customer customer:list) {
System.out.println(customer.getCid()+""+customer.getCustName());
}
2.条件查询:
条件查询语句写法:
from 实体类名称 where 实体类属性名称=? and 实体类属性名称 like ?
eg:
Query<Customer> query=session.createQuery("from Customer where CUSTNAME like ?");
//2.设置条件值
//向?里面设置值
//setParameter方法两个参数
//第一个参数:int类型是?位置,从0开始;
query.setParameter(0, %3%);
List<Customer> list= query.list();
for(Customer customer:list) {
System.out.println(customer.getCid()+"::::"+customer.getCustName());
}
3.排序查询
(1)hql排序语句:
from 实体类名称 + order by 实体类属性名称 asc/desc
eg:
Query<Customer> query=session.createQuery("from Customer order by CID desc");
4.分页查询
**开始位置计算公式:(当前页-1)*没页记录数
mysql实现:select * from cutomer LIMIT 0,8
在hql中:
在hql操作中,不能使用LIMIT,hibernate的Query对象中封装了两个方法,
可用于实现分页操作
eg:
//1.创建一个Query对象
Query<Customer> query=session.createQuery("from Customer");
//2.设置分页数据
//设置开始位置
query.setFirstResult(0);
//设置每页记录数
query.setMaxResults(1);
//调用方法得到结果
List<Customer> list= query.list();
for(Customer customer:list) {
System.out.println(customer.getCid()+"::::"+customer.getCustName());
}
5.投影查询
查询的不是所有字段值,而是部分字段的值
sql:select custName FROM customer
hql:select 实体类属性名称1,实体类属性名称2 from 实体类名称
**select 后面不能写*,不识别
eg:
Query<Object> query=session.createQuery("select cid from Customer");
List<Object> list=query.list();
for(Object object : list) {
System.out.println(object);
}
6.聚集函数的使用:
(1)常用的聚集函数:count、sum、avg、max、min
(2)hql聚集函数语句写法
1.查询表记录数
select count(*) from 实体类名称
eg:
Query<Object> query=session.createQuery("select count(*) from Customer");
Long long1=(Long)query.uniqueResult();
int count=long1.intValue();
System.out.println(count);
7.HQL多表查询
1.HQL内连接
(1)from Custtomer c inner join c.setLinkMan
eg:
//返回的是数组
Query<Object> query=session.createQuery("from Customer c inner join c.setLinkMan");
List<Object> list= query.list();
2.迫切内连接
和HQL内连接区别:
使用内连接返回list中每部分是数组,破解内连接返回list是对象
from Custtomer c inner join fetch c.setLinkMan
3.HQL左外连接
from Custtomer c left outer join c.setLinkMan
4.迫切左外连接
from Custtomer c left outer join fetch c.setLinkMan
迫切的左外连接返回list每部分是对象
(3)使用hql查询操作需要使用Query对象
1.创建一个Query对象,写hql语句
2.调用query对象里面的方法得到结果
4、QBC查询
eg:Criteria对象
(1)查询所有
//1创建Criteria对象
Criteria criteria=session.createCriteria(Customer.class);
List<Customer> list=criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCid()+":::"+customer.getCustName());;
}
(2)条件查询
eg:
//QBC条件查询
//1创建Criteria对象
Criteria criteria=session.createCriteria(Customer.class);
//2使用方法设置条件值
//首先使用add方法,表示设置条件值
//在add方法里面使用类的方法实现条件设置
criteria.add(Restrictions.eq("cid", 3));
List<Customer> list=criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCid()+":::"+customer.getCustName());;
}
criteria.add(Restrictions.like("custName", "%2%"));
(3)排序查询
eg:
criteria.addOrder(Order.asc("cid"));//升序
(4)分页查询
**开始位置计算公式:(当前页-1)*没页记录数
eg:
//设置分页数据
criteria.setFirstResult(0);
//设置开始位置
criteria.setMaxResults(3);
//每页显示记录数
(5)统计查询
eg:
criteria.setProjection(Projections.rowCount());//设置参数
Object object= criteria.uniqueResult();
Long long1=(Long)object;
int count=long1.intValue();
(6)离线查询
eg:
//创建对象
DetachedCriteria detachedCriteria=DetachedCriteria.forClass(Customer.class);
//最终执行时候才需要session
Criteria criteria=detachedCriteria.getExecutableCriteria(session);
List<Customer> list=criteria.list();
for (Customer customer : list) {
System.out.println(customer.getCid()+":::"+customer.getCustName());;
}
5、本地sql查询
eg:用SQLQuery对象,使用普通sql实现查询
Hibernate检索策略
检索策略的概念
(1)立即查询
根据id查询,调用get方法,一调用get方法马上发送语句查询数据库
eg:Customer customer=session.get(Customer.class, 2);
(2)延迟查询
根据id查询,还有load方法,调用load方法不会马上发送语句查询数据。
只有得到对象里面的值的时候才会发送语句查询数据库
eg:Customer customer=session.load(Customer.class, 1);
//调用Load方法之后,不会马上发送sql语句,得到对象里面不是id的其他值的时候才会发送语句
eg:
//根据cid=1客户查询该客户里面所有联系人
Customer customer=session.load(Customer.class, 1);
//Customer customer=session.get(Customer.class, 2);
//再查询这个客户里面所有联系人
//直接得到客户里面联系人的set集合
//得到set集合 没有发送语句
Set<LinkMan> linkMans=customer.getSetLinkMan();
//发送语句
System.out.println(linkMans.size());
延迟查询分成两类
1.类级别延迟
根据id查询返回实体类对象,调用load方法不会马上发送语句
2.关联级别延迟
查询某个客户,再查询该客户所有联系人。
查询客户的所有联系人的过程是否需要延迟。
这个过程就是关联级别延迟
关联级别延迟操作
在映射文件中进行配置实现
在set标签上使用属性:
(1)fetch:值select
(2)lazy:值
-true:延迟(默认)
-false:不延迟
调用get之后,2条sql语句
-extra:及其延迟
要什么值给什么值的查询,不做多余查询
Hibernate批量抓取
场景:要查询所有客户,返回list集合,我想得到每个客户中的联系人。
在客户的映射文件中,set标签配置
batch-size值,值越大发送sql语句越少
<set batch-size="10">