【Daily Fresh Mushroom】Quarkus использует Panache для упрощения операций с базой данных🔥

Микросервисы
【Daily Fresh Mushroom】Quarkus использует Panache для упрощения операций с базой данных🔥

использовать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.

Идентификатор по умолчанию

@Entity
public class Person extends PanacheEntity {
    public String name;
    public LocalDate birth;
    public Status status;
}

пользовательский идентификатор

@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<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

родной оператор

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<String, Object> params = new HashMap<>();
params.put("name", "stef");
params.put("status", Status.Alive);
Person.find("name = :name and status = :status", params);

Используйте параметры для определения параметров

// 使用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();

Другой способ использования репозитория

@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);
}