什么是Hibernate框架:
1、hibernate框架应用在javaee三层结构中dao层框架
2、在dao层里面做对数据库crud操作,使用hibernate实现crud操作。hibernate底层代码就是jdbc,hibernate对jdbc进行封装,使用hibernate好处就是不需要写复杂的jdbc代码了,不需要写sql语句实现
3、hibernate开源的轻量级框架
ORM思想
hibernate使用orm思想对数据库进行crud操作
orm:object relational mapping 对象关系映射
让实体类和数据库表进行一一对应关系
让实体类首先和数据库表对应
让实体类属性和表里面字段对应
不需要直接操作数据库表而操作表对应实体类对象
搭建hibernate环境
1、导入jar包,lib目录下的required文件夹、mysql驱动、和外部日志jar包
2、创建实体类
public class User(){
/*hibernate要求实体类要有一个属性唯一的*/
}
3、使用hibernate不需要自己手动建表,hibernate会自动建表
4、配置实体类和数据库一一对应关系(映射关系)
使用配置文件实现映射关系
1、创建XML格式的配置文件:映射配置文件名称和位置没有固定要求,一般建议在实体类所在的包里面创建,名字:实体类名称.xml
2、配置文件是xml格式,在配置文件中首先引入xml约束
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
3、配置映射关系
<hibernate-mapping>
<!--配置类和表对应
class标签
name属性:实体类全路径
table属性:数据库表名
-->
<class name=" " table="t_user">
<!--配置实体类id和表id对应
hibernate要求实体类有一个属性唯一值
hibernate要求表有字段作为唯一值
-->
<!--id标签
name属性:实体类里面id属性名称
column属性:生成表字段名称
-->
<id name="uid" column="uid">
<!--设置数据库表id增长策略
native:生成表id值是主键自动增长
-->
<generator class="native"></generator>
</id>
<!--配置其他属性和表字段对应
name属性:实体类属性名称
column属性:生成表字段名称
-->
<property name="属性名" column="生成表字段名称"></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-configuration>
<session-factory>
<!--配置数据库信息-->
<!-- property 元素用于配置Hibernate中的属性
键:值
-->
<!-- hibernate.connection.driver_class : 连接数据库的驱动 -->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- hibernate.connection.username : 连接数据库的用户名 -->
<property name="hibernate.connection.username">root</property>
<!-- hibernate.connection.password : 连接数据库的密码 -->
<property name="hibernate.connection.password">123</property>
<!-- hibernate.connection.url : 连接数据库的地址,路径 -->
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernatedemo</property>
<!--配置hibernate信息,这部分是可选的-->
<!-- show_sql: 操作数据库时,会 向控制台打印sql语句 -->
<property name="show_sql">true</property>
<!-- format_sql: 打印sql语句前,会将sql语句先格式化 -->
<property name="format_sql">true</property>
<!-- hbm2ddl.auto: 生成表结构的策略配置
update(最常用的取值): 如果当前数据库中不存在表结构,那么自动创建表结构.
如果存在表结构,并且表结构与实体一致,那么不做修改
如果存在表结构,并且表结构与实体不一致,那么会修改表结构.会保留原有列.
create(很少):无论是否存在表结构.每次启动Hibernate都会重新创建表结构.(数据会丢失)
create-drop(极少): 无论是否存在表结构.每次启动Hibernate都会重新创建表结构.每次Hibernate运行结束时,删除表结构.
validate(很少):不会自动创建表结构.也不会自动维护表结构.Hibernate只校验表结构. 如果表结构不一致将会抛出异常.
-->
<property name="hbm2ddl.auto">update</property>
<!-- 数据库方言配置
org.hibernate.dialect.MySQLDialect (选择最短的)
-->
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<!-- hibernate.connection.autocommit: 事务自动提交 -->
<property name="hibernate.connection.autocommit">true</property>
<!-- 将Session与线程绑定=> 只有配置了该配置,才能使用getCurrentSession -->
<property name="hibernate.current_session_context_class">thread</property>
<!--把映射文件放到核心配置文件中-->
<mapping resource="com/it/a_hello/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
实现添加操作
1、加载hibernate核心配置文件
Configuration sfg = new Configuration();
cfg.configure();
2、创建SessionFactory对象
SessionFactory sf = sfg.buildSessionFactory();
3、使用SessionFactory创建session对象
Session s = sessionFactory.openSession();
4、开启事物
Transation tx = s.beginTransation();
5、写具有逻辑curd操作
User user = new User();
user.setUsername();
user.setUserage();
user.setUseradd();
//调用session的方法实现添加
s.save(user);
6、提交事物
tx.commit();
7、关闭资源
session.close();
sessionFactory.close();
Hibernate配置文件详解
映射配置文件
1、名称和位置没有固定要求
2、映射问价那种,标签name属性值写实体类相关内容:class标签name属性值实体类全路径,id标签和property标签name属性值实体类属性名称
3、id标签和property,column属性可以省略,省略默认的值和name的值一样
4、property标签type属性,设置生成表字段的类型,自动生成对应类型
核心配置文件
1、核心配置写位置要求
2、数据库部分必须的,hibernate部分可选,映射文件必须的
3、位置.src下,文件名hibernate.cfg.xml
hibernate核心api
Configuration
1、到src下面找到名称hibernate.cfg.xml文件,并加载
SessionFactory
Session
Transation
实体类的编写
1、实体类里的属性是私有的
2、私有属性要使用公开的get和set方法
3、要求实体类有属性作为唯一值(一般用id值)
4、实体类属性建议不使用基本数据类型,使用基本数据类型对应的包装类。
Hibernate主键生成策略:
1、要求实体类有一个属性作为唯一值,对应表主键,主键可以有不同生成策略
2、主键生成策略有很多的值
3、在class属性里面由值
native:根据使用的数据库选择哪个值
uuid:之前web阶段写代码生成uuid,hebernate会自动帮我生成uuid值
使用uuid生成策略,实体类id属性必须是字符串类型
实体类操作
1、调用session的save方法实现添加
2、根据id查询
//调用session里面的get方法实现
//调用工具类得到sessionFactory
SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
//获取session
Session session = sessionFactory.openSession();
//开启事物
Transaction tx = session.beginTransaction();
//根据id查询
User user = session.get(实体类的class, id的值);
//提交事物
tx.commit();
//关闭
session.close();
sessionFactory.close();
修改操作
1、先根据id查找值
//调用session里面的get方法实现
//调用工具类得到sessionFactory
SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
//获取session
Session session = sessionFactory.openSession();
//开启事物
Transaction tx = session.beginTransaction();
//修改操作
//先根据id查询
User user = session.get(实体类的class, id的值);
//向返回的的user对象里面修改值
user.setUsername();
//调用session的update方法修改
session.update(user);
//提交事物
tx.commit();
//关闭
session.close();
sessionFactory.close();
删除操作
1、先根据id查找值
//调用session里面的get方法实现
//调用工具类得到sessionFactory
SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
//获取session
Session session = sessionFactory.openSession();
//开启事物
Transaction tx = session.beginTransaction();
//修改操作
//先根据id查询
User user = session.get(实体类的class, id的值);
//调用session的delete删除
---------------
//方法一:根据id删除
session.delete(user);
//方法二:
User user = new User();
user.setUid(3);
session.delete(user);
-------------------
//提交事物
tx.commit();
//关闭
session.close();
sessionFactory.close();
实体类状态:
1、瞬时态:对象没有id值,对象与session没有关联
2、持久态:对象有id值,对象与session有关联
3、托管态:对象有id值,但是与session没有关联
实体类对象的方法:
saveOrUpdate方法:实现添加、修改。实体类对象是瞬时态,做添加操作;托管态,做修改操作;持久态,做修改操作
Hibernate的一级缓存:
数据存到数据库里面,数据库本身是文件系统,使用流方式操作文件效率不是很高。把数据存到内存中,不需要使用流方式,可以直接读取内存中的数据,提高读取效率。
Hibernate框架提供了很多优化方式,hibernate缓存就是一个优化方式
hibernate缓存特点:
1、hibernate的一级缓存
1、hibernate的一级缓存默认是打开的
2、hibernate的一级缓存使用范围,是session范围,从session创建d到session关闭范围
3、hibernate的一级缓存中,存储数据必须是持久态数据
2、hibernate的二级缓存
目前已经不使用了,替代技术:redis
二级范围默认不是打开的,需要打开
使用范围是sessionFactory范围
hibernate事务操作
什么是事务?
事务特性
不考虑隔离性产生问题:
1、脏读
2、不可重复读
3、虚读
事务隔离级别:mysql默认隔离级别:repeatable read
Hibernate事务代码规范写法:
代码结构:
SessionFactory sessionFactory = null;
Session session = null;
Transation tx = null;
try{
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransation();
//增删改操作
//...
//提交事务
tx.commit();
}catch(){
//回滚事务
tx.rollback();
}finally{
//关闭
}
Hibernate绑定session
1、session类似jdbc的connection
2、帮实现与本地线程绑定session
3、获取与本地线程session
1、在hibernate核心配置文件中配置
<property name="hibernate.current_session_context_class">thread</property>
2、调用sessionFactory中的方法得到
sessionFactory.getCurrentSession();
得到与本地线程绑定的session
session = HibernateUtils.getSessionobject();
获取与本地线程绑定session的时候,关闭session报错,这个时候不需要手动关闭
查询所有
Query对象
使用query对象,不需要写sql语句,但是写hql语句(hibernate query language Hibernate提供查询语句,这个hql语句和普通sql语句很相似)
使用普通sql操作表和表字段,hql操作的是实体类和属性
查询所有hql语句:form 实体类名称
query对象使用:
1、创建Query对象
Query query = session.createQuery("from 实体类名");
2、调用query对象里面的方法得到结果
List<实体类名> list = query.list();
Criteria对象
使用这个对象查询操作,这个对象不需要写语句
实现过程:
1、创建Criteria对象
Criteria c = session.createCriteria(实体类.class);
2、调用方法得到结果
List<...> list = c.list();
SQLQuery对象
使用hibernate也能调用底层sql实现
SQLQuery sq = session.createSQLQuery("普通sql语句");
//默认里面每部分数组结构
List<Object[]> list = sq.list();
//上面这种形式每部分是数组,现在想返回每部分是对象
//返回每部分是对象形式,步骤如下:
sq.addEntity(实体类名.class);
List<实体类名> list = sq.list();
多表操作
表与表之间的关系
1、一对多
一对多映射配置
第一步:创建两个实体类(客户、联系人)
第二步:让这两个实体类之间互相表示
1、在客户实体类里面表示多个联系人 ,hibernate表示一个客户有多个联系人要求使用集合表示多的数据,使用set集合
2、在联系人实体类里面表示所属客户
第三步:配置映射关系
1、一般一个实体类对应一个映射文件
客户配置:
联系人配置:
2、把映射基本的配置完成
3、在映射文件中,配置一对多关系
在客户的映射文件中,表示所有联系人
<!--使用set属性表示所有联系人,name属性写实体类里面表示联系人set集合的名称-->
<set name="set集合名">
<!--一对多建表,有外键,hibernate机制,双向维护外键,在一和多那一方都配置外键-->
<key column="外键名"></key>
<one-to-many class="联系人实体类完整路径"/>
</set>
联系人映射文件中,表示所属客户
<many-to-one name="客户实体类名称" class="客户实体类全路径" colum="外键,和客户配置中key值一致"></many-to-one>
第四步:创建核心配置文件,把创建的配置文件引入到核心配置文件中
----------------------------------------------------------------------------------------------------------------------------------
一对多级联操作
级联保存
添加一个客户,为这个客户添加多个联系人
方式一:
1、创建客户和联系人对象
2、创建对象和联系人对象关系,把客户放联系人里面,把联系人放客户中
3、保存到数据库 session的save方法
方式二:
一般根据客户添加联系人
1、在客户映射文件进行配置
在set标签上进行配置,cascade属性代表级联保存
<set name="" cascade="save-update">
2、创建客户和联系人对象,只需要把联系人放到客户里面,最后只需要保存客户就可以
级联删除
删除某一个客户,这个客户里面多有联系人删除
删除某个客户,把客户里面所有联系人删除
1、在客户的映射文件set标签,进行配置
<set name="" cascade="delete">
如果级联保存的时候已经进行了配置,这个时候有多个值,多个值之间用英文逗号隔开delete,save-update
2、在代码中直接删除客户
根据id查询对象,根据session的delete删除
一对多修改操作
1、根据id查询联系人,根据id查询客户
2、设置持久态对象值,把客户放联系人里面,把联系人放客户中
inverse属性
因为hibernate是双向维护外键,在客户和联系人里面都需要维护外键,对性能有损耗,可以让其中一方不维护外键。
一对多里面,让其中一方放弃外键维护,让其中一的那方放弃维护
在set标签使用inverse属性配置
默认false代表不放弃关系维护,true放弃关系维护
<set inverse="true">
2、多对多
多对多映射配置
以用户和角色为例
1、创建实体类:用户和角色
2、让两个实体类互相表示
用户里面表示所有角色,使用set集合
一个角色有多个用户,使用set集合
3、配置映射关系
基本配置
配置多对多关系
在用户里面表示所有角色,用set标签
<set table="第三张表的名称">
<key column="配置当前映射文件在第三张表外键的名称"></key>
<many-to-many class="" column="角色在第三张表中外键名称"></many-to-many>
</set>
在角色里面表示所有用户,用set标签
<set table="第三张表的名称">
<key column="配置当前映射文件在第三张表外键的名称"></key>
<many-to-many class="" column="角色在第三张表中外键名称"></many-to-many>
</set>
4、在核心配置文件中引入映射文件
多对多级联保存
1、在用户配置文件中set标签进行配置,cascade值save-update
2、创建用户和角色对象,把用户方用户里面,最终保存用户就可以
多对多级联删除
1、在set标签进行配置,cascade值delete
2、先查再删,session.delete();
维护第三张表关系
用户和角色多对多关系,维护关系通过第三张表维护
让某个用户有某个角色
1、根据id查询用户和角色
2、把角色放到用户里面
把角色对象放到用户set集合
让某个用户没有某个角色
1、根据id查询用户和角色
2、从用户对象删除角色
在用户set集合删除角色对象
3、一对一
Hibernate查询方式
1、对象导航查询
根据id查询某个客户,再想查询客户里面所有的联系人
SessionFactory sessionFactory = null
Session session = null;
Transaction tx = null;
try{
sessionFactory = HibernateUtils.getSessionFactory();
session = sessionFactroy.openSession();
tx = session.beginTransaction();
//查询cid=1的客户,再查询这个客户里面所有联系人
Customer customer = session.get(Customer.class, 1);
//直接得到客户里面所有联系人的set集合
ser<linkMan> linkman = customer.getSetLinkMan();
tx.xommit();
}catch(Exception e){
tx.rollback();
}finally{
session.close();
sessionFactory.close();
}
2、OID查询
根据id查询某一条记录,返回对象
根据id查询记录,调用session里面的get方法
Customer customer = session.get(Customer.class, 1);
3、hql查询
Query对象,写hql语句实现查询
hql:hibernate query language
区别:普通sql操作数据库表和字段,hql操作实体类和属性
常用的hql语句
·查询所有
Query query= session.createQuery("from 实体类名称");
List<实体类名称> list = query.list();
·条件查询
hql支持 实体类别名.实体类属性 的格式
from 实体类名称 实体类别名 where 实体类别名.实体类属性名称=? and 实体类别名.实体类属性名称=?
from 实体类名称 where 实体类属性名称=? and 实体类属性名称=?
Query query = session.createQuery("...");
//设置条件值
query.setParameter(int i, Object obj);
//第一个参数是问号的位置,第二个参数具体参数值,问号的位置是0开始的
条件查询模糊查询
from Customer c where c.custName like ? //c是别名
_值_
%值
·排序查询
Query query = session.createQuery();
from 实体类名称 orber by 实体类属性名称 asc/desc
·分页查询
Query对象封装了两个方法实现分页操作:
//查询所有
Query query = session.createQuery("from Customer");
//设置分页数据
设置开始位置:
query.setFirstResult(0);
//设置每页显示的记录数
query.setMaxResult(4);
//调用方法调用最终的结果
List<Customer> list = query.list();
·投影查询
select 实体类属性名1,实体类属性名2 from 实体类名称
select后面不支持 * 号
Query query = session.createQuery();
·聚集函数使用
select count(*) from Customer
select sum(*) from Customer
select avg(*) from Customer
select max(*) from Customer
select min(*) from Customer
Query query = session.createQuery("");
调用方法得到结果
Object obj = query.uniqueResult();//注意,这个返回的Object类型实际是long类型,如果要转换成int类型,先要强转long类型,再转int类型
使用hql查询操作时候,使用Query对象实现
1、创建Query对象,写hql语句
2、调用query对象方法得到结果
·多表查询
内连接查询hql语句写法
以客户和联系人为例
form 客户实体类 别名 inner join 别名.setLinkMan集合 //别名可以不要
from Customer c inner join c.setLinkMan;
左外连接
from Customer c left outer join c.setLinkMan
迫切左外连接:from Customer c left outer join fetch c.setLinkMan
4、QBC查询
Criteria对象
使用qbc时候,不需要写语句,写方法就可以,使用qbc时候,操作实体类和属性
1、创建Criteria对象
2、调用方法
·查询所有
Criteria c = session.createCriteria(Customer.class);
List<Customer> list = c.list();
·条件查询
Criteria c = session.createCriteria(Customer.class);
//使用add方法,,表示设置条件值
方法(属性,条件值)
Restrictions.eq 等于
Restrictions.allEq 使用Map,使用key/value进行多个等于的比对
Restrictions.gt 大于 >
Restrictions.ge 大于等于 >=
Restrictions.lt 小于 <
Restrictions.le 小于等于 <=
Restrictions.between 对应SQL的BETWEEN子句
Restrictions.like 对应SQL的LIKE子句
Restrictions.in 对应SQL的in子句
Restrictions.and and关系
Restrictions.or or关系
多个条件
//业务:查询出id大于1,名字中带ji的用户
criteria.add(Restrictions.like("name","%ji%"))
criteria.add(Restrictions.gt("id", 1));
·排序查询
criteria.addOrder(Order.desc("id"))
·分页查询
Criteria中提供了两个方法,setFirstResult方法和setMaxResults,一个是数据的开始位置0表示第一条记录,一个是返回的记录数。
Criteria crit = session.createCriteria(Conft.class);
crit.setFirstResult(0);
crit.setMaxResults(10);
List<Conft> list = crit.list();
·统计查询
Criteria crit = session.createCriteria(Conft.class);
//设置操作
crit.setProjection(Projections.rowCount());
//调用方法得到结果
Object obj = crit.uniqueResult();//实际是long类型
·离线查询
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
DetachedCriteria criteria = DetachedCriteria.forClass(Linkman.class);
// 设置查询条件
criteria.add(Restrictions.eq("lkm_gender", "男"));
// 查询数据
List<Linkman> list = criteria.getExecutableCriteria(session).list();
for (Linkman linkman : list) {
System.out.println(linkman);
}
tr.commit();
5、本地sql查询
SQLQuery对象,使用普通sql实现查询
hibernate检索策略
hibernate检索分为两类
1、立即查询:根据id查询,调用get方法,一调用get方法马上发送查询数据库
2、延迟查询:根据id查询,还有load方法,调用load方法不会马上查询,只有得到对象里面的值的时候才会发送语句查询数据库