使用
Hibernate ORM的过程中,会有很多烦人的事情发生。
- ID逻辑,通常我们并不关心ID是怎么生成的,只是用做主键。
- 大量的
getter、setter方法,受益于贫血模型,但在使用中,我们只是使用这些方法来获取或者设置属性。 - 早起的Java EE模式建议我们将
Entity、DAO的进行划分,但在使用中,其实DAO通常都是空置的,这种多余的层级结构没有带来应有的价值。 - Hibernate提供了强大的通用的方法,但是大多数并没有被用到,这是一种浪费。
- 实际使用中,Hibernate在大多数的琐碎查询中显得更加复杂。
引入
<dependencies>
<!-- Hibernate ORM specific dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-hibernate-orm-panache</artifactId>
</dependency>
<!-- JDBC driver dependencies -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-mysql</artifactId>
</dependency>
</dependencies>
配置文件
quarkus.datasource.db-kind=mysql
quarkus.datasource.username=root
quarkus.datasource.password=123456
quarkus.datasource.jdbc.url=jdbc:mysql://127.0.0.1:3306/demo?characterEncoding=utf8&useSSL=false
quarkus.datasource.jdbc.max-size=8
quarkus.datasource.jdbc.min-size=1
# 日志
quarkus.hibernate-orm.log.sql=true
# 初始化脚本
quarkus.hibernate-orm.sql-load-script=import.sql
# 自动创建表
quarkus.hibernate-orm.database.generation=drop-and-create
定义数据库实体
通过继承PanacheEntity 或者 PanacheEntityBase,下面简单介绍了下基础的编码操作,Panache可以支持链式调用的,也可以返回Stream。
默认ID
@Entity
public class Person extends PanacheEntity {
public String name;
public LocalDate birth;
public Status status;
}
自定义ID
@Entity
public class Person extends PanacheEntityBase {
@Id
@SequenceGenerator(
name = "personSequence",
sequenceName = "person_id_seq",
allocationSize = 1,
initialValue = 4)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "personSequence")
public Integer id;
public String name;
public LocalDate birth;
public Status status;
}
定义的字段是public的,其实底层还是通过getter、setter来进行访问的,所以我们可以通过编写getter、setter来进行特殊处理。
基本操作
新增
@Transactional
public Person create() {
Person person = new Person();
person.name = "Stef";
person.birth = LocalDate.of(1910, Month.FEBRUARY, 1);
person.status = Status.Alive;
// 进行持久化
person.persist();
return person;
}
单条查询
查询实体
Person person = Person.findById(personId);
查询实体Optional
Optional<Person> optional = Person.findByIdOptional(personId);
Person person = optional.orElseThrow(() -> new NotFoundException());
查询列表
查询所有
List<Person> allPersons = Person.listAll();
long countAll = Person.count();
条件查询
List<Person> livingPersons = Person.list("status", Status.Alive);
long countAlive = Person.count("status", Status.Alive);
分页查询
PanacheQuery<Person> livingPersons = Person.find("status", Status.Alive);
// 每页 10 条,返回第 5 页
List<Person> page5 = livingPersons.page(Page.of(5, 10)).list();
// 总条数
long count = livingPersons.count();
排序
// 方式1
List<Person> persons = Person.list("order by name,birth");
// 方式2
List<Person> persons = Person.list(Sort.by("name").and("birth"));
// 方式3
List<Person> persons = Person.list("status", Sort.by("name").and("birth"), Status.Alive);
更新
单条更新
Optional<Person> optional = Person.findByIdOptional(personId);
Person person = optional.orElseThrow(() -> new NotFoundException());
person.name = "更改name";
批量更新
Person.update("name = 'Moral' where status = ?1", Status.Alive);
删除
单条删除
Optional<Person> optional = Person.findByIdOptional(personId);
Person person = optional.orElseThrow(() -> new NotFoundException());
person.delete();
删除全部
Person.deleteAll();
按条件删除
Person.delete("status", Status.Alive);
HQL的使用
native 语句
Order.find("select distinct o from Order o left join fetch o.lineItems");
Order.update("update from Person set name = 'Moral' where status = ?", Status.Alive);
查询语句
Person.find("name = ?1 and status = ?2", "stef", Status.Alive);
使用Map作为参数
Map<String, Object> params = new HashMap<>();
params.put("name", "stef");
params.put("status", Status.Alive);
Person.find("name = :name and status = :status", params);
使用Parameters定义参数
// 使用map
Person.find("name = :name and status = :status",
Parameters.with("name", "stef").and("status", Status.Alive).map());
// 不用map
Person.find("name = :name and status = :status",
Parameters.with("name", "stef").and("status", Status.Alive));
使用数据库锁
// 方式1
Person p = Person.findById(id, LockModeType.PESSIMISTIC_WRITE);
// 方式2
Person p = Person.find("name", name).withLock(LockModeType.PESSIMISTIC_WRITE).findOne();
另外的使用方式之Repository
@Entity
public class Person {
@Id @GeneratedValue private Long id;
private String name;
private LocalDate birth;
private Status status;
// getter and setter ...
}
@ApplicationScoped
public class PersonRepository implements PanacheRepository<Person> {
}
这种方式与 Spring Data JPA 比较类似了,就不做介绍了。
@GET
@Operation(summary = "查询记录列表")
public PageResponse<SysUserModel> list(
@QueryParam("key") String key,
@QueryParam("index") int index,
@QueryParam("size") int size
) {
StringBuilder sql = new StringBuilder("1 = 1 ");
Parameters parameters = new Parameters();
if (Objects.nonNull(key)) {
sql.append("and userName like :userName");
parameters.and("userName", "%" + key + "%");
}
PanacheQuery<SysUserModel> query = SysUserModel.find(sql.toString(), parameters);
query.page(Page.of(index, size == 0 ? 10 : size));
List<SysUserModel> list = query.list();
list.forEach(sysUserModel -> sysUserModel.password=null);
long count = query.count();
return PageResponse.page(count, list);
}