Hibernate增删改查操作(CRUD)

 
接下来,我们将介绍 Hibernate 是如何实现对数据库的增删改查(CRUD)操作的。

插入记录

Hibernate 在 Session 接口中为我们提供了一个 save() 方法,该方法可以向据库表中插入记录。

1. 在测试类 MyTest 中,创建一个名称为 testInsert 的方法,代码如下。
/**
* 保存数据
*/
@Test
public void testInsert() {
    //加载 Hibernate 核心配置文件
    Configuration configuration = new Configuration().configure();
    //创建一个 SessionFactory 用来获取 Session 连接对象
    SessionFactory sessionFactory = configuration.buildSessionFactory();
    //获取session 连接对象
    Session session = sessionFactory.openSession();
    //开始事务
    Transaction transaction = session.beginTransaction();
    //创建实体类对象
    User user = new User();
    user.setUserId("003");
    user.setUserName("编程帮新增用户");
    user.setPassword("654321");
    user.setEmail("14234567@qq.com");
    //向 user 表中插入数据,返回值为新增数据的主键 id
    Serializable save = session.save(user);
    System.out.println("新增数据的主键 id:"+save);
    //提交事务
    transaction.commit();
    //释放资源
    session.close();
    sessionFactory.close();
}

2. 运行测试方法 testInsert(),控制台输出如下。
Hibernate:
    insert
    into
        user
        (user_id, user_name, password, email)
    values
        (?, ?, ?, ?)
新增数据的主键 id:3

3. 查询数据库 user 表中的数据,结果如下表。

id user_id user_name password email
1 001 admin admin 12345678@qq.com
2 002 user 123456 98765432@qq.com
3 003 编程帮新增用户 654321 14234567@qq.com

由上表可以看出,我们成功地使用 Hibernate 向 user 表中添加了一条记录。

修改记录

Hibernate 在 Session 接口中为我们提供了一个 update() 方法,该方法可以用来修改数据库表中的记录。

1. 在 MyTest 类中,添加一个 testUpdate() 方法,代码如下。
/**
* 修改记录
*/
@Test
public void testUpdate() {
    //加载 Hibernate 核心配置文件
    Configuration configuration = new Configuration().configure();
    //创建一个 SessionFactory 用来获取 Session 连接对象
    SessionFactory sessionFactory = configuration.buildSessionFactory();
    //获取session 连接对象
    Session session = sessionFactory.openSession();
    //开始事务
    Transaction transaction = session.beginTransaction();
    //创建实体对象
    User user = new User();
    user.setId(3);
    //设置需要修改的字段
    user.setUserName("更新用户名");
    //直接调用 update() 方法进行修改
    session.update(user);
    //提交事务
    transaction.commit();
    //释放资源
    session.close();
    sessionFactory.close();
}

2. 执行测试方法 testUpdate(),控制台输出如下。
Hibernate:
    update
        user
    set
        user_id=?,
        user_name=?,
        password=?,
        email=?
    where
        id=?

3. 查询数据库 user 表中的数据,结果如下图。


图1:直接使用 update() 方法修改记录

从图 9 和控制台输出可知,update() 方法会更新指定记录的全部字段,对于我们没有指定的字段,Hibernate 则将其修改为默认值,这显然不是我们想要的结果。

通常我们会采用“先查询再修改”的方式来避免此问题的发生,即先将需要修改的记录查询出来,获得该条记录的实体对象,然后重新给该对象中的字段重新赋值,最后再使用该对象进行更新操作。

4. 修改 testUpdate() 方法的代码,采用“先查询再修改”的方式进行更新,代码如下。
/**
* 修改记录
*/
@Test
public void testUpdate() {
    //加载 Hibernate 核心配置文件
    Configuration configuration = new Configuration().configure();
    //创建一个 SessionFactory 用来获取 Session 连接对象
    SessionFactory sessionFactory = configuration.buildSessionFactory();
    //获取session 连接对象
    Session session = sessionFactory.openSession();
    //开始事务
    Transaction transaction = session.beginTransaction();
    //现将需要修改的记录查询出来
    User user = session.get(User.class, 3);
    //设置需要修改的字段
    user.setUserName("更新用户名");
    //直接调用 update() 方法进行修改
    session.update(user);
    //提交事务
    transaction.commit();
    //释放资源
    session.close();
    sessionFactory.close();
}

5. 重新执行测试方法 testUpdate() ,控制台输出如下。
Hibernate:
    select
        user0_.id as id1_0_0_,
        user0_.user_id as user_id2_0_0_,
        user0_.user_name as user_nam3_0_0_,
        user0_.password as password4_0_0_,
        user0_.email as email5_0_0_
    from
        user user0_
    where
        user0_.id=?
Hibernate:
    update
        user
    set
        user_id=?,
        user_name=?,
        password=?,
        email=?
    where
        id=?

6. 查询数据库 user 表中的数据,如下图。


图2:先查询在修改

从上图可知,我们成功地使用 Hibernate 修改了 user 表中的一条记录。

删除记录

Hibernate 在 Session 接口中,为我们提供了一个 delete() 方法,该方法用于删除数据库表中的记录。

1. 在 MyTest 类中,添加一个 testDelete() 方法,代码如下。
/**
* 删除记录
*/
@Test
public void testDelete() {
    //加载 Hibernate 核心配置文件
    Configuration configuration = new Configuration().configure();
    //创建一个 SessionFactory 用来获取 Session 连接对象
    SessionFactory sessionFactory = configuration.buildSessionFactory();
    //获取session 连接对象
    Session session = sessionFactory.openSession();
    //开始事务
    Transaction transaction = session.beginTransaction();
    User user = new User();
    user.setId(3);
    //删除指定的记录
    session.delete(user);
    //提交事务
    transaction.commit();
    //释放资源
    session.close();
    sessionFactory.close();
}

2. 执行测试方法 testDelete() ,控制台输出如下。
Hibernate:
    delete
    from
        user
    where
        id=?

3. 查询数据 user 表中的数据,结果如下图。


图3:删除记录

从上图可知,我们成功地使用 Hibernate 删除了 user 表中的一条记录。

查询数据

我们知道,Hibernate 通过 Session 接口提供的 get() 方法能够查询出一条指定的数据,但该方法无法查询多条或所有数库数据。

Hibernate 为用户提供了以下 3 种查询方式,它们都可以用来查询多条数据。
  • HQL 查询
  • QBC 查询
  • SQL 查询

HQL 查询

HQL 全称:Hibernate Query Language,它是一种面向对象的查询语言,它和 SQL 的语法相似,但 HQL 操作的是实体类对象及其中的属性,而不是数据库表中的字段。在 Hibernate 提供的各种检索方式中,HQL 是使用最广的一种检索方式。

1. 在数据库中执行以下 SQL 语句,向 user 表中添加 3 条使用 163 邮箱的用户数据。
INSERT INTO `user`(user_id, user_name, password, email) VALUES ( '003', 'user2', 'user2', '9dfasdfa@163.com');
INSERT INTO `user`(user_id, user_name, password, email) VALUES ( '004', 'user3', 'user3', '76543345@163.com');
INSERT INTO `user`(user_id, user_name, password, email) VALUES ( '005', 'user4', 'user4', '234543546@163.com');

2. 在 MyTest 类中,添加一个 testHqlQuery() 方法,该方法用于查询 user 表中的所有使用 163 邮箱的用户数据,代码如下。
/**
* 使用 HQL 查询
*/
@Test
public void testHqlQuery() {
    //加载 Hibernate 核心配置文件
    Configuration configuration = new Configuration().configure();
    //创建一个 SessionFactory 用来获取 Session 连接对象
    SessionFactory sessionFactory = configuration.buildSessionFactory();
    //获取session 连接对象
    Session session = sessionFactory.openSession();
    //开始事务
    Transaction transaction = session.beginTransaction();
    //创建 HQL 语句,语法与 SQL 类似,但操作的是实体类及其属性
    Query query = session.createQuery("from User where email like ?1");
    //查询所有使用 163 邮箱的用户
    query.setParameter(1, "%@163.com%");
    //获取结果集
    List<User> resultList = query.getResultList();
    //遍历结果集
    for (User user : resultList) {
        System.out.println(user);
    }
    //提交事务
    transaction.commit();
    //释放资源
    session.close();
    sessionFactory.close();
}

3. 执行测试方法 testHqlQuery() ,控制台输出如下。
Hibernate:
    select
        user0_.id as id1_0_,
        user0_.user_id as user_id2_0_,
        user0_.user_name as user_nam3_0_,
        user0_.password as password4_0_,
        user0_.email as email5_0_
    from
        user user0_
    where
        user0_.email like ?
net.biancheng.www.po.User{id=4, userId='003', userName='user2', password='user2', email='9dfasdfa@163.com'}
net.biancheng.www.po.User{id=5, userId='004', userName='user3', password='user3', email='76543345@163.com'}
net.biancheng.www.po.User{id=6, userId='005', userName='user4', password='user4', email='234543546@163.com'}

从以上控制台输出可知,我们成功地通过 HQL 查询到了 user 表中的多条数据。

QBC 查询

QBC 全称 Query By Criteria,是一种完全面向对象(比 HQL 更加面向对象)的对数据库查询技术。通过它对数据库进行查询时,应用程序不需要提供查询语句,而是通过 QBC API 中的相关的接口和类来设定需要查询的数据、查询条件等。

在 Hibernate 的早期版本中,通常通过以下方式使用 Criteria 查询数据库中的数据。
Criteria criteria = session.createCriteria(User.class);
criteria.add(Restrictions.eq("userName", "admin"));
List<Customer> list = criteria.list();

但 Hibernate5.2 之后,出于安全性考虑,这种方式已经基本废弃,现在 QBC 查询基本上都是使用 JPA(javax.persistence-api-xxx.jar)包中的 CriteriaBuilder(一个工厂类),来创建 CriteriaQuery 对象,以实现对数据库的操作。

QBC API 位于 javax.persistence.criteria 包中,主要包括以下接口:

接口 功能描述
CriteriaBuilder 用来生成 CriteriaQuery 实例对象的工厂。
CriteriaQuery QBC 主要的查询接口,通过它可以设定需要查询的数据。
Root 指定需要检索的对象图的根节点对象。
Selection 用来指定查询语句。
Expression Selection 接口的子接口,用来指定查询表达式。
Predicate Expression 接口的子接口,用来指定查询条件。

使用 QBC 查询时,需要以下步骤:
  1. 通过 Session 对象创建一个 CriteriaBuilder 实例;
  2. 通过 CriteriaBuilder 的实例对象创建一个 CriteriaQuery 的实例对象;
  3. 通过 CriteriaBuilder 对象创建一个 Root 的实例对象,并指定需要查询的对象图的根节点对象,Hibernate 会根据它来决定查询语句中的主表。
  4. 通过 CriteriaBuilder 提供的方法指定查询条件,并返回 Predicate 对象,Hibernate 根据它来决定查询语句中 where 子句的内容。
  5. 通过 Query 接口查询数据。

CriteriaBuilder 接口提供了一系列设定查询条件的方法,这些方法都返回 Predicate 对象,常用的设定条件查询的方法如下表。

方法 描述
equal() 等于
notEqual() 不等于
gt() 大于
ge() 大于等于
lt() 小于
le() 小于等于
between() 在……之间
like() 相似
isNotEmpty() 不为空
and()
or()

1. 在 MyTest 类中,添加一个 testQbcQuery() 方法,在该方法中,使用 QBC 查询 user 表中的所有使用 163 邮箱的用户数据,代码如下。
/**
* QBC 查询
*/
@Test
public void testQbcQuery() {
    //加载 Hibernate 核心配置文件
    Configuration configuration = new Configuration().configure();
    //创建一个 SessionFactory 用来获取 Session 连接对象
    SessionFactory sessionFactory = configuration.buildSessionFactory();
    //获取session 连接对象
    Session session = sessionFactory.openSession();
    //开始事务
    Transaction transaction = session.beginTransaction();
    //获得 CriteriaBuilder 对象
    CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
    //构建 CriteriaQuery 查询对象
    CriteriaQuery<User> criteria = criteriaBuilder.createQuery(User.class);
    //添加查询条件
    Root<User> from = criteria.from(User.class);
    Predicate like = criteriaBuilder.like(from.get("email"), "%@163.com%");
    criteria.where(criteriaBuilder.and(like));
    //获取结果集
    List<User> list = session.createQuery(criteria).getResultList();
    //遍历结果集
    for (User user : list) {
        System.out.println(user);
    }
    //提交事务
    transaction.commit();
    //释放资源
    session.close();
    sessionFactory.close();
}

2. 执行测试方法 testQbcQuery() ,控制台输出如下。
Hibernate:
    select
        user0_.id as id1_0_,
        user0_.user_id as user_id2_0_,
        user0_.user_name as user_nam3_0_,
        user0_.password as password4_0_,
        user0_.email as email5_0_
    from
        user user0_
    where
        user0_.email like ?
net.biancheng.www.po.User{id=4, userId='003', userName='user2', password='user2', email='9dfasdfa@163.com'}
net.biancheng.www.po.User{id=5, userId='004', userName='user3', password='user3', email='76543345@163.com'}
net.biancheng.www.po.User{id=6, userId='005', userName='user4', password='user4', email='234543546@163.com'}

从以上控制台输出可知,我们成功地通过 QBC 查询到了 user 表中的多条数据。

SQL 查询

Hibernate 同样支持使用原生的 SQL 语句对数据库进行查询。

1. 在 MyTest 类中,添加一个 testSqlQuery() 方法,该方法使用 SQL 查询 user 表中所有使用 163 邮箱的用户数据,代码如下。
/**
* SQL 查询
*/
@Test
public void testSqlQuery() {
    //加载 Hibernate 核心配置文件
    Configuration configuration = new Configuration().configure();
    //创建一个 SessionFactory 用来获取 Session 连接对象
    SessionFactory sessionFactory = configuration.buildSessionFactory();
    //获取session 连接对象
    Session session = sessionFactory.openSession();
    //开始事务
    Transaction transaction = session.beginTransaction();
    //构建 sql 查询
    NativeQuery sqlQuery = session.createSQLQuery("select * from user where email like '%163.com%'");
    sqlQuery.addEntity(User.class);
    //获得结果集
    List<User> resultList = sqlQuery.getResultList();
    //遍历结果集
    for (User user : resultList) {
    System.out.println(user);
    }
    //提交事务
    transaction.commit();
    //释放资源
    session.close();
    sessionFactory.close();
}

2. 执行测试方法 testSqlQuery() ,控制台输出如下。
Hibernate:
    select
        *
    from
        user
    where
        email like '%163.com%'
net.biancheng.www.po.User{id=4, userId='003', userName='user2', password='user2', email='9dfasdfa@163.com'}
net.biancheng.www.po.User{id=5, userId='004', userName='user3', password='user3', email='76543345@163.com'}
net.biancheng.www.po.User{id=6, userId='005', userName='user4', password='user4', email='234543546@163.com'}

从以上控制台输出可知,我们成功地使用 Hibernate 通过 SQL 查询到了 user 表中的多条数据。