Hibernate增删改查操作(CRUD)
接下来,我们将介绍 Hibernate 是如何实现对数据库的增删改查(CRUD)操作的。
1. 在测试类 MyTest 中,创建一个名称为 testInsert 的方法,代码如下。
2. 运行测试方法 testInsert(),控制台输出如下。
3. 查询数据库 user 表中的数据,结果如下表。
由上表可以看出,我们成功地使用 Hibernate 向 user 表中添加了一条记录。
1. 在 MyTest 类中,添加一个 testUpdate() 方法,代码如下。
2. 执行测试方法 testUpdate(),控制台输出如下。
3. 查询数据库 user 表中的数据,结果如下图。
图1:直接使用 update() 方法修改记录
从图 9 和控制台输出可知,update() 方法会更新指定记录的全部字段,对于我们没有指定的字段,Hibernate 则将其修改为默认值,这显然不是我们想要的结果。
通常我们会采用“先查询再修改”的方式来避免此问题的发生,即先将需要修改的记录查询出来,获得该条记录的实体对象,然后重新给该对象中的字段重新赋值,最后再使用该对象进行更新操作。
4. 修改 testUpdate() 方法的代码,采用“先查询再修改”的方式进行更新,代码如下。
5. 重新执行测试方法 testUpdate() ,控制台输出如下。
6. 查询数据库 user 表中的数据,如下图。
图2:先查询在修改
从上图可知,我们成功地使用 Hibernate 修改了 user 表中的一条记录。
1. 在 MyTest 类中,添加一个 testDelete() 方法,代码如下。
2. 执行测试方法 testDelete() ,控制台输出如下。
3. 查询数据 user 表中的数据,结果如下图。
图3:删除记录
从上图可知,我们成功地使用 Hibernate 删除了 user 表中的一条记录。
Hibernate 为用户提供了以下 3 种查询方式,它们都可以用来查询多条数据。
1. 在数据库中执行以下 SQL 语句,向 user 表中添加 3 条使用 163 邮箱的用户数据。
2. 在 MyTest 类中,添加一个 testHqlQuery() 方法,该方法用于查询 user 表中的所有使用 163 邮箱的用户数据,代码如下。
3. 执行测试方法 testHqlQuery() ,控制台输出如下。
从以上控制台输出可知,我们成功地通过 HQL 查询到了 user 表中的多条数据。
在 Hibernate 的早期版本中,通常通过以下方式使用 Criteria 查询数据库中的数据。
但 Hibernate5.2 之后,出于安全性考虑,这种方式已经基本废弃,现在 QBC 查询基本上都是使用 JPA(javax.persistence-api-xxx.jar)包中的 CriteriaBuilder(一个工厂类),来创建 CriteriaQuery 对象,以实现对数据库的操作。
QBC API 位于 javax.persistence.criteria 包中,主要包括以下接口:
使用 QBC 查询时,需要以下步骤:
CriteriaBuilder 接口提供了一系列设定查询条件的方法,这些方法都返回 Predicate 对象,常用的设定条件查询的方法如下表。
1. 在 MyTest 类中,添加一个 testQbcQuery() 方法,在该方法中,使用 QBC 查询 user 表中的所有使用 163 邮箱的用户数据,代码如下。
2. 执行测试方法 testQbcQuery() ,控制台输出如下。
从以上控制台输出可知,我们成功地通过 QBC 查询到了 user 表中的多条数据。
1. 在 MyTest 类中,添加一个 testSqlQuery() 方法,该方法使用 SQL 查询 user 表中所有使用 163 邮箱的用户数据,代码如下。
2. 执行测试方法 testSqlQuery() ,控制台输出如下。
从以上控制台输出可知,我们成功地使用 Hibernate 通过 SQL 查询到了 user 表中的多条数据。
插入记录
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 | |
---|---|---|---|---|
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 查询时,需要以下步骤:
- 通过 Session 对象创建一个 CriteriaBuilder 实例;
- 通过 CriteriaBuilder 的实例对象创建一个 CriteriaQuery 的实例对象;
- 通过 CriteriaBuilder 对象创建一个 Root 的实例对象,并指定需要查询的对象图的根节点对象,Hibernate 会根据它来决定查询语句中的主表。
- 通过 CriteriaBuilder 提供的方法指定查询条件,并返回 Predicate 对象,Hibernate 根据它来决定查询语句中 where 子句的内容。
- 通过 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 表中的多条数据。