Hibernate
Hibernate概述
- Hibernate框架应用在javaEE三层结构中的dao层框架
- 在dao层里面做对数据库crud(增上改查)操作,使用Hibernate实现crud操作,Hibernate底层代码就是jdbc,Hibernate对jdbc进行封装,使用Hibernate可以不用写复杂的jdbc代码,不需要写sql语句实现
- Hibernate是开源的轻量级的框架
ORM思想
什么是ORM
object relational mapping:对象关系映射
让实体类和数据库表进行一一对应关系
让实体类首先和数据库表对应
让实体类属性和表里面字段对应
不需要直接操作数据库表,而操作表对应实体类对象
Hibernate入门
搭建Hibernate环境
导入jar包(包括本身的lib中的required和jpa以及mysql驱动jar包和log4j日志jar包)
创建实体类
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30public class User {
//hibernate要求实体类中有一个属性唯一
private int uid;
private String uname;
private String pwd;
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getUname() {
return uname;
}
public void setUname(String uname) {
this.uname = uname;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}配置实体类和数据库表一对关系(映射关系)
创建xml格式的配置文件(位置没有固定文件,但建议在实体类所在包中,名称为实体类名.hbm.xml)
配置xml格式,在配置文件中首先引入xml约束,hibernate里面引入的是dtd约束
1
2
3- 配置映射关系
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34<!-- User.hbm.xml -->
<hibernate-mapping>
<!-- 1.配置类和表对应
class标签
name属性:实体类全路径
table属性:数据库表名称
-->
<class name="com.zephon.entity.User" table="user">
<!-- 2.配置实体类id和表id对应
hibernate要求实体类有一个属性唯一值
hibernate要求表有字段作为唯一值
-->
<!-- id标签
name属性:实体类里面id属性名称
column属性:生成的表字段名称
-->
<id name="uid" column="uid">
<!-- 设置数据库中增长策略
native:生成表id值就是主键自动增长
-->
<generator class="native"></generator>
</id>
<!-- 配置其它属性和表字段对应
name属性:实体类属性名称
column属性:生成表字段名称
-->
<property name="uname" column="uname"></property>
<property name="pwd" column="pwd"></property>
</class>
</hibernate-mapping>- 创建hibernate的核心配置文件(必须在src下,名称必须是hibernate.cfg.xml)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31<!-- hibernate.cfg.xml -->
<hibernate-configuration>
<session-factory>
<!-- 配置数据库信息 必须-->
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///JavaMysql0</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password"></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识别不同数据库特有的语句
-->
<!-- MySQL5.0之后,type=... 不再有效,所以修改方言中MySQLInnoDBDialect为MySQL5InnoDBDialect -->
<property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
<!-- 把映射文件放到核心配置文件中 -->
<mapping resource="com/zephon/entity/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>- 测试-实现添加操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35public class TestHibernate {
public static void main(String[] args) {
//1. 加载hibernate核心配置文件
//在src下找到名称是hibernate.cfg.xml的文件
Configuration cfg = new Configuration();
cfg.configure();
//2. 创建SessionFactory对象
//读取hibernate核心配置文件内容,创建sessionFactory
//在此过程中,根据映射关系,在数据库中把表创建
SessionFactory sessionFactory = cfg.buildSessionFactory();
//3. 使用SessionFactory创建session对象
// 类似于jdbc中的连接
Session session = sessionFactory.openSession();
//4. 开启事务
Transaction tx = session.beginTransaction();
//5. 写具体逻辑crud操作
User user = new User();
user.setUname("小明");
user.setPwd("123");
//调用session的方法实现添加
session.save(user);
//6. 提交事务
tx.commit();
//7. 关闭资源
session.close();
sessionFactory.close();
}
}
Hibernate 核心api
Configuration
1 | Configuration cfg = new Configuration(); |
到src下找到名称hibernage.cfg.xml配置文件,创建对象,将配置文件放到对象中,即加载核心配置文件
SessionFactory(重点)
使用configuration对象创建sessionFactory对象
1)创建sessionFactory过程中做的事:
根据核心配置文件中,数据库配置,映射文件部分,到数据库里根据映射关系创建表(前提是在配置文件中配置了需要创建表)
创建sessionFactory过程中,该过程特别耗资源,
解决:在hibernate操作中,建议每个项目一般创建一个sessionFactory对象
具体实现:写一个工具类,用静态代码块实现,静态代码块在类加载时执行,执行一次
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15public class HibernateUtils {
private static Configuration cfg = null;
private static SessionFactory sessionFactory = null;
static {
//加载核心配置文件
cfg = new Configuration();
cfg.configure();
sessionFactory = cfg.buildSessionFactory();
}
public static SessionFactory getSessionFactory(){
return sessionFactory;
}
}
Session(重点)
session类似于jdbc中connection
调用session里面不同的方法实现crud操作
1)添加 save
2)修改 update
3)删除 delete
4)根据id查询 get
session对象是单线程对象(不能共用,只能自己用)
Transaction
事务对象
1
2//4. 开启事务
Transaction tx = session.beginTransaction();事务的提交和回滚
1
2tx.commit();//提交
tx.rollback();//回滚事务
1)四个特性
原子性、一致性、隔离性、持久性
实体类编写规则
实体类里面的属性是私有的
私有属性使用对应公开的set、get方法
要求有一个属性作为唯一值(一般用id值)
属性建议不使用基本数据类型,使用基本数据类型对应的包装类
1)八个基本数据类型对应的包装类
int-Interger
char-Character
其它的都是首字母大写 如:double-Double
2)使用包装类的原因:
如:表示学生的分数,若int score;
学生得0分:int score=0;
学生没有参加考试,int score=0;不能准确表示
如果用包装类:Interger score = 0;得0分
Interger score=null; 没有参加考试
Hibernate主键生成策略
hibernate要求实体类里面有一个属性作为唯一值,对应表主键,主键可以不同生成策略
hibernate主键生成策略有很多的值
1
2
3
4<!-- 设置数据库中增长策略
native:生成表id值就是主键自动增长
-->
<generator class="native"></generator>在class属性中的值
演示使用uuid
- 使用uuid生成策略,实体类id属性类型必须改成字符串类型
- 配置部分改成uuid
实体类操作
添加
使用session.save方法
1 | User user = new User(); |
根据id查询
调用session.get方法
1 | //第一个参数:实体类的class,第二个参数:id值 |
修改
首先查询(根据id查询),再修改值
1 | //修改uid=2记录的uname值 |
删除
调用session.delete方法
1 | //删除 |
saveOrUpdate方法
实体类对象状态是瞬时态时,做添加操作
实体类对象状态是托管态时,做更新操作
实体类对象状态是持久态时,做更新操作
实体类对象状态(概念)
瞬时态
对象中没有id值,对象与session没有关联
1
2
3User u = new User();
u.setUname("jack");
u.setPwd("123");持久态
对象中有id值,与session有关联
1
User user = session.get(User.class,1);
托管态
对象中有id值,与session没有关联
1
2User user = new User();
user.setUid(3);
Hibernate的一级缓存
什么是缓存
数据存放到数据库里面,数据库本身是文件系统,使用流方式操作文件效率不是很高
1)把数据存到内存里面,不需要使用流方式,可以直接读内存中的数据
2)把数据存到内存中,提高读取效率
Hibernate缓存
hibernate框架中提供很多优化方式,hibernate的缓存就是一个优化方式
hibernate缓存特点:
第一类:hibernate的一级缓存
1)hibernate的一级缓存默认是打开的
2)hibernate的一级缓存使用范围,是session的范围,从session创建到session关闭
3)hibernate的一级缓存中,存储数据必须是持久态数据
第二类:hibernate的二级缓存
1)目前已经不使用了,替代技术redis
2)二级缓存默认不是打开的,需要配置
3)二级缓存使用范围,是sessionFactory范围
验证一级缓存的存在
1 | public class TestCasch { |
Hibernate一级缓存特性
持久态自动更新数据库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class TestCasch {
public static void main(String[] args) {
SessionFactory sessionFactory = HibernateUtils.getSessionFactory();
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
//1.根据id查询
User user = session.get(User.class,2);
//2.设置返回对象值
user.setUname("Lucy");
//3.调用方法实现
//session.update(user); //注释了仍然可以更新
transaction.commit();
session.close();
sessionFactory.close();
}
}执行过程(了解)
1)第一步查询时会把返回的user持久态对象放到一级缓存和缓存对应的快照区中
2)第二步设置对象值时会修改user对象里面的值,同时修改一级缓存内容,但不会修改一级缓存对应的快照区中内容
3)最后提交事务时,会比较一级缓存的内容和对应的快照区内容是否相同,若不同,则需要把一级缓存内容更新到数据库中
Hibernate事务代码规范写法
1.代码结构
1 | try{ |
2.实例
1 | public void testDemo(){ |
Hibernate绑定session
session类似于jdbc中的connection
Hibernate已经帮实现与本地线程绑定session
获取与本地线程绑定的session
1)在hibernate核心配置文件中配置
1
2
3<!-- 在hibernate核心配置文件中配置 -->
<property name="hibernate.current_session_context_class">thread</property>2)调用sessionFactory中的方法
1
2
3
4//提供返回与本地线程绑定的session的方法
public static Session getSessionObject(){
return sessionFactory.getCurrentSession();
}
Hibernate的api使用
Query对象
使用query对象,不需要写sql语句,但要写hql语句
1)hql:hibernate query language,hibernate提供的查询语言,和普通sql语句相似
2)hql和sql区别:
使用sql操作表和表字段,而使用hql操作实体类和属性
查询所有记录的hql语句
from 实体类名
Query对象使用
1)创建Query对象
2)调用Query对象里面的方法得到结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25public void testQuery(){
SessionFactory sessionFactory =null;
Session session = null;
Transaction transaction = null;
try{
sessionFactory = HibernateUtils.getSessionFactory();
// session = sessionFactory.openSession();
session = HibernateUtils.getSessionObject();
transaction = session.beginTransaction();
Query query = session.createQuery("from User");
List<User> list = query.list();
for(User u:list){
System.out.println(u);
}
transaction.commit();
}catch (Exception e){
transaction.rollback();
}finally {
session.close();
sessionFactory.close();
}
}
Criteria对象
使用这个对象查询时,不需要写语句,直接调用方法实现
实现过程
1)创建Criteria对象
2)调用方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public void testCriteria(){
SessionFactory sessionFactory =null;
Session session = null;
Transaction transaction = null;
try{
sessionFactory = HibernateUtils.getSessionFactory();
// session = sessionFactory.openSession();
session = HibernateUtils.getSessionObject();
transaction = session.beginTransaction();
Criteria criteria = session.createCriteria(User.class);
List<User> list = criteria.list();
for(User u:list){
System.out.println(u);
}
transaction.commit();
}catch (Exception e){
transaction.rollback();
}finally {
session.close();
sessionFactory.close();
}
SQLQuery对象
使用该对象,调用底层sql实现
实现过程
1)创建对象
2)调用方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30public void testSQL(){
SessionFactory sessionFactory =null;
Session session = null;
Transaction transaction = null;
try{
sessionFactory = HibernateUtils.getSessionFactory();
// session = sessionFactory.openSession();
session = HibernateUtils.getSessionObject();
transaction = session.beginTransaction();
NativeQuery sqlQuery = session.createSQLQuery("select * from ta_user");
//默认返回数组形式
// List<Object[]> list = sqlQuery.list();
// for(Object[] object:list){
// System.out.println(Arrays.toString(object));
// }
//设置返回对象形式
sqlQuery.addEntity(User.class);
List<User> list = sqlQuery.list();
for(User u:list){
System.out.println(u);
}
transaction.commit();
}catch (Exception e){
transaction.rollback();
}finally {
session.close();
sessionFactory.close();
}
}
待学
表与表之间的关系(一对多操作、多对多操作 )、hql、QBC等。。。。待学