Hibernate 相信Java程序员都挺熟悉的了,不过应该国内的程序员都喜欢用MyBatis,老外更喜欢用Hibernate这种ORM框架。目前Quarkus只支持了Hibernate,包括响应式的方式目前也有了实现。本章简单介绍如何整合Hibernate。
1 本章目标
- 整合Hibernate
- 实现一个基本的CRUD
- 多数据源如何使用
- schema管理工具介绍
2 搭建项目
2.1 引入依赖
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm</artifactId>
</dependency>
<!-- JDBC driver dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy-jackson</artifactId>
</dependency>
这里还是使用的PG数据库,具体支持的数据库可以看上节的数据库配置。本章以非响应式数据源为例。
2.2 加入配置
创建application.properties 配置文件,添加配置 主要有两方面
- 数据源配置 见上节
- Hibernate配置
对于Hibernate配置其实有两种方式,一种就是在application.properties中配置,另一种就是传统的方式添加一个 persistence.xml。当前更推荐使用第一种方式。如果两种同时配置的话会抛出异常。
配置内容如下:
quarkus.datasource.db-kind=postgresql
quarkus.datasource.username=postgres
quarkus.datasource.password=postgres
quarkus.datasource.jdbc.url=jdbc:postgresql://192.168.199.125:5432/quarkus_demo
quarkus.hibernate-orm.log.sql=true
quarkus.hibernate-orm.log.format-sql=false
quarkus.hibernate-orm.log.bind-parameters=true
quarkus.hibernate-orm.database.generation=none
我的配置文件里主要配置了SQL日志的打印和schema管理方式。不过有一点奇怪的是,这里打印出来的SQL日志并没有参数信息。我并没有使用Hibernate自带的Schema管理后面会推荐一些管理工具。
更多配置见https://quarkus.io/guides/hibernate-orm#quarkus-hibernate-orm_configuration 这里的配置跟原生配置差不太多但也不完全一致请注意查看。
2.3 创建一个数据库映射实体
@Entity(name = "t_user")
public class User {
@Id
@SequenceGenerator(name = "user_id_seq", sequenceName = "user_id_seq", allocationSize = 1)
@GeneratedValue(generator = "user_id_seq")
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
最简单的配置就是在类上加一个@Entity 指明表,和@ID 字段。如果是自增主键的话需要添加两个注解,PG里的自增主键其实是会自动生成一个序列,通过@SequenceGenerator
和 @GeneratedValue
声明和使用一下就行了。
2.4 schema
CREATE TABLE "public"."t_user" (
"id" int2 NOT NULL DEFAULT nextval('user_id_seq'::regclass),
"name" varchar(255) COLLATE "pg_catalog"."default",
CONSTRAINT "user_pkey" PRIMARY KEY ("id")
)
;
ALTER TABLE "public"."t_user"
OWNER TO "postgres";
3 CRUD
项目搭建完了,接下来就可以愉快的CRUD了。直接创建一个UserResource来实现我们的CRUD接口。
3.1 Create
@Path("user")
public class UserResource {
@Inject
EntityManager entityManager;
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Transactional
public int save(User user){
entityManager.persist(user);
return 1;
}
这里操作数据源的Bean是EntityManager,它关联了实体和持久化上下文。说白了就是封装了操作数据源的各种方法。这里还必须要说的是@Transactional
,大家肯定都清楚这个是事物管理,但是测试来看,这里必须要加上不加会报错。Transaction is not active, consider adding @Transactional to your method to automatically activate one.
生成的SQL如下: 确实不显示参数
Hibernate: select nextval ('user_id_seq')
Hibernate: insert into t_user (name, id) values (?, ?)
3.2 Delete
@DELETE
@Consumes(MediaType.APPLICATION_JSON)
@Transactional
public User delete(User user){
var u = entityManager.getReference(User.class, user.getId());
entityManager.remove(u);
return u;
}
在我印象中只有我第一家工作时用过Hibernate,对Hibernate真的记不清了一个删除操作卡了我半天。不管删除或者更新操作需要获取这条记录的Session才能操作= =,说白了就是先查出来在操作。
3.3 修改
@PUT
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_JSON)
@Transactional
public User update(User user){
var u = entityManager.find(User.class, user.getId());
u.setName(u.getName()+"_UPDATE");
return u;
}
3.4 查询
@GET
@Path("{id}")
@Produces(MediaType.APPLICATION_JSON)
public Object getUserById(@PathParam("id") Integer id){
return entityManager.createNativeQuery("select * from t_user where id = ?").setParameter(1,id)
.getSingleResult();
}
查询我直接选择了写SQL的方式,也可以使用CriteriaQuery这种使用方式。
这样Quarkus整合Hibernate CRUD就完成了。其实我更期待的是Hibernate在响应式下应该如何用。
4 多数据源整合Hibernate
在上节中也讲过了,Quarkus支持多数据源,多异构数据库的支持。那Hibernate改如何配置呢?看过多数据源配置的同学应该对这种配置有了解了。格式如下:
quarkus.hibernate-orm."[name]".datasource=users
就是对配置项起一个别名来区分不同的配置。
引入多持久单元配置后会有两个问题
- 与数据库映射的Entity实例应该怎么绑定到正确的持久化单元
- 如何引入正确的持久化操作类
EntityManager
4.1 配置不同持久单元的Entity
- 方式一 添加配置项
quarkus.hibernate-orm."users".packages=org.acme.model.shared,org.acme.model.user
指明包路径 - 方式二 创建一个名为
package-info.java
的文件 在package上添加@io.quarkus.hibernate.orm.PersistenceUnit
注解。
注意是一个文件,不是类。
4.2 指定 EntityManager
@Inject
@PersistenceUnit("users")
EntityManager entityManager;
同样添加一个@PersistenceUnit(“users”)注解就可以了。
5 Schema 管理
什么是Schema管理呢,说简单点就是管理我们数据库的维护记录如 添加新表,修改表或者删除等。在没有使用管理工具前怎么操作的呢,就是在测试环境每个同事手动操作数据库,在上线前将变更脚本统一一下一块执行。这种方式管理不灵活且非常容易出问题。这里简单介绍接个Schema管理工具,具体使用方式大家可以看一下文档就可以了。
- Hibernate自带管理工具
- FlyWay
- Liquibase
- sqitch
Hibernate自带工具就不说了,虽然满足基本需求,但是功能太单一。Flyway和Liquibase 是Quarkus官方支持的工具,功能也比较全面只不过大部分功能需要收费,如果不差钱可以选择这两个。
Sqitch 是我们目前在用的Schema管理工具,使用简单功能也满足需求,主要是免费= =
总结
本章简单介绍了Quarkus整合Hibernate并简单实现了一个CRUD接口。在后面的文章将将进入深入Quarkus整合Hibernate的使用。