基于JPA、JDBC
目录导航
本文内容基于Hibernate 5.2.17.Final版本。
1、连接数据库
1.1、加载数据源信息、对象和表的映射关系
通过Configuration类完成数据库连接的初始化操作,对应的示例代码实现如下:
Configuration configuration = new Configuration().configure();
其中Configuration类的configure方法默认加载资源目录(resource)下的配置文件,configure方法不传参数默认加载hibernate.cfg.xml该名称的文件,也可传入指定配置文件的名称。该方法的相关源码如下:
public Configuration configure() throws HibernateException {
return this.configure("hibernate.cfg.xml");
}
public Configuration configure(String resource) throws HibernateException {
this.standardServiceRegistryBuilder.configure(resource);
this.properties.putAll(this.standardServiceRegistryBuilder.getSettings());
return this;
}
hibernate.cfg.xml配置文件中,需要配置:
- 数据库url
- 数据库用户名
- 数据库密码
- 数据库连接使用的驱动类
- 数据库的方言类
- 对象和表的映射关系
简单配置示例如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!--数据库url-->
<property name="connection.url">jdbc:mysql://127.0.0.1:3306/db_test?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai</property>
<!--数据库用户名-->
<property name="connection.username">root</property>
<!--数据库密码-->
<property name="connection.password">123456</property>
<!--数据库连接使用的驱动类-->
<property name="connection.driver_class">com.mysql.cj.jdbc.Driver</property>
<!--数据库的方言类-->
<property name="dialect">org.hibernate.dialect.MySQL57Dialect</property>
<!--注解配置,对象和表的映射关系-->
<mapping class="org.example.model.Book"></mapping>
<!--xml配置,对象和表的映射关系-->
<!--<mapping resource="org/example/model/Book.hbm.xml"></mapping>-->
</session-factory>
</hibernate-configuration>
此处的注意点:
- url中如果需要符号“&”拼接参数,可能会报错,可用该符号的转义字符&代替。
- mapping标签配置对象表映射关系主要有两种方式:
- resource属性:xml文件中通过标签配置表字段和类属性的映射关系
- class属性:实体类中通过为类属性添加注解映射表字段
1.2、创建连接数据库的会话
先通过Cofiguration的实例获取SessionFactory对象实例,然后通过SessionFactory的API创建会话实例。
SessionFactory sessionFactory = configuration.buildSessionFactory();
1.2.1 openSession方法
该方法创建的会话实例,操作完成后需要调用close()方法进行手动关闭会话,线程不安全。
Session session = sessionFactory.openSession();
1.2.2 getCurrentSession方法
该方法创建的会话实例与当前线程绑定,要求必须开启事务,在事务提交或回滚后、线程结束后,自动关闭会话,线程安全。
Session session = sessionFactory.getCurrentSession();
1.2.3 openStatelessSession方法
该方法创建的会话实例,不会缓存实体的任何状态,适合批量操作时使用。
StatelessSession session = sessionFactory.openStatelessSession();
2、执行SQL
Hibernate底层封装了JDBC。
2.1 读写操作
Hibernate5提供三种执行SQL的方式:
- Session API
- Query API
- Criteria API
2.1.1 Session API 执行SQL
支持增删改查操作。
Book book = new Book();
// 插入
session.save(book);
// 修改
session.update(book);
// 根据参数,执行插入或修改
session.saveOrUpdate(book);
// 删除
session.delete(book);
// 主键查询(立即加载)
session.get(book);
// 主键查询(延迟加载)
session.load(book);
2.1.2 Query API 执行SQL
Hibernate 提供HQL和原生SQL两种方式,均支持增删改查。
- 插入
// HQL插入操作 (官方文档明确说明可以支持插入功能,部分玩家未get到其实现方式而以为不支持)
Query query = session.createQuery(
"INSERT INTO Book (name, price) " +
"SELECT :name, :price FROM Book");
query.setParameter("name", "水浒传");
query.setParameter("price", 39.9);
query.executeUpdate();
// 原生SQL插入操作
NativeQuery<Book> query = session.createNativeQuery("INSERT INTO book (name,price) values(:name,:price)", Book.class);
query.setParameter("name", "西游记");
query.setParameter("price", 59.9);
query.executeUpdate();
- 删除
// HQL删除操作
Query query = session.createQuery(
"DELETE FROM Book WHERE id=:id" );
query.setParameter("id", 6L);
query.executeUpdate();
// 原生SQL删除操作
NativeQuery<Book> query = session.createNativeQuery("DELETE FROM book WHERE id=:id", Book.class);
query.setParameter("id", 9);
query.executeUpdate();
- 修改
// HQL修改
Query query = session.createQuery(
"UPDATE Book SET price=:price WHERE id=:id" );
query.setParameter("id", 7L);
query.setParameter("price", 29.9);
query.executeUpdate();
// 原生SQL修改操作
NativeQuery<Book> query = session.createNativeQuery("UPDATE book SET price=:price WHERE id=:id", Book.class);
query.setParameter("id", 10L);
query.setParameter("price", 69.9);
query.executeUpdate();
- 查询
// HQL查询操作
Query query = session.createQuery(
"FROM Book WHERE id=:id" );
query.setParameter("id", 7L);
List<Book> list = query.list();
// 原生SQL查询操作
NativeQuery<Book> query = session.createNativeQuery("SELECT * FROM book WHERE id=:id", Book.class);
query.setParameter("id", 10);
List<Book> list = query.list();
2.1.3 Criteria API 执行SQL
Criteria方式为HQL和原生SQL查询提供了一种类型安全的替代方法。
Criteria方式支持删改查操作,暂未看到支持插入操作。
- 删除
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaDelete<Book> criteria = builder.createCriteriaDelete(Book.class);
Root<Book> root = criteria.from(Book.class);
criteria.where(builder.equal(root.<Long>get("id"), 7));
Query<Book> query = session.createQuery(criteria);
query.executeUpdate();
- 修改
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaUpdate<Book> criteria = builder.createCriteriaUpdate(Book.class);
Root<Book> root = criteria.from(Book.class);
criteria.set("price", 59.5);
criteria.where(builder.equal(root.<Long>get("id"), 8));
Query<Book> query = session.createQuery(criteria);
query.executeUpdate();
- 查询
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Book> criteria = builder.createQuery(Book.class);
Root<Book> root = criteria.from(Book.class);
criteria.where(builder.like(root.<String>get("name"), "%三%"));
Query<Book> query = session.createQuery(criteria);
List<Book> list = query.list();
2.2、缓存机制
- 一级缓存(Session):单个会话内,会话结束、缓存清除。
- 二级缓存(SessionFactory):所有会话共享,全局的缓存。
3、释放连接资源
session.flush();
session.clear();
session.close();