Posts 持久层框架——Hibernate
Post
Cancel

持久层框架——Hibernate

Hibernate

Hibernate简介

ORM(Object Relation Mapping)

译为:对象关系映射,解决了对象和关系型数据库之间得数据交互问题。

ORM技术可以根据提前配置好得对象和数据库之间的映射关系生成对应的SQL语句,整个过程不需要人工干预。

数据库 类/对象
表(table) 类(class)
表中的记录(record,也称行) 对象(Object)
表中的字段(field,也称列) 对象中的属性(attribute)

ORM框架

ORM 技术通常使用单独的框架,或者框架的某个模块来实现,下面列出了常用的 ORM 框架:

  • 常用的 Java ORM 框架有 Hibernate 和 Mybatis。
  • 常用的 Python ORM 实现有 SQLAlchemy 框架、Peewee 框架、Django框架的 ORM 模块等。
  • 常用的 PHP ORM 实现有 Laravel 框架、Yii 框架的 ORM 模块、ThinkPHP 框架的 ORM 模块等。

Hibernate是什么

一个开源免费的、基于ORM技术的Java持久化框架。

什么是ORM?

一种可以自动生成SQL语句的技术,它可以将对象中的数据自动存储到数据库中,也可以反过来将数据库中的数据自动提取到对象中。

什么是持久化?

就是将程序中的数据存储到数据库中。

将程序中的数据写入数据库,数据就可以永久存储,不会随着程序的关闭而消失了,所以将这个过程称为数据的持久化。

Hibernate支持的数据库

Hibernate 支持几乎所有主流的关系型数据库,只要在配置文件中设置好当前正在使用的数据库,程序员就不需要操心不同数据库之间的差异。 以下常见数据库都被 Hibernate 支持:

  • MySQL
  • Oracle
  • Microsoft SQL Server
  • DB2
  • PostgreSQL
  • FrontBase
  • Sybase

Hibernate 是一种全自动的 ORM 框架

Hibernate 是一款全自动的 ORM 框架。之所以将 Hibernate 称为全自动的 ORM 框架,这其实是相对于 MyBatis 来说的。

MyBatis 虽然是一种 ORM 框架,但它建立的映射关系是不完整的。Mybatis 只能将数据表映射到 Java 对象上,却不能将 Java 对象映射到数据表上,所以数据只能从数据表自动提取到 Java 对象中,反之则不行。要想将 Java 对象中的数据存储数据表中,开发人员需要手动编写 SQL 语句,依然非常麻烦,这就是 MyBatis 被称为半自动 ORM 框架的原因。

Hibernate 的缓存机制

​ Hibernate 提供了缓存机制(一级缓存、二级缓存、查询缓存),我们可以将那些经常使用的数据存放到 Hibernate 缓存中。当 Hibernate 在查询数据时,会优先到缓存中查找,如果找到则直接使用,只有在缓存中找不到指定的数据时,Hibernate 才会到数据库中检索,因此 Hibernate 的缓存机制能够有效地降低应用程序对数据库访问的频次,提高应用程序的运行性能。

Hibernate:CRUD

Hibernate 核心接口

Configuration(重量级)

​ Configuration 主要用于启动、加载和管理 Hibernate 的配置文件信息,在启动 Hibernate 的过程中,Configuration 实例首先确定 Hibernate 文件的位置,然后读取相关配置,最后创建一个唯一的 SessionFactory 实例。

1
Configuration config = new Configuration().configue("这里可以不写,也可以写hibernate.cfg.xml的路径");

需要注意的是,Configuration 对象只存在于系统的初始化阶段,它将 SessionFactory 创建完成后,就完成了自己的使命。

SessionFactory(重量级)

​ SessionFactory 接口负责读取并解析映射文件,以及建立 Session 对象,它在 Hibernate 中起到一个缓冲区的作用,会将 Configuration 对象中的所有配置信息、Hibernate 自动生成的 SQL 语句以及某些可重复利用的数据加载到缓冲区中。同时,它还维护了 Hibernate 的二级缓存。

1
SessionFactory sessionFactory = config.buildSessionFactory();

SessionFactory 具有以下特点。

  • 它是线程安全的,它的同一个实例能够供多个线程共享。
  • 它是重量级的,不能随意创建和销毁它的实例。

​ 由于 SessionFactory 是一个重量级的对象,占用的内存空间较大,所以通常情况下,一个应用程序只需要一个 SessionFactory 实例,只有应用中存在多个数据源时,才为每个数据源建立一个 SessionFactory 实例。为此,在实际开发时,通常会抽取出一个工具类提供 Session 对象。下面就介绍一个简单的抽取方式,如下所示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class HibernateUtils {
    // 声明一个私有的静态final类型的Configuration对象
    private static final Configuration config;
    // 声明一个私有的静态的final类型的SessionFactory对象
    private static final SessionFactory factory;
    // 通过静态代码块构建SessionFactory
    static {
        config = new Configuration().configure();
        factory = config.buildSessionFactory();
    }
    // 提供一个公有的静态方法供外部获取,并返回一个session对象
    // 也可以通过ThreadLocal实现多线程模式。
    public static Session getSession() {
        return factory.openSession();
    }
}

Session(此 Session 非 http 里的那个session)、

Session 是 Java 应用程序和 Hibernate 进行交互时所使用的主要接口,是持久化操作的核心 API。它主要用于读取、创建和删除映射对象的实例,这一系列的操作将被转换为数据表中的增加、修改、查询和删除操作。

Session 是轻量级的,实例的创建和销毁不需要消耗太多的资源,同时它还是 Hibernate 的一级缓存,这个缓存主要用于存放当前工作单元加载的对象。

1
2
3
4
5
6
7
8
9
10
/**
* 采用openSession方法创建Session
* 此方法直接创建一个新的Session实例,并且在使用完后需要调用close手动关闭。
*/
Session session = sessionfactory.openSession();
/**
* 采用getCurrentSession()方法创建Session
* 此方法创建的session会绑定在当前线程中,在提交或回滚后会自动关闭
*/
Session session = sessionFactory.getCurrentSession();

Transaction

Transaction 接口主要是用于管理事务,它是 Hibernate 的数据库事务接口,且对底层的事务接口进行了封装。Transaction 接口的实例对象是通过 Session 对象开启的,其开启方式如下所示:

1
Transaction transaction = session.beginTransaction();

事务管理方法:

  • commit(); //提交相关联的session实例
  • rollback(); //回滚
  • wasCommitted(); //检查事务是否提交
1
2
3
4
5
6
7
8
9
try{
    transaction = session.beginTransaction();
    session.save(user); //执行操作
    transaction.commit(); //提交
} catch(Exception e){
    transaction.rollback(); //回滚事务
} finally{
    session.close(); //关闭资源
}

Query(执行HQL)

Query 接口是 Hibernate 的查询接口,主要用于执行 Hibernate 的查询操作。Query 中包装了一个 HQL(Hibernate Query Language)查询语句,该语句采用了面向对象的查询方式,具有丰富灵活的查询特征。因此,Hibernate 官方推荐使用 HQL 语言进行查询。

  1. 在 Hibernate 中,使用 Query 对象的步骤如下。
  2. 获得 Hibernate Session 对象。
  3. 编写 HQL 语句。
  4. 调用 session.createQuery 创建查询对象。
  5. 如果 HQL 语句包含参数,则调用 Query 的 setXxx 设置参数。
  6. 调用 Query 对象的 list() 或 uniqueResult() 方法执行查询。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public void testFindAll() {
    Configuration config = new Configuration().configure();
    SessionFactory sessionFactory = config.buildSessionFactory();
    // 1.得到一个Session        
    Session session = sessionFactory.openSession();   
    Transaction transaction = session.beginTransaction();
    // 2.编写 HQL,其中的User代表的是类
    String hql = "from User";
    // 3.创建Query查询对象
    Query query = session.createQuery(hql);
    // 4.使用query.list()方法查询数据,并放入list集合
    List<User> list = query.list();
    for (User u : list) {
        System.out.println(u);
    }
    transaction.commit();
    session.close();
    sessionFactory.close();
}

Criteria(Hibernate 5: 已过时)

Criteria 接口是 Hibernate 提供的一个面向对象的查询条件接口,通过它完全不需要考虑数据库底层如何实现,以及 SQL 语句如何编写。Criteria 查询又称为 QBC 查询(Query By Criteria),是 Hibernate 的另一种对象检索方式。

一个单独的查询就是 Criterion 接口的一个实例,用于限制 Criteria 对象的查询,在 Hibernate 中 Criterion 对象的创建通常是通过 Restrictions 工厂类完成的,它提供了一系列的条件查询方法。

名 称 描 述
Criteria add(Criterion criterion) 用于设置查询的条件,这个方法的参数为 Criterion 对象的实例
Criteria addOrder(Order order) 用于设置结果集的排序规则,其参数为一个 Order 对象实例
Criteria createCriteria(String associationPath) 用于创建一个新的 Criteria,这个方法用于执行符合查询时设置查询条件
List list() 用于执行数据库查询,返回查询的结果
Criteria setFirstResult(int firstResult) 设置获取第一个记录的位置,这个位置从 0 开始算
Object uniqueResult() 这个方法用于得到唯一的结果对象实例。在确保最多只有一个 满足条件的查询结果时,可以选择适用这个方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
	public void testQBC() {
        Configuration config = new Configuration().configure();
        SessionFactory sessionFactory = config.buildSessionFactory();
        // 1.得到一个Session
        Session session = sessionFactory.openSession();
        Transaction transaction = session.beginTransaction();
        // 2.通过session获得Criteria对象
        Criteria criteria = session.createCriteria(User.class);
        // 3.使用Restrictions的eq方法设定查询条件为name="zhangsan"
        // 4.向Criteria对象中添加查询条件
        criteria.add(Restrictions.eq("name", "zhangsan"));
        // 5.执行Criterita的list()方法获得结果
        List<User> list = criteria.list();
        for (User u : list) {
            System.out.println(u);
        }
        transaction.commit();
        session.close();
        sessionFactory.close();
    }

Hibernate 执行增删改查的几种方法

一、session自带方法(oid)

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
35
36
Configuration cfg = new Configuration().configure();
SessionFactory sf = cfg.buildSessionFactory();
Session session = sf.openSession();
//查----
Object obj = session.get(Object.class, "这里放置的参数要与所查询的类同类型");
System.out.println(Object.toString());
//增----
session.beginTransaction();
Object obj = new Object();
obj.setXXX();
...;
session.save(obj);
session.getTransaction().commit();
//改----
session.beginTransaction();
Object obj = session.get(Object.class, "要更新的数据的主键");
obj.setXXX();//更改数据
/*
* 有三种方法更新
* 1.merge:合并两个对象。
* 2.update:直接更新。
* 3.saveOrUpdate:有就保存,没有就更新(一般用这个)
*/
session.saveOrUpdate(obj);
session.save(obj);
session.getTransaction().commit();
//删----
session.beginTransaction();
Object obj = session.get(Object.class, "要更新的数据的主键");
session.delete(obj);
session.saveOrUpdate(obj);
session.save(obj);
session.getTransaction().commit();
//关闭session和sessionFactory
session.close();
sf.close();

二、HQL

条件查询
1
2
3
4
5
6
7
from User user where user.age=20;
from User user where user.age between 20 and 30;
from User user where user.age in(20,30);
from User user where user.name is null;
from User user where user.name like %zx%;
from User user where (user.age%2)=1;
from User user where user.age=20 and user.name like %zx%;
实体更新和删除(Hibernate3新增)

更新

1
2
3
4
5
Transaction trans = session.beginTransaction();
String hql = "update User user set user.age=20 where user.age=18";
Query queryupdate = session.createQuery(hql);
int ret = queryupdate.executeUpdate();
trans.commit();

删除

1
2
3
4
5
Transaction trans=session.beginTransaction();
String hql=delete from User user where user.age=18;
Query queryupdate=session.createQuery(hql);
int ret=queryupdate.executeUpdate();
trans.commit();
属性查询
1
2
3
4
5
6
7
8
9
10
11
12
//检索一个
List list = session.createQuery("select user.name from User user").list();
for(int i = 0;i<list.size();i++){
    System.out.println(list.get(i));
}
//检索多个
List list=session.createQuery(select user.name,user.age from User user ).list();
for(int i=0;i<list.size();i++){
    Object[] obj=(Object[])list.get(i);
    System.out.println(obj[0]);
    System.out.println(obj[1]);
}

参考:Faron

三、Criteria(QBC:Query By Criteria)

QBC的组成:

Criteria、Criteriion、Order、Restrictions(常用)

Restrictions:Criteria最重要的工具

比较运算符等价函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
=   Restrictions.eq() 等于
<>   Restrictions.not(Exprission.eq()) 不等于
>   Restrictions.gt() 大于
>=   Restrictions.ge() 大于等于
<   Restrictions.lt() 小于
<=   Restrictions.le() 小于等于
is null   Restrictions.isnull() 等于空值
is not null   Restrictions.isNotNull() 非空值
like   Restrictions.like() 字符串模式匹配
and   Restrictions.and() 逻辑与
and   Restrictions.conjunction() 逻辑与 
or   Restrictions.or() 逻辑或
or   Restrictions.disjunction() 逻辑或
not   Restrictions.not() 逻辑非
in(列表)   Restrictions.in() 等于列表中的某一个值
ont in(列表)   Restrictions.not(Restrictions.in())不等于列表中任意一个值
between x and y   Restrictions.between() 闭区间xy中的任意值
not between x and y   Restrictions.not(Restrictions..between()) 小于值X或者大于值y

与 in 结合

1
cri.add(Restrictions.in("要查询的字段", new 数组))

直接使用SQL

1
2
3
4
List cats = sess.createCriteria(Cat.class) 
.add( Restrictions.sql("lower({alias}.name) like lower(?)", "Fritz%", 
Hibernate.STRING) )
.list();
标准查询
1
2
Criteria cr = session.createCriteria(Employee.class);  
List results = cr.list();  
分页查询
1
2
3
4
Criteria crt = session.createCriteria(Object.class);
crt.setFirstResult(0);//查询页数
crt.setMaxResults(10);//每页最大数据条数
List results = crt.list();
排序查询
1
2
3
4
5
6
7
8
Criteria cr = session.createCriteria(Employee.class);
// To get records having salary more than 2000
cr.add(Restrictions.gt("salary", 2000));
// To sort records in descening order
crit.addOrder(Order.desc("salary"));
// To sort records in ascending order
crit.addOrder(Order.asc("salary"));
List results = cr.list();

参考:Faron

This post is licensed under CC BY 4.0 by the author.

JavaWeb基础——servlet

Spring——基础(持续更新中)

Comments powered by Disqus.