The English version of quarkus.io is the official project site. Translated sites are community supported on a best-effort basis.
Edit this Page

Usando Hibernate ORM e Jakarta Persistence

O Hibernate ORM é a implementação padrão de fato da Jakarta Persistence (anteriormente conhecida como JPA) e oferece toda a abrangência de um Mapeador Objeto-Relacional. Ele funciona perfeitamente no Quarkus.

Solução

Recomendamos que siga as instruções nas seções seguintes e crie a aplicação passo a passo. No entanto, você pode ir diretamente para o exemplo completo.

Clone o repositório Git: git clone https://github.com/quarkusio/quarkus-quickstarts.git, ou baixe um arquivo.

A solução está localizada no hibernate-orm-quickstart diretório.

Configurando e definido o Hibernate ORM

Ao usar o Hibernate ORM no Quarkus, você não precisa ter um recurso persistence.xml para configurá-lo.

Usar esse arquivo de configuração clássico é uma opção, mas desnecessária a menos que você tenha necessidades avançadas específicas. Então veremos primeiro como o Hibernate ORM pode ser configurado sem um recurso persistence.xml.

No Quarkus, você só precisa:

  • adicionar suas configurações no application.properties

  • anotar suas entidades com @Entity e qualquer outras anotações de mapeamento como de costume

Outras necessidades de configuração foram automatizadas: O Quarkus fará algumas escolhas opinativas e suposições bem fundamentadas.

Adicione as seguintes dependências ao seu projeto:

  • a extensão Hibernate ORM: io.quarkus:quarkus-hibernate-orm

  • A extensão do seu driver JDBC, as seguintes opções estão disponíveis:

Por exemplo:

pom.xml
<!-- Hibernate ORM specific dependencies -->
<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>
build.gradle
// Hibernate ORM specific dependencies
implementation("io.quarkus:quarkus-hibernate-orm")

// JDBC driver dependencies
implementation("io.quarkus:quarkus-jdbc-postgresql")

Anote seus objetos persistentes com @Entity, em seguida, adicione as propriedades de configuração relevantes em application.properties .

Exemplo application.properties
quarkus.datasource.db-kind = postgresql (1)

quarkus.hibernate-orm.schema-management.strategy=drop-and-create (2)

%prod.quarkus.datasource.username = hibernate
%prod.quarkus.datasource.password = hibernate
%prod.quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/hibernate_db
1 Configure a fonte de dados.
2 Remove e crie o banco de dados na inicialização (use update para atualizar apenas o schema).

Observe que essas propriedades de configuração não são as mesmas do arquivo de configuração típico do Hibernate ORM. Elas geralmente correspondem às propriedades de configuração do Hibernate ORM, mas podem ter nomes diferentes e não necessariamente possuem uma correspondência de 1:1 entre si.

Além disso, o Quarkus definirá automaticamente muitas definições de configuração do Hibernate ORM e, com frequência, usará padrões mais modernos.

For a list of the items that you can set in application.properties, see Configuration Reference for Hibernate ORM.

Uma EntityManagerFactory será criada com base na configuração do Quarkus datasource , desde que a extensão Hibernate ORM esteja listada entre as dependências do seu projeto.

O dialeto será selecionado e configurado automaticamente com base na sua fonte de dados. você pode querer configurá-lo para corresponder mais precisamente ao seu banco de dados.

Você pode então injetar seu EntityManager sem problemas:

Exemplo de bean da aplicação usando o Hibernate
@ApplicationScoped
public class SantaClausService {
    @Inject
    EntityManager em; (1)

    @Transactional (2)
    public void createGift(String giftDescription) {
        Gift gift = new Gift();
        gift.setName(giftDescription);
        em.persist(gift);
    }
}
1 Injete seu gerenciador de entidades e divirta-se
2 Marque o método do seu bean CDI como @Transactional e o EntityManager será inscrito e fará o flush no commit.
Exemplo de entidade
@Entity
public class Gift {
    private Long id;
    private String name;

    @Id
    @GeneratedValue
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

Para carregar instruções SQL quando o Hibernate ORM for iniciar, adicione um arquivo import.sql na raiz do seu diretório resources. Esse script pode conter quaisquer instruções SQL DML. Certifique-se de terminar cada instrução com um ponto e vírgula.

Isso é útil para ter um conjunto de dados pronto para seus testes ou demonstrações.

Certifique-se de envolver os métodos que modificam o banco de dados (por exemplo, entity.persist() ) em uma transação. Marcar um método do bean CDI como @Transactional fará isso por você e tornará esse método um limite de transação. Recomendamos fazer isso nos limites do ponto de entrada da sua aplicação, como seus controladores de endpoint REST.

Dialeto

Bancos de dados suportados

Para bancos de dados compatíveis, o dialeto do Hibernate ORM não precisa ser definido explicitamente: ele é selecionado automaticamente com base na fonte de dados.

Por padrão, o dialeto é configurado para a versão mínima suportada do banco de dados.

Para que o Hibernate ORM gere SQL mais eficiente, evite soluções alternativas e aproveite mais recursos do banco de dados, você pode definir a versão do banco de dados explicitamente:

application.properties com uma db-version explícita
quarkus.datasource.db-kind = postgresql
quarkus.datasource.db-version = 18.1 (1)

%prod.quarkus.datasource.username = hibernate
%prod.quarkus.datasource.password = hibernate
%prod.quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:5432/hibernate_db
1 Defina a versão do banco de dados. O dialeto do Hibernate ORM terá como alvo essa versão.

Como regra geral, a versão definida aqui deve ser a mais alta possível, mas deve ser menor ou igual à versão de qualquer banco de dados ao qual sua aplicação Irã se conectar.

Conforme descrito acima, a versão pode ser pré-configurada explicitamente por meio da propriedade de configuração quarkus.datasource.db-version ou definida implicitamente pelo processo de compilação do Quarkus para uma versão mínima suportada do banco de dados. O Quarkus tentará verificar essa versão pré-configurada em relação à versão real do banco de dados na inicialização, resultando em falha na inicialização quando a versão real for inferior.

Essa é uma proteção: para versões do banco de dados mais antigas do que as configuradas, o Hibernate ORM pode gerar SQL inválido, o que levaria a exceções de tempo de execução.

Se o banco de dados não puder ser acessado, será registrado um aviso, mas a inicialização continuará. Opcionalmente, você pode desativar a verificação de versão se souber que o banco de dados não poderá ser acessado na inicialização usando quarkus.hibernate-orm.database.version-check.enabled=false.

Outros bancos de dados

Se o seu banco de dados não tiver uma extensão Quarkus correspondente ou se os padrões não corresponderem às suas necessidades por algum motivo, será necessário definir explicitamente o dialeto Hibernate ORM :

application.properties com um dialect explícito
quarkus.datasource.db-kind = postgresql

quarkus.hibernate-orm.dialect=Cockroach (1)

%prod.quarkus.datasource.username = hibernate
%prod.quarkus.datasource.password = hibernate
%prod.quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:26257/hibernate_db
1 Defina o dialeto do Hibernate ORM.

Para dialetos integrados, o valor esperado é um dos nomes No lista oficial de dialetos, sem o sufixo Dialect, por exemplo, Cockroach para CockroachDialect.

Para dialetos de terceiros, o valor esperado é o nome completo da classe, por exemplo com.acme.hibernate.AcmeDbDialect .

Nesse caso, lembre-se de que o driver JDBC ou o dialeto Hibernate ORM pode não funcionar corretamente nos executáveis nativos do GraalVM.

Assim como nos banco de dados compatíveis, você pode configurar a versão do banco de dados explicitamente para aproveitar ao máximo o Hibernate ORM:

application.properties com um dialect explícito e o db-version
quarkus.datasource.db-kind = postgresql
quarkus.datasource.db-version = 25.4 (1)

quarkus.hibernate-orm.dialect=Cockroach (2)

%prod.quarkus.datasource.username = hibernate
%prod.quarkus.datasource.password = hibernate
%prod.quarkus.datasource.jdbc.url = jdbc:postgresql://localhost:26257/hibernate_db
1 Defina a versão do banco de dados. O dialeto do Hibernate ORM terá como alvo essa versão. Como estamos direcionando o CockroachDB aqui, estamos passando a versão do CockroachDB, não a versão do PostgreSQL.
2 Defina o dialeto do Hibernate ORM.

Banco de dados variável

Ao ativar o banco de dados multi-tenancy, o Hibernate ORM usará várias fontes de dados em tempo de execução para a mesma unidade de persistência e, por padrão, o Quarkus não pode dizer qual fonte de dados será usada, portanto, não poderá detectar um dialeto a ser usado no Hibernate ORM.

Por esse motivo, ao ativar o banco de dados multi-tenancy, é recomendável apontar explicitamente a configuração do Hibernate ORM para um recurso de dados entre os que serão usados em tempo de execução, por exemplo, com quarkus.hibernate-orm.datasource=base ( base é o nome de um recurso de dados).

Ao fazer isso, o Quarkus inferirá a versão do banco de dados e (se possível) o dialeto a partir dessa fonte de dados. Para bancos de dados não suportados, ainda pode ser necessário definir explicitamente o dialeto do Hibernate ORM, conforme explicado em esta seção.

Propriedades de configuração do Hibernate ORM

Há várias propriedades opcionais úteis para refinar seu EntityManagerFactory ou orientar suposições de Quarkus.

Não há propriedades obrigatórias, desde que uma fonte de dados padrão esteja configurada.

Quando nenhuma propriedade é definida, o Quarkus normalmente pode inferir tudo o que é necessário para configurar o Hibernate ORM e fará com que ele use a fonte de dados padrão.

The configuration properties listed in Configuration Reference for Hibernate ORM allow you to override such defaults, and customize and tune various aspects.

Não misture as propriedades persistence.xml e quarkus.hibernate-orm.* em application.properties. O Quarkus lançará uma exceção. Decida qual abordagem você deseja utilizar.

Se o classpath contiver um persistence.xml que o você deseja ignorar, defina a seguinte propriedade de configuração:

quarkus.hibernate-orm.persistence-xml.ignore=true

Múltiplas unidades de persistência

Configuração de várias unidades de persistência

É possível definir várias unidades de persistência usando as propriedades de configuração do Quarkus.

As propriedades na raiz do namespace quarkus.hibernate-orm. definem a unidade de persistência padrão. Por exemplo, o snippet a seguir define uma fonte de dados padrão e uma unidade de persistência padrão:

quarkus.datasource.db-kind=h2
quarkus.datasource.jdbc.url=jdbc:h2:mem:default;DB_CLOSE_DELAY=-1

quarkus.hibernate-orm.schema-management.strategy=drop-and-create

Usando uma abordagem baseada em mapa, é possível definir unidades de persistência nomeadas:

quarkus.datasource."users".db-kind=h2 (1)
quarkus.datasource."users".jdbc.url=jdbc:h2:mem:users;DB_CLOSE_DELAY=-1

quarkus.datasource."inventory".db-kind=h2 (2)
quarkus.datasource."inventory".jdbc.url=jdbc:h2:mem:inventory;DB_CLOSE_DELAY=-1

quarkus.hibernate-orm."users".schema-management.strategy=drop-and-create (3)
quarkus.hibernate-orm."users".datasource=users (4)
quarkus.hibernate-orm."users".packages=org.acme.model.user (5)

quarkus.hibernate-orm."inventory".schema-management.strategy=drop-and-create (6)
quarkus.hibernate-orm."inventory".datasource=inventory
quarkus.hibernate-orm."inventory".packages=org.acme.model.inventory
1 Defina uma fonte de dados chamada users.
2 Defina uma fonte de dados chamada inventory.
3 Defina uma unidade de persistência chamada users.
4 Definir a fonte de dados usada pela unidade de persistência.
5 Essa propriedade de configuração é importante, mas a discutiremos um pouco mais adiante.
6 Defina uma unidade de persistência chamada inventory apontando para a fonte de dados inventory .

Você pode misturar a fonte de dados padrão e as fontes de dados nomeadas ou ter apenas uma ou outra.

A unidade de persistência padrão aponta para a fonte de dados padrão por padrão. Para unidades de persistência nomeadas, a propriedade datasource é obrigatória. Você pode apontar sua unidade de persistência para a fonte de dados padrão, definindo-a como <default> (que é o nome interno da fonte de dados padrão).

É perfeitamente válido ter várias unidades de persistência apontando para a mesma fonte de dados.

Anexar classes de modelo a unidades de persistência

Há duas maneiras de anexar classes de modelo a unidades de persistência, e elas não devem ser misturadas:

  • Por meio da propriedade de configuração packages;

  • Por meio da anotação em nível de pacote @io.quarkus.hibernate.orm.PersistenceUnit.

Se ambos forem misturados, as anotações serão ignoradas e somente as propriedades de configuração do packages serão levadas em conta.

Usar a propriedade de configuração packages é simples:

quarkus.hibernate-orm.schema-management.strategy=drop-and-create
quarkus.hibernate-orm.packages=org.acme.model.defaultpu

quarkus.hibernate-orm."users".schema-management.strategy=drop-and-create
quarkus.hibernate-orm."users".datasource=users
quarkus.hibernate-orm."users".packages=org.acme.model.user

Esse snippet de configuração criará duas unidades de persistência:

  • O padrão que conterá todas as classes de modelo no pacote org.acme.model.defaultpu, incluindo os subpacotes.

  • Uma unidade de persistência nomeada users que conterá todas as classes de modelo do pacote org.acme.model.user, incluindo os subpacotes.

Você pode anexar vários pacotes a uma unidade de persistência:

quarkus.hibernate-orm."users".packages=org.acme.model.shared,org.acme.model.user

Todas as classes de modelo dos pacotes org.acme.model.shared e org.acme.model.user serão vinculadas à unidade de persistência users .

Também é suportado vincular uma determinada classe de modelo a várias unidades de persistência.

As classes de modelo precisam ser adicionadas de forma consistente a uma determinada unidade de persistência. Isso significa que todas as classes de modelo dependentes de uma determinada entidade (superclasses mapeadas, embeddables…​) precisam estar vinculadas à unidade de persistência. Como estamos lidando com a unidade de persistência no nível do pacote, isso deve ser bastante simples.

Entidades Panache podem ser vinculadas a apenas uma unidade de persistência.

Para entidades vinculadas a várias unidades de persistência, não é possível utilizar o Panache. É possível, no entanto, combinar as duas abordagens e mesclar entidades Panache e entidades tradicionais quando múltiplas unidades de persistência forem necessárias.

Se você tiver um caso de uso para isso e ideias inteligentes sobre como implementá-lo sem poluir a abordagem simplificada do Panache, entre em contato pelo lista de discussão quarkus-dev.

A segunda abordagem para vincular classes de modelo a uma unidade de persistência é utilizar anotações @io.quarkus.hibernate.orm.PersistenceUnit no nível de pacote. Novamente, as duas abordagens não podem ser combinadas.

Para obter uma configuração semelhante à acima com a propriedade de configuração packages, crie um arquivo package-info.java com o seguinte conteúdo:

@PersistenceUnit("users") (1)
package org.acme.model.user;

import io.quarkus.hibernate.orm.PersistenceUnit;
1 Cuidado, use a anotação @io.quarkus.hibernate.orm.PersistenceUnit, não a do Jakarta Persistence.

Suportamos apenas a definição de @PersistenceUnit para classes de modelo no nível do pacote, o uso da anotação @PersistenceUnit no nível da classe não é compatível nesse caso.

Observe que, de forma semelhante ao que fazemos com a propriedade de configuração, levamos em consideração o pacote anotado e também todos os seus subpacotes.

Integração com CDI

Injecting entry points

Se você já está familiarizado com o uso do Hibernate ORM no Quarkus, provavelmente já injetou o EntityManager via CDI:

@Inject
EntityManager entityManager;

Isso injetará o EntityManager da unidade de persistência padrão.

Injetar o EntityManager de uma unidade de persistência nomeada (users em nosso exemplo) é tão simples quanto:

@Inject
@PersistenceUnit("users") (1)
EntityManager entityManager;
1 Aqui, novamente, usamos a mesma anotação @io.quarkus.hibernate.orm.PersistenceUnit.

The injected EntityManager or Session instance is a proxy that requires an active transaction for interaction.

By default it is also possible to use it for read-only operations without a transaction when in a request scope, but this can be disabled by setting quarkus.hibernate-orm.request-scoped.enabled to false.

Você pode injetar o EntityManagerFactory de uma unidade de persistência nomeada utilizando o mesmo mecanismo:

@Inject
@PersistenceUnit("users")
EntityManagerFactory entityManagerFactory;

In addition to EntityManager and EntityManagerFactory, Quarkus also supports injecting the following JPA/Hibernate components:

@Inject
CriteriaBuilder criteriaBuilder;

@Inject
HibernateCriteriaBuilder hibernateCriteriaBuilder;

@Inject
Metamodel metamodel;

@Inject
jakarta.persistence.Cache cache;

@Inject
org.hibernate.Cache cache;

@Inject
jakarta.persistence.PersistenceUnitUtil persistenceUnitUtil;

@Inject
jakarta.persistence.SchemaManager schemaManager;

@Inject
org.hibernate.relational.SchemaManager schemaManager;

These components can also be injected with a specific persistence unit qualifier:

@Inject
@PersistenceUnit("users")
CriteriaBuilder criteriaBuilder;

Plugging in converters and entity listeners

The Quarkus extension for Hibernate ORM supports injecting attribute converters and entity listeners into Hibernate ORM.

Just use them as you would in vanilla Hibernate ORM (see documentation linked above), and rely on CDI features (@Inject, @PostConstruct, @PreDestroy, …​) in the converter/listener implementation as needed.

When no CDI scope is specified, the converter/listener will behave as if it was @Dependent and will be instantiated once per persistence unit it’s used in.

You can force a CDI scope by annotating the converter/listener class with for example @ApplicationScoped.

In very exotic scenarios, if you need to prevent usage of CDI in a converter/listener even though it uses CDI annotations (@Inject, …​), annotate it with @Vetoed. The class will then be instantiated by Hibernate ORM through its default constructor.

Plugging in other custom components

The Quarkus extension for Hibernate ORM will automatically inject components annotated with @PersistenceUnitExtension into Hibernate Search.

The annotation can optionally target a specific persistence unit with @PersistenceUnitExtension(name = "nameOfYourPU").

This feature is available for the following component types:

org.hibernate.Interceptor

See Interceptadores.

org.hibernate.resource.jdbc.spi.StatementInspector

See Inspetores de declaração.

org.hibernate.type.format.FormatMapper

See Personalização da serialização/deserialização JSON/XML.

io.quarkus.hibernate.orm.runtime.tenant.TenantResolver

See Multitenancy.

io.quarkus.hibernate.orm.runtime.tenant.TenantConnectionResolver

See Resolução programática de conexões de tenants.

org.hibernate.boot.model.FunctionContributor

See Custom functions, types and mappings.

org.hibernate.boot.model.TypeContributor

See Custom functions, types and mappings.

Ativar/desativar unidades de persistência

When a persistence unit is configured at build time, and it is assigned entity types or an active datasource, the persistence unit is active by default. Quarkus starts the corresponding Hibernate ORM SessionFactory when the application starts.

To deactivate a persistence unit at runtime, set quarkus.hibernate-orm[.optional name].active to false.

If a persistence unit is not active:

  • The SessionFactory does not start during application startup.

  • Static CDI injection points involving the persistence unit, such as @Inject SessionFactory sf or @Inject Session session, cause application startup to fail.

  • Dynamic retrieval of the persistence unit, such as through CDI.getBeanContainer(), Arc.instance(), or an injected Instance<Session>, causes an exception to be thrown.

  • Other Quarkus extensions that consume the persistence unit may cause application startup to fail.

    In this case, you must also deactivate those other extensions.

Isso é particularmente útil quando você deseja que uma aplicação seja capaz de utilizar um dos datasources de um conjunto predeterminado em tempo de execução.

Por exemplo, com a seguinte configuração:

quarkus.hibernate-orm."pg".packages=org.acme.model.shared
quarkus.hibernate-orm."pg".datasource=pg
quarkus.hibernate-orm."pg".schema-management.strategy=drop-and-create
quarkus.hibernate-orm."pg".active=false
quarkus.datasource."pg".db-kind=h2
quarkus.datasource."pg".active=false
%prod.quarkus.datasource."pg".jdbc.url=jdbc:postgresql:///your_database

quarkus.hibernate-orm."oracle".packages=org.acme.model.shared
quarkus.hibernate-orm."oracle".datasource=oracle
quarkus.hibernate-orm."oracle".schema-management.strategy=drop-and-create
quarkus.hibernate-orm."oracle".active=false
quarkus.datasource."oracle".db-kind=oracle
quarkus.datasource."oracle".active=false
%prod.quarkus.datasource."oracle".jdbc.url=jdbc:oracle:///your_database

A configuração de quarkus.hibernate-orm."pg".active=true e quarkus.datasource."pg".active=true em tempo de execução disponibilizará apenas a unidade de persistência e a fonte de dados do PostgreSQL, e a configuração de quarkus.hibernate-orm."oracle".active=true e quarkus.datasource."oracle".active=true em tempo de execução disponibilizará apenas a unidade de persistência e a fonte de dados do Oracle.

Os perfis de configuração personalizados podem ajudar a simplificar essa configuração. Ao anexar a seguinte configuração específica de perfil à configuração acima, você pode selecionar uma unidade de persistência/fonte de dados em tempo de execução simplesmente definindo quarkus.profile: quarkus.profile=prod,pg ou quarkus.profile=prod,oracle.

%pg.quarkus.hibernate-orm."pg".active=true
%pg.quarkus.datasource."pg".active=true
# Add any pg-related runtime configuration here, prefixed with "%pg."

%oracle.quarkus.hibernate-orm."oracle".active=true
%oracle.quarkus.datasource."oracle".active=true
# Add any oracle-related runtime configuration here, prefixed with "%oracle."

With this setup, ensure that only the active persistence unit is accessed. To achieve this, inject an InjectableInstance<SessionFactory> or InjectableInstance<Session> with an @Any qualifier and call getActive().

import io.quarkus.arc.InjectableInstance;
@ApplicationScoped
public class MyConsumer {
    @Inject
    @Any
    InjectableInstance<Session> session;

    public void doSomething() {
        Session sessionForActivePersistenceUnit = session.getActive();
        // ...
    }
}

Alternatively, you can define a CDI bean producer for the beans of the default persistence unit. This bean producer redirects to the currently active named persistence unit. This allows beans to be injected directly, as shown below:

public class MyProducer {
    @Inject
    @PersistenceUnit("pg")
    InjectableInstance<Session> pgSessionBean; (1)

    @Inject
    @PersistenceUnit("oracle")
    InjectableInstance<Session> oracleSessionBean;

    @Produces (2)
    @ApplicationScoped
    public Session session() {
        if (pgSessionBean.getHandle().getBean().isActive()) { (3)
            return pgSessionBean.get();
        } else if (oracleSessionBean.getHandle().getBean().isActive()) { (3)
            return oracleSessionBean.get();
        } else {
            throw new RuntimeException("No active persistence unit!");
        }
    }
}

@ApplicationScoped
public class MyConsumer {
    @Inject
    Session session; (4)

    public void doSomething() {
        // .. just use the injected session ...
    }
}
1 Do not inject a Session directly. Injecting inactive beans causes a startup failure. Instead, inject InjectableInstance<Session>.
2 Declare a CDI producer method to define the default session. It selects either PostgreSQL or Oracle, depending on which persistence unit is active.
3 Check if a bean is active before retrieving it.
4 Injects the only active persistence unit.

Configurando o Hibernate ORM com um persistence.xml

Para definir e configurar o Hibernate ORM, recomenda-se using application.properties, mas você também pode usar um arquivo META-INF/persistence.xml. Isso é útil principalmente para migrar o código existente para o Quarkus.

O uso de um arquivo persistence.xml implica algumas restrições:

  • As unidades de persistência definidas em persistence.xml sempre usam a fonte de dados padrão .

  • As unidades de persistência definidas em persistence.xml devem ser configuradas explicitamente: O Quarkus manterá a injeção de configuração relacionada ao ambiente em um nível mínimo.

    Em particular, o Quarkus não configurará automaticamente o dialeto ou a versão do banco de dados com base na fonte de dados, portanto, se a configuração padrão do Hibernate ORM não atender às suas necessidades, você precisará incluir em persistence.xml configurações como hibernate.dialect/jakarta.persistence.database-product-name e possivelmente jakarta.persistence.database-product-version.

  • O uso do persistence.xml é incompatível com o uso das propriedades do quarkus.hibernate-orm.* no application.properties: se você misturar os dois, o Quarkus abrirá uma exceção.

  • A experiência do desenvolvedor pode ser afetada negativamente ao usar o site persistence.xml em comparação com using application.properties, devido a recursos indisponíveis, orientação limitada na documentação do Quarkus e mensagens de erro que fornecem dicas de resolução que não podem ser aplicadas (por exemplo, usando as propriedades do site quarkus.hibernate-orm.*).

Se o classpath contiver um persistence.xml que o você deseja ignorar, defina a seguinte propriedade de configuração:

quarkus.hibernate-orm.persistence-xml.ignore=true

As dependências pom.xml, bem como o código Java, seriam idênticos ao exemplo anterior. A única diferença é que você especificaria a configuração do Hibernate ORM em META-INF/persistence.xml:

Exemplo de recurso persistence.xml
<persistence xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence
             http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"
             version="2.1">

    <persistence-unit name="CustomerPU" transaction-type="JTA">

        <description>My customer entities</description>

        <properties>
            <!-- Connection specific -->
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>

            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>

            <!--
                Optimistically create the tables;
                will cause background errors being logged if they already exist,
                but is practical to retain existing data across runs (or create as needed) -->
            <property name="jakarta.persistence.schema-generation.database.action" value="drop-and-create"/>

            <property name="jakarta.persistence.validation.mode" value="NONE"/>
        </properties>

    </persistence-unit>
</persistence>

Ao usar a configuração persistence.xml, você está configurando o Hibernate ORM diretamente, portanto, nesse caso, a referência apropriada é a documentação em hibernate.org.

Lembre-se de que esses não são os mesmos nomes de propriedade usados no Quarkus application.properties, nem os mesmos padrões serão aplicados.

Mapeamento XML

O Hibernate ORM no Quarkus oferece suporte ao mapeamento XML. Você pode adicionar arquivos de mapeamento seguindo o orm.xml format (Jakarta Persistence) ou o hbm.xml format (specific to Hibernate ORM, deprecated):

Os arquivos de mapeamento XML são analisados no momento da compilação.

O arquivo META-INF/orm.xml sempre será incluído por padrão, se existir no classpath.

Se não for isso que você deseja, use quarkus.hibernate-orm.mapping-files = no-file ou <mapping-file>no-file</mapping-file>.

Definição de entidades em projetos externos ou jars

O Hibernate ORM no Quarkus depende de aprimoramentos de bytecode em tempo de compilação para suas entidades. Se você definir as entidades no mesmo projeto em que criou o aplicativo Quarkus, tudo funcionará bem.

Se as entidades vierem de projetos ou jars externos, você pode garantir que o seu jar seja tratado como uma biblioteca de aplicação Quarkus adicionando um arquivo META-INF/beans.xml vazio.

Isso permitirá que o Quarkus indexe e aprimore suas entidades como se elas estivessem dentro do projeto atual.

Hibernate ORM no modo de desenvolvimento

O modo de desenvolvimento do Quarkus é muito útil para aplicações que combinam frontend ou serviços com acesso a banco de dados.

Há algumas abordagens comuns para tirar o melhor proveito disso.

The first choice is to use quarkus.hibernate-orm.schema-management.strategy=drop-and-create in conjunction with import.sql.

Dessa forma, a cada alteração na sua aplicação e, em particular, nas suas entidades, o schema do banco de dados será recriado corretamente e seus dados de fixture (armazenados em import.sql) serão usados para repopulá-lo do zero. Isso é ideal para ter controle total sobre seu ambiente e funciona perfeitamente com o modo de live reload do Quarkus: qualquer alteração nas suas entidades ou no import.sql é imediatamente detectada e o schema é atualizado sem reiniciar a aplicação!

By default, in dev and test modes, Hibernate ORM, upon boot, will read and execute the SQL statements in the /import.sql file (if present). You can change the file name by changing the property quarkus.hibernate-orm.sql-load-script in application.properties. You can also provide a .zip file in the same way which should contain only the files containing the SQL statements to be executed.

The second approach is to use quarkus.hibernate-orm.schema-management.strategy=update. This approach is best when you do many entity changes but still need to work on a copy of the production data or if you want to reproduce a bug that is based on specific database entries. update is a best effort from Hibernate ORM and will fail in specific situations including altering your database structure which could lead to data loss. For example if you change structures which violate a foreign key constraint, Hibernate ORM might have to bail out. But for development, these limitations are acceptable.

The third approach is to use quarkus.hibernate-orm.schema-management.strategy=none. This approach is best when you are working on a copy of the production data but want to fully control the schema evolution. Or if you use a database schema migration tool like Flyway or Liquibase.

Com essa abordagem, ao fazer alterações em uma entidade, certifique-se de adaptar o schema do banco de dados adequadamente, você também pode usar validate para que o Hibernate verifique se o schema corresponde às suas expectativas.

Do not use quarkus.hibernate-orm.schema-management.strategy drop-and-create and update in your production environment.

Essas abordagens se tornam muito poderosas quando combinadas com os perfis de configuração do Quarkus. Você pode definir diferentes perfis de configuração para selecionar comportamentos distintos dependendo do seu ambiente. Isso é excelente porque permite definir diferentes combinações de propriedades do Hibernate ORM que correspondam ao estilo de desenvolvimento que você precisa no momento.

application.properties
%dev.quarkus.hibernate-orm.schema-management.strategy = drop-and-create
%dev.quarkus.hibernate-orm.sql-load-script = import-dev.sql

%dev-with-data.quarkus.hibernate-orm.schema-management.strategy = update
%dev-with-data.quarkus.hibernate-orm.sql-load-script = no-file

%prod.quarkus.hibernate-orm.schema-management.strategy = none
%prod.quarkus.hibernate-orm.sql-load-script = no-file

Você pode iniciar o modo de desenvolvimento usando um perfil personalizado:

CLI
quarkus dev -Dquarkus.profile=dev-with-data
Maven
./mvnw quarkus:dev -Dquarkus.profile=dev-with-data
Gradle
./gradlew --console=plain quarkusDev -Dquarkus.profile=dev-with-data

Hibernate ORM em modo de produção

O Quarkus vem com perfis padrão ( dev , test e prod ). E você pode adicionar seus próprios perfis personalizados para descrever vários ambientes ( staging , prod-us , etc).

A extensão Hibernate ORM Quarkus define algumas configurações padrão de forma diferente nos modos de desenvolvimento e teste do que em outros ambientes.

  • quarkus.hibernate-orm.sql-load-script é definido como no-file para todos os perfis, exceto os perfis dev e test.

Você pode substituí-lo explicitamente no seu application.properties (por exemplo, %prod.quarkus.hibernate-orm.sql-load-script = import.sql ), mas queríamos que você evitasse substituir o banco de dados por acidente no prod :)

Por falar nisso, certifique-se de não descartar o esquema do banco de dados na produção! Adicione o seguinte em seu arquivo de propriedades.

application.properties
%prod.quarkus.hibernate-orm.schema-management.strategy = none
%prod.quarkus.hibernate-orm.sql-load-script = no-file

Flyway integration

Transacionando automaticamente para o Flyway para gerenciar schemas

Se você tiver a extensão Flyway instalada ao executar no modo de desenvolvimento, o Quarkus oferece uma forma simples de inicializar sua configuração do Flyway utilizando o schema gerado automaticamente pelo Hibernate ORM. O objetivo é facilitar a transição da fase inicial de desenvolvimento, onde o Hibernate pode ser usado para configurar o schema rapidamente, para a fase de produção, onde o Flyway é utilizado para gerenciar as alterações do schema.

Para usar esse recurso, basta abrir a Dev UI quando a extensão quarkus-flyway estiver instalada e clicar no link Datasources no painel Flyway. Pressione o botão Create Initial Migration e ocorrerá o seguinte:

  • Um arquivo db/migration/V1.0.0__{appname}.sql será criado, contendo o SQL que o Hibernate está executando para gerar o esquema

  • quarkus.flyway.baseline-on-migrate será definido, informando ao Flyway para criar automaticamente suas tabelas de linha de base

  • quarkus.flyway.migrate-at-start será definido, informando ao Flyway para aplicar automaticamente as migrações na inicialização da aplicação

  • %dev.quarkus.flyway.clean-at-start e %test.quarkus.flyway.clean-at-start serão definidos para limpar o banco de dados após o recarregamento no modo dev/test

Esse botão é apenas uma conveniência para ajudá-lo a começar rapidamente com o Flyway, cabe a você determinar como deseja gerenciar os schemas do seu banco de dados em produção. Em particular, a configuração migrate-at-start pode não ser adequada para todos os ambientes.

Incremental migrations from entity changes

After the first migration is created, Quarkus can derive a draft migration from your updated entity model, so you don’t need to hand‑write a baseline for each change. To create a new migration, click the Generate Migration File button in the Dev UI Flyway pane.

Always review the suggested script. While Quarkus infers schema changes from your entities, domain‑specific data movements, concurrency considerations, and advanced index strategies still require human judgment.

Generated migration files follow the following pattern:

  • Major version is extracted from the last existing migration in your project.

  • Minor version is the current timestamp at generation time.

Offline startup

By default, Hibernate attempts to connect to the database at startup to fetch metadata. This is useful, for example, to validate the schema or create some temporary tables, making the startup process smoother and more user-friendly.

However, in certain environments, such as when running a Quarkus application in a container within a Kubernetes cluster, this connection might not be possible. For example, if the application runs in one pod and the database in another, the database may not be reachable at startup time. To address this, Quarkus provides an offline startup mode, which allows Hibernate to skip connecting to the database during application startup.

When using offline startup, it’s important to ensure that the database schema has already been created correctly before the application starts.

You can rely on Flyway, Liquibase or custom setups to create/migrate your database schema, though obviously at a time where the database is accessible — Flyway’s migrate-at-start option in particular will just fail at application startup if the database is not reachable.

To enable offline startup, set the following configuration property:

application.properties
quarkus.hibernate-orm.database.start-offline=true

You can also fine-tune dialect behavior for specific databases using additional properties, such as:

application.properties
quarkus.hibernate-orm."offline".dialect.mariadb.bytes-per-character=1
quarkus.hibernate-orm."offline".dialect.mariadb.no-backslash-escapes=true
quarkus.hibernate-orm."offline".dialect.mariadb.storage-engine=InnoDB (1)
quarkus.hibernate-orm."inventory".dialect.mysql.storage-engine=MyISAM (2)
1 Set the storage engine for the MariaDB dialect of the offline persistence unit.
2 Different persistence units can use different storage engines.

Refer to the Configuration Reference for Hibernate ORM section for more details on the available properties.

Armazenamento em cache

Aplicações que leem as mesmas entidades com frequência podem ter seu desempenho melhorado quando o cache de segundo nível do Hibernate ORM está habilitado.

Armazenamento em cache de entidades

Para ativar o cache de segundo nível, marque as entidades que você deseja armazenar em cache com @jakarta.persistence.Cacheable:

@Entity
@Cacheable
public class Country {
    int dialInCode;
    // ...
}

Quando uma entidade é anotada com @Cacheable, todos os seus valores de campo são armazenados em cache, exceto para coleções e relações com outras entidades.

Isso significa que a entidade pode ser carregada sem consultar o banco de dados, mas é preciso ter cuidado, pois isso implica que a entidade carregada pode não refletir as alterações recentes no banco de dados.

Armazenamento em cache de coleções e relações

Coleções e relacionamentos precisam ser anotados individualmente para serem cacheados; nesse caso, deve-se utilizar a anotação específica do Hibernate @org.hibernate.annotations.Cache, que também requer a especificação da CacheConcurrencyStrategy:

package org.acme;

@Entity
@Cacheable
public class Country {
    // ...

    @OneToMany
    @Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
    List<City> cities;

    // ...
}

Cache de queries

As queries também podem se beneficiar do cache de segundo nível. Os resultados de queries em cache podem ser retornados imediatamente ao chamador, evitando a execução da query no banco de dados.

Tenha cuidado, pois isso implica que os resultados podem não refletir alterações recentes.

Para cachear uma query, marque-a como cacheável na instância de Query:

Query query = ...
query.setHint("org.hibernate.cacheable", Boolean.TRUE);

Se você tiver uma NamedQuery, pode habilitar o cache diretamente em sua definição, que geralmente estará em uma entidade:

@Entity
@NamedQuery(name = "Fruits.findAll",
      query = "SELECT f FROM Fruit f ORDER BY f.name",
      hints = @QueryHint(name = "org.hibernate.cacheable", value = "true") )
public class Fruit {
   ...

É só isso! A tecnologia de cache já está integrada e habilitada por padrão no Quarkus, portanto basta definir quais podem ser cacheados com segurança.

Ajuste das regiões de cache

Os caches armazenam os dados em regiões separadas para isolar diferentes porções de dados, essas regiões recebem um nome, o que é útil para configurar cada região de forma independente ou para monitorar suas estatísticas.

Por padrão, as entidades são cacheadas em regiões nomeadas de acordo com seu nome completamente qualificado, por exemplo, org.acme.Country.

As coleções são armazenadas em cache em regiões nomeadas com o nome totalmente qualificado de sua entidade proprietária e o nome do campo da coleção, separados pelo caractere #, por exemplo, org.acme.Country#cities .

Por padrão, todas as consultas em cache são mantidas em uma única região dedicada a elas, chamada default-query-results-region.

Todas as regiões são limitadas por tamanho e tempo por padrão. Os padrões são 10000 max entries e 100 seconds como tempo máximo de inatividade.

O tamanho de cada região pode ser personalizado por meio da propriedade quarkus.hibernate-orm.cache."<region_name>".memory.object-count (Substitua <region_name> pelo nome real da região).

Para definir o tempo ocioso máximo, forneça a duração (consulte a nota sobre o formato da duração abaixo) por meio da propriedade quarkus.hibernate-orm.cache."<region_name>".expiration.max-idle (Substitua <region_name> pelo nome real da região).

As aspas duplas são obrigatórias se o nome da região contiver um ponto. Por exemplo:

quarkus.hibernate-orm.cache."org.acme.MyEntity".memory.object-count=1000

To write duration values, use the standard java.time.Duration format. See the Duration#parse() javadoc for more information.

Você também pode usar um formato simplificado, começando com um número:

  • Se o valor for apenas um número, ele representará o tempo em segundos.

  • Se o valor for um número seguido de 'ms', ele representa o tempo em milissegundos.

Em outros casos, o formato simplificado é traduzido para o formato 'java.time.Duration' para análise:

  • Se o valor for um número seguido de 'h', 'm' ou 's', ele é prefixado com 'PT'.

  • Se o valor for um número seguido de 'd', ele é prefixado com 'P'.

Limitações do cache

Atualmente, a tecnologia de cache fornecida pelo Quarkus é bastante rudimentar e limitada.

A equipe achou que era melhor ter algum recurso de cache para começar do que não ter nada, você pode esperar que uma solução de cache melhor seja integrada em versões futuras, e qualquer ajuda e feedback nessa área é muito bem-vinda.

Esses caches são mantidos localmente, portanto não são invalidados nem atualizados quando alterações são feitas no armazenamento persistente por outras aplicações.

Além disso, ao executar múltiplas instâncias da mesma aplicação (em um cluster, por exemplo no Kubernetes/OpenShift), os caches em instâncias separadas da aplicação não são sincronizados.

Por essas razões, habilitar o cache só é adequado quando certas premissas podem ser assumidas: recomendamos fortemente que apenas entidades, coleções e queries que nunca mudam sejam cacheadas. Ou, no máximo, que quando uma entidade for de fato modificada e permitida de ser lida de forma desatualizada (stale), isso não impacte as expectativas da aplicação.

Seguir esse conselho garante que as aplicações obtenham o melhor desempenho do cache de segundo nível e, ao mesmo tempo, evitem comportamentos inesperados.

Além dos dados imutáveis, em determinados contextos, pode ser aceitável habilitar o cache também em dados mutáveis, isso pode ser uma troca necessária em entidades selecionadas que são lidas com frequência e para as quais algum grau de obsoletismo é aceitável, esse "grau aceitável de obsoletismo" pode ser ajustado definindo-se as propriedades de despejo. No entanto, isso não é recomendado e deve ser feito com extremo cuidado, pois pode produzir efeitos inesperados e imprevistos nos dados.

Em vez de habilitar o cache em dados mutáveis, a solução ideal seria utilizar um cache clusterizado; no entanto, no momento o Quarkus não oferece nenhuma implementação desse tipo: sinta-se à vontade para entrar em contato e informar essa necessidade para que a equipe possa levá-la em consideração.

Por fim, o cache de segundo nível pode ser desativado globalmente ao definir hibernate.cache.use_second_level_cache como false, essa é uma configuração que precisa ser especificada no arquivo de configuração persistence.xml.

Quando o cache de segundo nível está desativado, todas as anotações de cache são ignoradas e todas as consultas são executadas ignorando os caches, isso geralmente é útil apenas para diagnosticar problemas.

Hibernate Envers

A extensão Envers do Hibernate ORM tem como objetivo fornecer uma solução fácil de auditoria/controle de versão para classes de entidades.

No Quarkus, o Envers tem uma extensão dedicada do Quarkus io.quarkus:quarkus-hibernate-envers, você só precisa adicioná-la ao seu projeto para começar a usá-la.

Dependência adicional para ativar o Hibernate Envers
    <!-- Add the Hibernate Envers extension -->
    <dependency>
        <groupId>io.quarkus</groupId>
        <artifactId>quarkus-hibernate-envers</artifactId>
    </dependency>

Nesse momento, a extensão não expõe propriedades de configuração adicionais.

Para obter mais informações sobre o Hibernate Envers, consulte hibernate.org/orm/envers/ .

Hibernate Spatial

The Spatial extension to Hibernate ORM provides a standardized, cross-database interface to geographic data storage and query functions.

To use Hibernate Spatial, you simply need to add the dependency to your project:

Additional dependency to enable Hibernate Spatial
    <!-- Add the Hibernate Spatial module -->
    <dependency>
        <groupId>org.hibernate.orm</groupId>
        <artifactId>hibernate-spatial</artifactId>
    </dependency>

The dependency version is managed by Quarkus, so you don’t need to specify it explicitly.

You can find all information about Spatial in the Hibernate user guide: Hibernate ORM Spatial.

Hibernate Vector

The Vector extension to Hibernate ORM provides support for mathematical vector types, functions, and vector similarity search. It enables storage and querying of vector embeddings (arrays of bytes, floats, or doubles) in databases that support native vector types or arrays. This is commonly used in AI/ML applications to persist and query embeddings generated by machine learning models.

To use Hibernate Vector, add the dependency to your project:

Additional dependency to enable Hibernate Vector
    <!-- Add the Hibernate Vector module -->
    <dependency>
        <groupId>org.hibernate.orm</groupId>
        <artifactId>hibernate-vector</artifactId>
    </dependency>

The dependency version is managed by Quarkus, so you don’t need to specify it explicitly.

To map a vector column, annotate a persistent attribute with one of the various vector @JdbcTypeCode`s (for example, `SqlTypes.VECTOR for a float[] embedding) and specify the vector length with @Array(length = …​).

Example entity with a vector
@Entity
public class Document {

    @Id
    private Long id;

    @Column(name = "the_vector")
    @JdbcTypeCode(SqlTypes.VECTOR)
    @Array(length = 1536)
    private float[] theVector;
}

You can find all information about Vector in the Hibernate user guide: Hibernate ORM Vector.

Métricas

Micrometer is capable of exposing metrics that Hibernate ORM collects at runtime. To enable exposure of Hibernate metrics on the /q/metrics endpoint, make sure your project depends on a metrics extension and set the configuration property quarkus.hibernate-orm.metrics.enabled to true.

Limitações e outras informações importantes

O Quarkus não modifica as bibliotecas que utiliza, essa regra também se aplica ao Hibernate ORM: ao usar esta extensão, você terá basicamente a mesma experiência de usar a biblioteca original.

Porém, embora compartilhem o mesmo código, o Quarkus configura alguns componentes automaticamente e injeta implementações customizadas para alguns pontos de extensão, isso deve ser transparente e útil, mas se você for um especialista em Hibernate pode querer saber o que está sendo feito.

Enhancement automático em tempo de build

O Hibernate ORM pode utilizar entidades com enhancement em tempo de build, normalmente isso não é obrigatório, mas é útil e fará com que suas aplicações tenham melhor desempenho.

Normalmente, seria necessário adaptar seus scripts de build para incluir os plugins de Enhancement do Hibernate, no Quarkus isso não é necessário, pois a etapa de enhancement está integrada ao build e à análise da aplicação Quarkus.

Devido ao uso de aprimoramento, o uso do método clone() em entidades não é suportado no momento, pois ele também clonará alguns campos específicos de aprimoramento que são específicos da entidade.

Essa limitação pode ser removida no futuro.

Integração automática

Integração com o Transaction Manager

Você não precisa configurar isso, o Quarkus injeta automaticamente a referência ao Narayana Transaction Manager. A dependência é incluída automaticamente como uma dependência transitiva da extensão do Hibernate ORM. Toda a configuração é opcional, para mais detalhes, consulte Usando Transações no Quarkus.

Pool de conexões

Também não é necessário escolher um. O Quarkus inclui automaticamente o pool de conexões Agroal, configure seu datasource como nos exemplos acima e ele configurará o Hibernate ORM para usar o Agroal. Mais detalhes sobre esse pool de conexões podem ser encontrados em Quarkus - Datasources.

Cache de segundo nível

Conforme explicado anteriormente na seção de Cache, você não precisa escolher uma implementação. Uma implementação adequada baseada nas tecnologias do Infinispan e do Caffeine é incluída como uma dependência transitiva da extensão do Hibernate ORM e integrada automaticamente durante a compilação.

Limitações

Mapeamento XML com arquivos duplicados no classpath

Espera-se que os arquivos de mapeamento XML tenham um caminho exclusivo.

Na prática, só é possível ter arquivos de mapeamento XML duplicados no classpath em cenários muito específicos. Por exemplo, se dois JARs incluírem um arquivo META-INF/orm.xml (com exatamente o mesmo caminho, mas em JARs diferentes), o caminho do arquivo de mapeamento META-INF/orm.xml só poderá ser referenciado a partir de um persistence.xml no mesmo JAR que o arquivo META-INF/orm.xml .

JMX

Os beans de gerenciamento não estão funcionando nas imagens nativas do GraalVM, portanto, a capacidade do Hibernate de registrar estatísticas e operações de gerenciamento com o bean JMX é desativada ao compilar em uma imagem nativa. Essa limitação provavelmente é permanente, pois não é um objetivo das imagens nativas implementar o suporte ao JMX. Todas essas métricas podem ser acessadas de outras formas.

Integração da JACC

A capacidade do Hibernate ORM de se integrar ao JACC é desativada ao criar imagens nativas do GraalVM pois o JACC não está disponível - nem é útil - no modo nativo.

Vinculação da sessão ao contexto ThreadLocal

É impossível usar o auxiliar ThreadLocalSessionContext do Hibernate ORM, pois o suporte a ele não está implementado. Como o Quarkus oferece suporte a CDI pronto para uso, a injeção ou a pesquisa programática de CDI é uma abordagem melhor. Esse recurso também não se integrou bem aos componentes reativos e às técnicas mais modernas de propagação de contexto, o que nos faz acreditar que esse recurso legado não tem futuro. Você precisar muito associá-lo a um ThreadLocal, deve ser trivial implementá-lo em seu próprio código.

JNDI

A tecnologia JNDI é comumente usada em outros tempos de execução para integrar diferentes componentes. Um caso de uso comum são os servidores Java Enterprise para vincular os componentes TransactionManager e Datasource a um nome e, em seguida, ter o Hibernate ORM configurado para procurar esses componentes pelo nome. Mas no Quarkus, esse caso de uso não se aplica, pois os componentes são injetados diretamente, tornando o suporte a JNDI um legado desnecessário. Para evitar o uso inesperado do JNDI, o suporte total ao JNDI foi desativado na extensão do Hibernate ORM para o Quarkus. Isso é tanto uma precaução de segurança quanto uma otimização.

Outras diferenças notáveis

Formato de import.sql

Ao importar um import.sql para configurar o banco de dados, lembre-se de que o Quarkus reconfigura o Hibernate ORM de modo a exigir um ponto e vírgula ( ; ) para encerrar cada instrução. O padrão no Hibernate é ter uma instrução por linha, sem exigir um terminador diferente de nova linha: lembre-se de converter seus scripts para usar o caractere de terminação ; se estiver reutilizando scripts existentes. Isso é útil para permitir declarações de várias linhas e formatação amigável.

Simplificando o Hibernate ORM com o Panache

A extensão Hibernate ORM with Panache facilita o uso do Hibernate ORM fornecendo entidades (e repositórios) no estilo de Active Record e concentra-se em tornar as entidades triviais e divertidas de escrever no Quarkus.

Configure sua fonte de dados

A configuração do Datasource é extremamente simples, mas é abordada em outro guia, pois tecnicamente é implementada pela extensão do pool de conexões do Agroal para o Quarkus.

Acesse Quarkus - Datasources para obter todos os detalhes.

Multitenancy

"O termo multitenancy, em geral, é aplicado ao desenvolvimento de software para indicar uma arquitetura na qual uma única instância em execução de um aplicativo atende simultaneamente a vários clientes (locatários). Isso é muito comum em soluções de SaaS. O isolamento de informações (dados, personalizações etc.) pertencentes aos vários locatários é um desafio especial nesses sistemas. Isso inclui os dados de propriedade de cada locatário armazenados no banco de dados" (Guia do Usuário do Hibernate).

Atualmente, o Quarkus suporta a abordagem de banco de dados separado, a abordagem de esquema separado e a abordagem de discriminador.

Para ver o multitenancy em ação, você pode conferir o hibernate-orm-multi-tenancy-schema-quickstart ou o hibernate-orm-multi-tenancy-database-quickstart .

Escrevendo o aplicativo

Vamos começar implementando o endpoint /{tenant}. Como você pode ver no código-fonte abaixo, ele é apenas um recurso Jakarta REST comum:

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.persistence.EntityManager;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

@ApplicationScoped
@Path("/{tenant}")
public class FruitResource {

    @Inject
    EntityManager entityManager;

    @GET
    @Path("fruits")
    public Fruit[] getFruits() {
        return entityManager.createNamedQuery("Fruits.findAll", Fruit.class)
                .getResultList().toArray(new Fruit[0]);
    }

}

Para resolver o tenant a partir das requisições recebidas e mapeá-lo para uma configuração específica de tenant, você precisa criar uma implementação para a interface io.quarkus.hibernate.orm.runtime.tenant.TenantResolver

import jakarta.enterprise.context.ApplicationScoped;

import io.quarkus.hibernate.orm.runtime.tenant.TenantResolver;
import io.vertx.ext.web.RoutingContext;

@PersistenceUnitExtension (1)
@RequestScoped (2)
public class CustomTenantResolver implements TenantResolver {

    @Inject
    RoutingContext context;

    @Override
    public String getDefaultTenantId() {
        return "base";
    }

    @Override
    public String resolveTenantId() {
        String path = context.request().path();
        String[] parts = path.split("/");

        if (parts.length == 0) {
            // resolve to default tenant config
            return getDefaultTenantId();
        }

        return parts[1];
    }

}
1 Anote a implementação do TenantResolver com o qualificador @PersistenceUnitExtension para informar ao Quarkus que ele deve ser usado na unidade de persistência padrão.

Para unidades de persistência nomeadas, use @PersistenceUnitExtension("nameOfYourPU") .

2 O bean é feito @RequestScoped, pois a resolução do tenant depende da requisição recebida.

Na implementação acima, os tenants são resolvidos a partir do caminho da requisição, de forma que, caso nenhum tenant possa ser inferido, o identificador de tenant padrão é retornado.

Você também usar o OIDC multitenancy e os IDs de locatário do OIDC e do Hibernate ORM forem os mesmos, poderá obter o ID de locatário do OIDC em um atributo RoutingContext, como no exemplo abaixo:

import io.quarkus.hibernate.orm.runtime.tenant.TenantResolver;
import io.quarkus.oidc.runtime.OidcUtils;
import io.vertx.ext.web.RoutingContext;

@PersistenceUnitExtension
@RequestScoped
public class CustomTenantResolver implements TenantResolver {

    @Inject
    RoutingContext context; (1)
    ...
    @Override
    public String resolveTenantId() {
        // OIDC has saved the tenant id as the RoutingContext attribute:
        return context.get(OidcUtils.TENANT_ID_ATTRIBUTE);
    }
}
1 Se o TenantResolver do Hibernate também resolver tenants quando não há uma requisição HTTP ativa, por exemplo ao consultar o banco de dados a partir de um scheduler, o bean CDI RoutingContext não estará disponível. Nesse caso, injete o bean CDI io.quarkus.vertx.http.runtime.CurrentVertxRequest e obtenha o RoutingContext a partir dele.

Configurando a aplicação

Em geral, não é possível utilizar o recurso de geração de banco de dados do Hibernate ORM em conjunto com uma configuração de multitenancy. Portanto, você deve desabilitá-lo e garantir que as tabelas sejam criadas por schema. A configuração a seguir utilizará a extensão Flyway para atingir esse objetivo.

Abordagem SCHEMA

A mesma fonte de dados será usada para todos os locatários e um esquema deve ser criado para cada locatário dentro dessa fonte de dados.

Some databases like MariaDB/MySQL do not support database schemas by default. In these cases you can either: 1. Configure the JDBC driver to support schemas. Use quarkus.datasource.jdbc.additional-jdbc-properties."databaseTerm"=SCHEMA or quarkus.datasource."datasource-name".jdbc.additional-jdbc-properties."databaseTerm"=SCHEMA for MySQL Connector/J. Use quarkus.datasource.jdbc.additional-jdbc-properties."useCatalogTerm"=SCHEMA or quarkus.datasource."datasource-name".jdbc.additional-jdbc-properties."useCatalogTerm"=SCHEMA for MariaDB Connector/J.

and 2. Fall back to the database approach.

quarkus.hibernate-orm.schema-management.strategy=none (1)

quarkus.hibernate-orm.multitenant=SCHEMA (2)

quarkus.datasource.db-kind=postgresql (3)

quarkus.flyway.schemas=base,mycompany (4)
quarkus.flyway.locations=classpath:schema
quarkus.flyway.migrate-at-start=true

%prod.quarkus.datasource.username=quarkus_test
%prod.quarkus.datasource.password=quarkus_test
%prod.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/quarkus_test
1 Desative a geração de esquemas, pois ela não é compatível com o Hibernate ORM para multitenancy de esquemas. Em vez disso, usaremos o Flyway, veja mais abaixo.
2 Habilitar o multitenancy do esquema.

Usamos a fonte de dados padrão aqui, mas poderíamos usar uma fonte de dados nomeada, se quiséssemos, seguindo aqui instruções.

3 Configure a fonte de dados.
4 Configure o Flyway para a inicialização do banco de dados, pois a geração de esquemas pelo Hibernate ORM não é suportada nesse caso.

Aqui está um exemplo do Flyway SQL ( V1.0.0__create_fruits.sql ) a ser criado na pasta configurada src/main/resources/schema.

CREATE SEQUENCE base.fruit_seq INCREMENT BY 50; -- 50 is quarkus default
CREATE TABLE base.fruit
(
    id   INT,
    name VARCHAR(40)
);
INSERT INTO base.fruit(id, name) VALUES (1, 'Cherry');
INSERT INTO base.fruit(id, name) VALUES (2, 'Apple');
INSERT INTO base.fruit(id, name) VALUES (3, 'Banana');
ALTER SEQUENCE base.fruit_seq RESTART WITH 4;

CREATE SEQUENCE mycompany.fruit_seq INCREMENT BY 50; -- 50 is quarkus default
CREATE TABLE mycompany.fruit
(
  id   INT,
  name VARCHAR(40)
);
INSERT INTO mycompany.fruit(id, name) VALUES (1, 'Avocado');
INSERT INTO mycompany.fruit(id, name) VALUES (2, 'Apricots');
INSERT INTO mycompany.fruit(id, name) VALUES (3, 'Blackberries');
ALTER SEQUENCE mycompany.fruit_seq RESTART WITH 4;

Abordagem de banco de dados

Para cada tenant, você precisa criar uma fonte de dados nomeada com o mesmo identificador que é retornado pelo TenantResolver.

Com essa abordagem, todos os datasources utilizados pela mesma unidade de persistência são assumidos como apontando para um banco de dados do mesmo fornecedor (mesmo db-kind) e versão.

As incompatibilidades não serão detectadas e podem resultar em um comportamento imprevisível.

A lista de fontes de dados é definida no momento da compilação, portanto, com essa abordagem, a list de locatários é fixa no momento da compilação . Se a lista de locatários precisar ser alterada no tempo de execução, o senhor deverá resolver as conexões de tenant programaticamente.

quarkus.hibernate-orm.schema-management.strategy=none (1)

quarkus.hibernate-orm.multitenant=DATABASE (2)
quarkus.hibernate-orm.datasource=base (3)

# Default tenant 'base'
quarkus.datasource.base.db-kind=postgresql (4)
quarkus.flyway.base.locations=classpath:database/base (5)
quarkus.flyway.base.migrate-at-start=true
%prod.quarkus.datasource.base.username=base
%prod.quarkus.datasource.base.password=base
%prod.quarkus.datasource.base.jdbc.url=jdbc:postgresql://localhost:5432/base

# Tenant 'mycompany'
quarkus.datasource.mycompany.db-kind=postgresql (6)
quarkus.flyway.mycompany.locations=classpath:database/mycompany (7)
quarkus.flyway.mycompany.migrate-at-start=true
%prod.quarkus.datasource.mycompany.username=mycompany
%prod.quarkus.datasource.mycompany.password=mycompany
%prod.quarkus.datasource.mycompany.jdbc.url=jdbc:postgresql://localhost:5433/mycompany
1 Desative a geração de esquemas, pois ela não é compatível com o Hibernate ORM para multitenancy de banco de dados. Em vez disso, usaremos o Flyway, veja mais abaixo.
2 Habilite o multitenancy do banco de dados.
3 Selecione uma fonte de dados para a unidade de persistência.

Isso serve apenas para permitir que o Quarkus determine o dialeto ORM do Hibernate a ser usado, consulte essa seção para obter detalhes.

4 Configure a fonte de dados para um tenant, base .
5 Configure o Flyway para a inicialização do banco de dados para o locatário base, porque a geração de esquema pelo Hibernate ORM não é suportada nesse caso.
6 Configure o datasource para outro tenant.

Poderia haver mais tenants, mas aqui vamos nos limitar a dois.

7 Configure o Flyway para a inicialização do banco de dados para o locatário mycompany, porque a geração de esquema pelo Hibernate ORM não é suportada nesse caso.

A seguir, exemplos dos arquivos SQL do Flyway a serem criados na pasta configurada src/main/resources/database.

Esquema para o tenant base ( src/main/resources/database/base/V1.0.0__create_fruits.sql ):

CREATE SEQUENCE fruit_seq INCREMENT BY 50; -- 50 is quarkus default
CREATE TABLE fruit
(
    id   INT,
    name VARCHAR(40)
);
INSERT INTO fruit(id, name) VALUES (1, 'Cherry');
INSERT INTO fruit(id, name) VALUES (2, 'Apple');
INSERT INTO fruit(id, name) VALUES (3, 'Banana');
ALTER SEQUENCE fruit_seq RESTART WITH 4;

Esquema para o tenant mycompany ( src/main/resources/database/mycompany/V1.0.0__create_fruits.sql ):

CREATE SEQUENCE fruit_seq INCREMENT BY 50; -- 50 is quarkus default
CREATE TABLE fruit
(
  id   INT,
  name VARCHAR(40)
);
INSERT INTO fruit(id, name) VALUES (1, 'Avocado');
INSERT INTO fruit(id, name) VALUES (2, 'Apricots');
INSERT INTO fruit(id, name) VALUES (3, 'Blackberries');
ALTER SEQUENCE fruit_seq RESTART WITH 4;

Abordagem DISCRIMINADORA

A fonte de dados padrão será usada para todos os tenants. Todas as entidades que definirem um campo anotado com @TenantId terão esse campo preenchido automaticamente e serão filtradas automaticamente nas consultas.

quarkus.hibernate-orm.multitenant=DISCRIMINATOR (1)

quarkus.datasource.db-kind=postgresql (2)

%prod.quarkus.datasource.username=quarkus_test
%prod.quarkus.datasource.password=quarkus_test
%prod.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/quarkus_test
1 Ativar o multi-tenancy do discriminador.
2 Configure a fonte de dados.

Resolução programática de conexões de tenants

Se precisar de uma configuração mais dinâmica para os diferentes locatários que deseja suportar e não quiser ter várias entradas no arquivo de configuração, poderá usar a interface io.quarkus.hibernate.orm.runtime.tenant.TenantConnectionResolver para implementar sua própria lógica para recuperar uma conexão. Criar um bean com escopo de aplicativo que implemente essa interface e anotá-lo com @PersistenceUnitExtension (ou @PersistenceUnitExtension("nameOfYourPU") para uma unidade de persistência nomeada) substituirá a implementação padrão atual do Quarkus, io.quarkus.hibernate.orm.runtime.tenant.DataSourceTenantConnectionResolver. Seu resolvedor de conexão personalizado permitiria, por exemplo, ler as informações do locatário de um banco de dados e criar uma conexão por locatário em tempo de execução com base nelas.

integrações automáticas não funcionarão com o site ConnectionProvider criado programaticamente. Isso significa que todas essas integrações, inclusive as de outros módulos do Quarkus (por exemplo, SmallRye Health), devem ser feitas manualmente.

Aqui está um exemplo de implementação do site TenantConnectionResolver usando tecnologias padrão da Quarkus - Agroal para pooling e Narayana para transações:

@ApplicationScoped
@PersistenceUnitExtension
public class ExampleTenantConnectionResolver implements TenantConnectionResolver {

    private final jakarta.transaction.TransactionManager transactionManager;
    private final TransactionSynchronizationRegistry transactionSynchronizationRegistry;

    public ExampleTenantConnectionResolver(
            TransactionManager transactionManager,
            TransactionSynchronizationRegistry transactionSynchronizationRegistry) {
        this.transactionManager = transactionManager;
        this.transactionSynchronizationRegistry = transactionSynchronizationRegistry;
    }

    @Override
    public ConnectionProvider resolve(String tenantId) {
        // Use your own ConnectionProvider implementation here
        return new YourOwnCustomConnectionProviderImpl(createDatasource(tenantId));
    }

    private AgroalDataSource createDatasource(String tenantId) {
        try {
            final var txIntegration = new NarayanaTransactionIntegration(
                    transactionManager, transactionSynchronizationRegistry, null, false, null);
            // Fetch JDBC URL, username, password & other values from a per-tenant dynamic source
            final var dataSourceConfig = new AgroalDataSourceConfigurationSupplier()
                    .connectionPoolConfiguration(pc -> pc.initialSize(2)
                            .maxSize(10)
                            .minSize(2)
                            .maxLifetime(Duration.of(5, ChronoUnit.MINUTES))
                            .acquisitionTimeout(Duration.of(30, ChronoUnit.SECONDS))
                            .transactionIntegration(txIntegration)
                            .connectionFactoryConfiguration(
                                    cf -> cf.jdbcUrl("jdbc:postgresql://postgres:5432/" + tenantId)
                                            .credential(new NamePrincipal(username))
                                            .credential(new SimplePassword(password))));
            return AgroalDataSource.from(dataSourceConfig.get());
        } catch (SQLException ex) {
            throw new IllegalStateException(
                    "Failed to create a new data source based on the existing datasource configuration", ex);
        }
    }
}

Custom functions, types and mappings

To register custom SQL functions or types, in Hibernate ORM, you can implement the standard Hibernate interfaces:

  • org.hibernate.boot.model.FunctionContributor

  • org.hibernate.boot.model.TypeContributor

Creating an application-scoped bean that implements one of these interfaces and annotating it with @PersistenceUnitExtension (or @PersistenceUnitExtension("nameOfYourPU") for a named persistence unit) will automatically register it with the corresponding persistence unit.

Here is an example of a custom function contributor:

import java.util.List;
import org.hibernate.boot.model.FunctionContributions;
import org.hibernate.boot.model.FunctionContributor;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.StandardArgumentsValidators;
import org.hibernate.query.sqm.produce.function.StandardFunctionArgumentTypeResolvers;
import org.hibernate.query.sqm.produce.function.StandardFunctionReturnTypeResolvers;
import org.hibernate.sql.ast.SqlAstTranslator;
import org.hibernate.sql.ast.spi.SqlAppender;
import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.ReturnableType;
import org.hibernate.sql.ast.tree.expression.SqlAstNodeRenderingMode;
import org.hibernate.type.StandardBasicTypes;
import org.hibernate.type.spi.TypeConfiguration;
import io.quarkus.hibernate.orm.PersistenceUnitExtension;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
@PersistenceUnitExtension
public class CustomFunctionContributor implements FunctionContributor {

    @Override
    public void contributeFunctions(FunctionContributions functionContributions) {
        functionContributions.getFunctionRegistry().register(
                "addHardcodedSuffix",
                new HardcodedSuffixFunction(
                        functionContributions.getTypeConfiguration(), "_some_suffix"));
    }

    private static final class HardcodedSuffixFunction extends AbstractSqmSelfRenderingFunctionDescriptor {
        private final String suffix;

        private HardcodedSuffixFunction(TypeConfiguration typeConfiguration, String suffix) {
            super("addHardcodedSuffix",
                    StandardArgumentsValidators.exactly(1),
                    StandardFunctionReturnTypeResolvers.invariant(
                            typeConfiguration.getBasicTypeRegistry().resolve(StandardBasicTypes.STRING)),
                    StandardFunctionArgumentTypeResolvers.impliedOrInvariant(typeConfiguration, StandardBasicTypes.STRING)
            );
            this.suffix = suffix;
        }

        @Override
        public void render(SqlAppender sqlAppender, List<? extends SqlAstNode> sqlAstArguments, ReturnableType<?> returnType,
                           SqlAstTranslator<?> walker) {
            sqlAppender.appendSql('(');
            walker.render(sqlAstArguments.get(0), SqlAstNodeRenderingMode.DEFAULT);
            sqlAppender.appendSql(" || '" + suffix + "')");
        }
    }
}

And here is an example of a custom type contributor that registers a custom UserType (e.g. mapping a Boolean to "Y"/"N"):

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.hibernate.boot.model.TypeContributions;
import org.hibernate.boot.model.TypeContributor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.type.SqlTypes;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.usertype.UserType;
import io.quarkus.hibernate.orm.PersistenceUnitExtension;
import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
@PersistenceUnitExtension
public class CustomTypeContributor implements TypeContributor {

    @Override
    public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) {
        // Registers the custom type so it can be used via @Type(value = BooleanYesNoType.class) on your entity property
        typeContributions.getTypeConfiguration()
                .getBasicTypeRegistry()
                .register(new BooleanYesNoType(), "boolean_yes_no");
    }

    public static final class BooleanYesNoType implements UserType<Boolean> {
        @Override
        public int getSqlType() {
            return SqlTypes.VARCHAR;
        }

        @Override
        public Class<Boolean> returnedClass() {
            return Boolean.class;
        }

        @Override
        public Boolean nullSafeGet(ResultSet rs, int position, WrapperOptions options) throws SQLException {
            String value = rs.getString(position);

            if (value == null) {
                return null;
            }

            return "Y".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value);
        }

        @Override
        public void nullSafeSet(PreparedStatement st, Boolean value, int position, WrapperOptions options) throws SQLException {
            if (value == null) {
                st.setNull(position, SqlTypes.VARCHAR);
            } else {
                st.setString(position, value ? "Y" : "N");
            }
        }

        @Override
        public Boolean deepCopy(Boolean value) {
            return value;
        }

        @Override
        public boolean isMutable() {
            return false;
        }
    }
}

Interceptadores

Você pode atribuir um org.hibernate.Interceptor ao seu SessionFactory simplesmente definindo um bean CDI com o qualificador apropriado:

@PersistenceUnitExtension (1)
public static class MyInterceptor implements Interceptor, Serializable { (2)
    @Override
    public boolean onLoad(Object entity, Object id, Object[] state, (3)
            String[] propertyNames, Type[] types) {
        // ...
        return false;
    }
}
1 Anote a implementação do interceptador com o qualificador @PersistenceUnitExtension para informar ao Quarkus que ele deve ser usado na unidade de persistência padrão.

Para unidades de persistência nomeadas, use @PersistenceUnitExtension("nameOfYourPU")

2 Implement methods of org.hibernate.Interceptor as necessary.

Por padrão, os beans de interceptador anotados com @PersistenceUnitExtension são escopo da aplicação, o que significa que somente uma instância de interceptador será criada por aplicação e reutilizada em todos os gerenciadores de entidades. Por esse motivo, a implementação do interceptador deve ser thread-safe.

Para criar uma instância de interceptador por gerente de entidade, anote seu bean com @Dependent. Nesse caso, a implementação do interceptador não precisa ser thread-safe.

Devido a uma limitação do próprio Hibernate ORM, os métodos @PreDestroy em interceptores com escopo @Dependent nunca serão chamados.

Inspetores de declaração

Você pode atribuir um org.hibernate.engine.jdbc.spi.StatementInspector ao seu SessionFactory simplesmente definindo um bean CDI com o qualificador apropriado:

@PersistenceUnitExtension (1)
public class MyStatementInspector implements StatementInspector { (2)
    @Override
    public String inspect(String sql) {
        // ...
        return sql;
    }
}
1 Anote a implementação do inspetor de instruções com o qualificador @PersistenceUnitExtension para informar ao Quarkus que ele deve ser usado na unidade de persistência padrão.

Para unidades de persistência nomeadas, use @PersistenceUnitExtension("nameOfYourPU")

2 Implementar org.hibernate.engine.jdbc.spi.StatementInspector .

Personalização da serialização/deserialização JSON/XML

Por padrão, o Quarkus tentará configurar automaticamente os mapeadores de formato, dependendo das extensões disponíveis. O ObjectMapper (ou Jsonb ) configurado globalmente será usado para operações de serialização/desserialização quando o Jackson (ou JSON-B) estiver disponível. Jackson terá precedência se Jackson e JSON-B estiverem disponíveis ao mesmo tempo.

A serialização/desserialização de JSON e XML no Hibernate ORM pode ser personalizada com a implementação de um org.hibernate.type.format.FormatMapper e a anotação da implementação com os qualificadores apropriados:

import io.quarkus.hibernate.orm.JsonFormat;
import org.hibernate.type.format.FormatMapper;

@JsonFormat (1)
@PersistenceUnitExtension (2)
public class MyJsonFormatMapper implements FormatMapper { (3)
    @Override
    public <T> T fromString(CharSequence charSequence, JavaType<T> javaType, WrapperOptions wrapperOptions) {
        // ...
    }

    @Override
    public <T> String toString(T value, JavaType<T> javaType, WrapperOptions wrapperOptions) {
       // ...
    }
}
1 Anote a implementação do mapeador de formato com o qualificador @JsonFormat para informar ao Quarkus que esse mapeador é específico para serialização/desserialização de JSON.
Certifique-se de que a anotação @io.quarkus.hibernate.orm.JsonFormat específica do Quarkus seja usada e não a da Jackson.
2 Anote a implementação do mapeador de formato com o qualificador @PersistenceUnitExtension para informar ao Quarkus que ele deve ser usado na unidade de persistência padrão.

Para unidades de persistência nomeadas, use @PersistenceUnitExtension("nameOfYourPU")

3 Implementar org.hibernate.type.format.FormatMapper .

No caso de um mapeador de formato XML personalizado, um qualificador CDI diferente deve ser aplicado:

import io.quarkus.hibernate.orm.XmlFormat;
import org.hibernate.type.format.FormatMapper;

@XmlFormat (1)
@PersistenceUnitExtension (2)
public class MyJsonFormatMapper implements FormatMapper { (3)
    @Override
    public <T> T fromString(CharSequence charSequence, JavaType<T> javaType, WrapperOptions wrapperOptions) {
        // ...
    }

    @Override
    public <T> String toString(T value, JavaType<T> javaType, WrapperOptions wrapperOptions) {
       // ...
    }
}
1 Anote a implementação do mapeador de formato com o qualificador @XmlFormat para informar ao Quarkus que esse mapeador é específico para serialização/desserialização de XML.
2 Anote a implementação do mapeador de formato com o qualificador @PersistenceUnitExtension para informar ao Quarkus que ele deve ser usado na unidade de persistência padrão.

Para unidades de persistência nomeadas, use @PersistenceUnitExtension("nameOfYourPU")

3 Implementar org.hibernate.type.format.FormatMapper .

Os mapeadores de formato devem ter os qualificadores de CDI @PersistenceUnitExtension e @JsonFormat ou @XmlFormat aplicados.

Ter vários mapeadores de formato JSON (ou XML) registrados para a mesma unidade de persistência resultará em uma exceção, devido à ambiguidade.

Validation modes and Hibernate Validator integration

Hibernate Validator integration into Hibernate ORM opens up the following capabilities:

  • performing entity validation on lifecycle events

  • applying constraint information from entities to DDL

From Quarkus’s perspective, this is controlled by the quarkus.hibernate-orm.validation.mode configuration property. The available validation modes are:

  • auto — the default option; works the same as callback and ddl enabled simultaneously when the application uses quarkus-hibernate-validator, and as none otherwise.

  • callback — Hibernate Validator will perform the lifecycle event validation.

  • ddl — Hibernate Validator constraints will be considered for the DDL operations

  • none — Hibernate Validator integration will be disabled.

While all constraints with corresponding Jakarta Validation rules will apply during the callback validation, in the ddl mode, only a subset of constraints is used to influence the DDL. In the Hibernate Validator documentation, you can find the list of available constraints and their impact on the DDL generation.

Let’s consider having a simple entity with some constraints applied to its properties:

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

@Entity
public class MyEntity {
    @Id
    @GeneratedValue
    public long id;

    @NotNull
    @NotEmpty
    @Size(max = 50)
    public String name;

    public String value;
}

With the ddl mode enabled, the resulting schema would be expected to have the following constraints:

create table myentity
(
    id    bigint      not null  primary key,
    name  varchar(50) not null, (1)
    value varchar(255),         (2)
);
1 The name column has a not null constraint because of the @NotNull constraint, and the length of the values is limited to 50 because of the @Size(max=50) constraint.
2 Since the value property in the entity has no constraints, there are no additional constraints in the DDL, and the 255 length limit comes from the default jakarta.persistence.Column#length().

With the callback mode, expect getting a jakarta.validation.ConstraintViolationException thrown:

try {
    MyEntity entity = new MyEntity();
    entity.setName(veryLongName);
    em.persist(entity);
    em.flush();
} catch (ConstraintViolationException exception) {
    // handle the constraint violations somehow
}

Since Quarkus has built-in exception mappers for jakarta.validation.ConstraintViolationException, explicitly handling these exceptions might be redundant. See the REST end point validation section of the Hibernate Validator guide for more details.

Static metamodel and Jakarta Data

Both static metamodel and Jakarta Data capabilities of Hibernate ORM are available in Quarkus through the hibernate-processor annotation processor. Since it is an annotation processor, you must configure it accordingly in your build tool:

pom.xml
<plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
        <!-- This setting is required for the annotation processor dependencies to be managed by Quarkus.
             More information is available in Maven compiler plugin documentation:
             https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#annotationProcessorPathsUseDepMgmt -->
        <annotationProcessorPathsUseDepMgmt>true</annotationProcessorPathsUseDepMgmt>
        <annotationProcessorPaths>
            <path>
                <groupId>org.hibernate.orm</groupId>
                <artifactId>hibernate-processor</artifactId>
                <!-- Note, no artifact version is required, it's managed by Quarkus.  -->
            </path>
            <!-- other processors that may be required by your app -->
        </annotationProcessorPaths>
        <!-- Other compiler plugin configuration options -->
    </configuration>
</plugin>
build.gradle
// Enforce the version management of your annotation processor dependencies,
// so that there's no need to define an explicit version of the hibernate-processor
annotationProcessor enforcedPlatform("${quarkusPlatformGroupId}:${quarkusPlatformArtifactId}:${quarkusPlatformVersion}")
annotationProcessor 'org.hibernate.orm:hibernate-processor'

Static metamodel

The generated static metamodel allows for building queries in a type-safe manner. Let’s consider having a simple entity:

@Entity
public class MyEntity {
    @Id
    @GeneratedValue
    public Integer id;

    @Column(unique = true)
    public String name;
}

A query created with the help of static metamodel may look as:

var builder = session.getCriteriaBuilder();
var criteria = builder.createQuery(MyEntity.class);
var e = criteria.from(MyEntity_.class);
criteria.where(e.get(MyEntity_.name).equalTo(name));
var query = session.createQuery(criteria);
var result = query.list();

For a more detailed overview of static metamodel, please refer to the Jakarta Persistence specification.

Jakarta Data

Jakarta Data requires, besides having the hibernate-processor annotation processor in place, one extra dependency to be added:

pom.xml
<dependency>
    <groupId>jakarta.data</groupId>
    <artifactId>jakarta.data-api</artifactId>
</dependency>
build.gradle
implementation 'jakarta.data:jakarta.data-api'

With this dependency, and the annotation processor in place you could simply create your repositories as follows:

@Repository
public interface MyRepository extends CrudRepository<MyEntity, Integer> { (1)

    @Query("select e from MyEntity e where e.name like :name") (2)
    List<MyEntity> findByName(String name);

    @Delete (3)
    void delete(String name);

}
1 To skip the boilerplate definition of CRUD operations, we can use one of the available interfaces (e.g. CrudRepository or BasicRepository).
2 Adding custom queries with parameters is as easy as providing your query string to the @Query annotation.
3 If the basic CRUD operations from the Jakarta Data interfaces are not enough, we can always add a custom one, in this case a delete operation that removes `MyEntity`s by name.

And then the repository can be used as any other bean:

public class MyEntityResource {

    @Inject
    MyRepository repository;

    @POST
    @Transactional
    public void create(MyEntity entity) {
        repository.insert(entity);
    }

    // ...

}

When working with non-default persistence units, remember to specify the persistence unit name the repository is targeting in the dataStore attribute of the repository annotation:

@Repository(dataStore = "other") (1)
public interface MyNonDefaultPURepository {
    // ...
}
1 Pass the name of the non-default persistence unit to the repository annotation (other in this example).

Review the Javadoc of the @Repository annotation to learn more about the dataStore attribute.

Please refer to the corresponding Hibernate Data Repositories and Jakarta Data guides to learn what else they have to offer.

Secure Jakarta Data repositories

Quarkus Security provides an initial support for securing Jakarta Data Repositories with security annotations.

Example Jakarta Data repository with method-level security annotation
@Repository
public interface MyRepository extends CrudRepository<MyEntity, Integer> {

    @RolesAllowed("admin")
    @Delete
    void delete(String name);

}
Example Jakarta Data repository with class-level security annotation
@Authenticated
@Repository
public interface MyRepository extends CrudRepository<MyEntity, Integer> {

    @Delete
    void delete(String name);

}

In the example above, only methods directly declared on the MyRepository interface are secured. Methods inherited from CrudRepository, such as insert, are not secured because type-level annotations only affect the type they annotate.

Currently, generic interface methods using type variables or wildcards cannot be secured reliably with standard security annotations. Therefore, you must not attempt to secure such methods and instead use two alternatives described below.

Example repository with a generic method using a type variable
public interface MyParentRepository<T extends MyEntity> {

    @Find
    Stream<T> findAll(Order<T> order);

}

@Repository
public interface MyRepository extends MyParentRepository<MyEntity> {
}

Alternative 1: Apply a security annotation to the calling method in your REST layer:

@Path("my-entity")
public class MyEntityResource {

    @Inject
    MyRepository myRepository;

    @PermissionsAllowed("find-all")
    @GET
    public List<MyEntity> findAll() {
        return myRepository.findAll(Order.by(Sort.asc(MyEntity_.NAME))).toList();
    }

}

Alternative 2: Replace the type variable T with a concrete type in the repository interface:

@Repository
public interface MyRepository {

    @PermissionsAllowed("find-all")
    @Find
    Stream<MyEntity> findAll(Order<MyEntity> order);

}

Configuration Reference for Hibernate ORM

Propriedade de Configuração Fixa no Momento da Compilação - Todas as outras propriedades de configuração podem ser sobrepostas em tempo de execução.

Configuration property

Tipo

Padrão

Whether Hibernate ORM is enabled during the build.

If Hibernate ORM is disabled during the build, all processing related to Hibernate ORM will be skipped, but it will not be possible to activate Hibernate ORM at runtime: quarkus.hibernate-orm.active will default to false and setting it to true will lead to an error.

Environment variable: QUARKUS_HIBERNATE_ORM_ENABLED

Show more

booleano

true

Whether Hibernate ORM is working in blocking mode.

Hibernate ORM’s blocking EntityManager/Session/SessionFactory are normally disabled by default if no JDBC datasource is found. You can set this property to false if you want to disable them despite having a JDBC datasource.

Environment variable: QUARKUS_HIBERNATE_ORM_BLOCKING

Show more

booleano

true

If true, Quarkus will ignore any persistence.xml file in the classpath and rely exclusively on the Quarkus configuration.

Environment variable: QUARKUS_HIBERNATE_ORM_PERSISTENCE_XML_IGNORE

Show more

booleano

false

Whether statistics collection is enabled. If 'metrics.enabled' is true, then the default here is considered true, otherwise the default is false.

Environment variable: QUARKUS_HIBERNATE_ORM_STATISTICS

Show more

booleano

Whether session metrics should be appended into the server log for each Hibernate session. This only has effect if statistics are enabled (quarkus.hibernate-orm.statistics). The default is false (which means both statistics and log-session-metrics need to be enabled for the session metrics to appear in the log).

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_SESSION_METRICS

Show more

booleano

Whether metrics are published if a metrics extension is enabled.

Environment variable: QUARKUS_HIBERNATE_ORM_METRICS_ENABLED

Show more

booleano

false

Allow hql queries in the Dev UI page

Environment variable: QUARKUS_HIBERNATE_ORM_DEV_UI_ALLOW_HQL

Show more

booleano

false

Enable or disable access to a Hibernate ORM EntityManager/Session/StatelessSession *when no transaction is active* but a request scope is. When enabled, the corresponding sessions will be read-only. Defaults to enabled for backwards compatibility, but disabling this is recommended, to avoid inconsistent resulsts caused by queries running outside of transactions.

Environment variable: QUARKUS_HIBERNATE_ORM_REQUEST_SCOPED_ENABLED

Show more

booleano

true

quarkus.hibernate-orm."persistence-unit-name".datasource

The name of the datasource which this persistence unit uses.

If undefined, it will use the default datasource.

Environment variable: QUARKUS_HIBERNATE_ORM_DATASOURCE

Show more

string

quarkus.hibernate-orm."persistence-unit-name".packages

The packages in which the entities affected to this persistence unit are located.

Environment variable: QUARKUS_HIBERNATE_ORM_PACKAGES

Show more

list of string

quarkus.hibernate-orm."persistence-unit-name".sql-load-script

Paths to files containing the SQL statements to execute when Hibernate ORM starts.

The files are retrieved from the classpath resources, so they must be located in the resources directory (e.g. src/main/resources).

The default value for this setting differs depending on the Quarkus launch mode:

  • In dev and test modes, it defaults to import.sql. Simply add an import.sql file in the root of your resources directory and it will be picked up without having to set this property. Pass no-file to force Hibernate ORM to ignore the SQL import file.

  • In production mode, it defaults to no-file. It means Hibernate ORM won’t try to execute any SQL import file by default. Pass an explicit value to force Hibernate ORM to execute the SQL import file.

If you need different SQL statements between dev mode, test (@QuarkusTest) and in production, use Quarkus configuration profiles facility.

application.properties
%dev.quarkus.hibernate-orm.sql-load-script = import-dev.sql
%test.quarkus.hibernate-orm.sql-load-script = import-test.sql
%prod.quarkus.hibernate-orm.sql-load-script = no-file

Quarkus supports files with SQL statements or comments spread over multiple lines, or .zip files containing those files. Each SQL statement must be terminated by a semicolon.

Environment variable: QUARKUS_HIBERNATE_ORM_SQL_LOAD_SCRIPT

Show more

list of string

import.sql in dev and test modes ; no-file otherwise

quarkus.hibernate-orm."persistence-unit-name".physical-naming-strategy

Pluggable strategy contract for applying physical naming rules for database object names. Class name of the Hibernate PhysicalNamingStrategy implementation

Environment variable: QUARKUS_HIBERNATE_ORM_PHYSICAL_NAMING_STRATEGY

Show more

string

quarkus.hibernate-orm."persistence-unit-name".implicit-naming-strategy

Pluggable strategy for applying implicit naming rules when an explicit name is not given. Class name of the Hibernate ImplicitNamingStrategy implementation

Environment variable: QUARKUS_HIBERNATE_ORM_IMPLICIT_NAMING_STRATEGY

Show more

string

quarkus.hibernate-orm."persistence-unit-name".mapping-files

XML files to configure the entity mapping, e.g. META-INF/my-orm.xml.

Defaults to META-INF/orm.xml if it exists. Pass no-file to force Hibernate ORM to ignore META-INF/orm.xml.

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_FILES

Show more

list of string

META-INF/orm.xml if it exists; no-file otherwise

quarkus.hibernate-orm."persistence-unit-name".quote-identifiers.strategy

Identifiers can be quoted using one of the available strategies.

Set to none by default, meaning no identifiers will be quoted. If set to all, all identifiers and column definitions will be quoted. Additionally, setting it to all-except-column-definitions will skip the column definitions, which can usually be required when they exist, or else use the option only-keywords to quote only identifiers deemed SQL keywords by the Hibernate ORM dialect.

Environment variable: QUARKUS_HIBERNATE_ORM_QUOTE_IDENTIFIERS_STRATEGY

Show more

noneIdentifiers are not quoted., allAll identifiers are quoted., all-except-column-definitionsAll identifiers, except column definitions, are quoted., only-keywordsOnly keywords will be quoted.

noneIdentifiers are not quoted.

quarkus.hibernate-orm."persistence-unit-name".second-level-caching-enabled

The default in Quarkus is for 2nd level caching to be enabled, and a good implementation is already integrated for you.

Just cherry-pick which entities should be using the cache.

Set this to false to disable all 2nd level caches.

Environment variable: QUARKUS_HIBERNATE_ORM_SECOND_LEVEL_CACHING_ENABLED

Show more

booleano

true

quarkus.hibernate-orm."persistence-unit-name".validation.mode

Defines how the Bean Validation integration behaves.

Environment variable: QUARKUS_HIBERNATE_ORM_VALIDATION_MODE

Show more

list of autoIf a Bean Validation provider is present then behaves as if both ValidationMode#CALLBACK and ValidationMode#DDL modes are configured. Otherwise, same as ValidationMode#NONE., callbackBean Validation will perform the lifecycle event validation., ddlBean Validation constraints will be considered for the DDL operations., noneBean Validation integration will be disabled.

auto

quarkus.hibernate-orm."persistence-unit-name".multitenant

Defines the method for multi-tenancy (DATABASE, NONE, SCHEMA). The complete list of allowed values is available in the Hibernate ORM JavaDoc. The type DISCRIMINATOR is currently not supported. The default value is NONE (no multi-tenancy).

Environment variable: QUARKUS_HIBERNATE_ORM_MULTITENANT

Show more

string

quarkus.hibernate-orm."persistence-unit-name".validate-in-dev-mode

If hibernate is not auto generating the schema, and Quarkus is running in development mode then Quarkus will attempt to validate the database after startup and print a log message if there are any problems.

Environment variable: QUARKUS_HIBERNATE_ORM_VALIDATE_IN_DEV_MODE

Show more

booleano

true

quarkus.hibernate-orm."persistence-unit-name".active

Whether this persistence unit should be active at runtime.

Note that if Hibernate ORM is disabled (i.e. quarkus.hibernate-orm.enabled is set to false), all persistence units are deactivated, and setting this property to true will fail.

Environment variable: QUARKUS_HIBERNATE_ORM_ACTIVE

Show more

booleano

`true` if Hibernate ORM is enabled and there are entity types or an active datasource assigned to the persistence unit; `false` otherwise

quarkus.hibernate-orm."persistence-unit-name".unsupported-properties."full-property-key"

Properties that should be passed on directly to Hibernate ORM. Use the full configuration property key here, for instance quarkus.hibernate-orm.unsupported-properties."hibernate.order_inserts" = true.

Properties set here are completely unsupported: as Quarkus doesn’t generally know about these properties and their purpose, there is absolutely no guarantee that they will work correctly, and even if they do, that may change when upgrading to a newer version of Quarkus (even just a micro/patch version).

Consider using a supported configuration property before falling back to unsupported ones. If none exists, make sure to file a feature request so that a supported configuration property can be added to Quarkus, and more importantly so that the configuration property is tested regularly.

Environment variable: QUARKUS_HIBERNATE_ORM_UNSUPPORTED_PROPERTIES__FULL_PROPERTY_KEY_

Show more

Map<String,String>

quarkus.hibernate-orm."persistence-unit-name".batch-fetch-size

This property is deprecated: fetch should be used to configure fetching properties.

The size of the batches used when loading entities and collections.

-1 means batch loading is disabled.

Environment variable: QUARKUS_HIBERNATE_ORM_BATCH_FETCH_SIZE

Show more

int

16

quarkus.hibernate-orm."persistence-unit-name".max-fetch-depth

This property is deprecated: fetch should be used to configure fetching properties.

The maximum depth of outer join fetch tree for single-ended associations (one-to-one, many-to-one).

A 0 disables default outer join fetching.

Environment variable: QUARKUS_HIBERNATE_ORM_MAX_FETCH_DEPTH

Show more

int

quarkus.hibernate-orm."persistence-unit-name".metadata-builder-contributor

This property is deprecated.

Class name of a custom org.hibernate.boot.spi.MetadataBuilderContributor implementation.

Not all customization options exposed by org.hibernate.boot.MetadataBuilder will work correctly. Stay clear of options related to classpath scanning in particular.

This setting is exposed mainly to allow registration of types, converters and SQL functions.

  • @deprecated Use TypeContributor, FunctionContributor or AdditionalMappingContributor instead.

Environment variable: QUARKUS_HIBERNATE_ORM_METADATA_BUILDER_CONTRIBUTOR

Show more

string

quarkus.hibernate-orm."persistence-unit-name".validation.enabled

This property is deprecated since 3.19: Use mode() instead.

Enables the Bean Validation integration.

Environment variable: QUARKUS_HIBERNATE_ORM_VALIDATION_ENABLED

Show more

booleano

true

quarkus.hibernate-orm."persistence-unit-name".multitenant-schema-datasource

This property is deprecated: Use datasource() instead.

Defines the name of the datasource to use in case of SCHEMA approach. The datasource of the persistence unit will be used if not set.

Environment variable: QUARKUS_HIBERNATE_ORM_MULTITENANT_SCHEMA_DATASOURCE

Show more

string

Database related configuration

Tipo

Padrão

When set, attempts to exchange data with the database as the given version of Hibernate ORM would have, on a best-effort basis.

Please note:

  • schema validation may still fail in some cases: this attempts to make Hibernate ORM 6+ behave correctly at runtime, but it may still expect a different (but runtime-compatible) schema.

  • robust test suites are still useful and recommended: you should still check that your application behaves as intended with your legacy schema.

  • this feature is inherently unstable: some aspects of it may stop working in future versions of Quarkus, and older versions will be dropped as Hibernate ORM changes pile up and support for those older versions becomes too unreliable.

  • you should still plan a migration of your schema to a newer version of Hibernate ORM. For help with migration, refer to the Quarkus 3 migration guide from Hibernate ORM 5 to 6.

Environment variable: QUARKUS_HIBERNATE_ORM_DATABASE_ORM_COMPATIBILITY_VERSION

Show more

5.6, latest

latest

quarkus.hibernate-orm."persistence-unit-name".database.charset

The charset of the database.

Used for DDL generation and also for the SQL import scripts.

Environment variable: QUARKUS_HIBERNATE_ORM_DATABASE_CHARSET

Show more

Charset

UTF-8

quarkus.hibernate-orm."persistence-unit-name".database.default-catalog

The default catalog to use for the database objects.

Environment variable: QUARKUS_HIBERNATE_ORM_DATABASE_DEFAULT_CATALOG

Show more

string

quarkus.hibernate-orm."persistence-unit-name".database.default-schema

The default schema to use for the database objects.

Environment variable: QUARKUS_HIBERNATE_ORM_DATABASE_DEFAULT_SCHEMA

Show more

string

quarkus.hibernate-orm."persistence-unit-name".database.version-check.enabled

Whether Hibernate ORM should check on startup that the version of the database matches the version configured on the dialect (either the default version, or the one set through quarkus.datasource.db-version).

This should be set to false if the database is not available on startup.

Environment variable: QUARKUS_HIBERNATE_ORM_DATABASE_VERSION_CHECK_ENABLED

Show more

booleano

`false` if starting offline (see `start-offline`), `true` otherwise

quarkus.hibernate-orm."persistence-unit-name".database.start-offline

Instructs Hibernate ORM to avoid connecting to the database on startup.

When starting offline: * Hibernate ORM will not attempt to create a schema automatically, so it must already be created when the application hits the database for the first time. * Quarkus will not check that the database version matches the one configured at build time.

Environment variable: QUARKUS_HIBERNATE_ORM_DATABASE_START_OFFLINE

Show more

booleano

false

JSON/XML mapping related configuration

Tipo

Padrão

How the default JSON/XML format mappers are configured. Only available to mitigate migration from the current Quarkus-preconfigured format mappers (that will be removed in the future version).

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_FORMAT_GLOBAL

Show more

ignore, warn, fail

fail

quarkus.hibernate-orm."persistence-unit-name".mapping.timezone.default-storage

How to store timezones in the database by default for properties of type OffsetDateTime and ZonedDateTime. This default may be overridden on a per-property basis using @TimeZoneStorage. NOTE: Properties of type OffsetTime are https://hibernate.atlassian.net/browse/HHH-16287[not affected by this setting].

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_TIMEZONE_DEFAULT_STORAGE

Show more

nativeStores the timestamp and timezone in a column of type timestamp with time zone. Only available on some databases/dialects; if not supported, an exception will be thrown during static initialization., normalizeDoes not store the timezone, and loses timezone information upon persisting. Instead, normalizes the value\: * upon persisting to the database, to a timestamp in the JDBC timezone set through quarkus.hibernate-orm.jdbc.timezone, or the JVM default timezone if not set. * upon reading back from the database, to the JVM default timezone. Use this to get the legacy behavior of Quarkus 2 / Hibernate ORM 5 or older., normalize-utcDoes not store the timezone, and loses timezone information upon persisting. Instead, normalizes the value to a timestamp in the UTC timezone., columnStores the timezone in a separate column next to the timestamp column. Use @TimeZoneColumn on the relevant entity property to customize the timezone column., autoEquivalent to native if supported, column otherwise., defaultEquivalent to native if supported, normalize-utc otherwise.

defaultEquivalent to native if supported, normalize-utc otherwise.

quarkus.hibernate-orm."persistence-unit-name".mapping.id.optimizer.default

The optimizer to apply to identifier generators whose optimizer is not configured explicitly.

Only relevant for table- and sequence-based identifier generators. Other generators, such as UUID-based generators, will ignore this setting.

The optimizer is responsible for pooling new identifier values, in order to reduce the frequency of database calls to retrieve those values and thereby improve performance.

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_ID_OPTIMIZER_DEFAULT

Show more

pooled-loAssumes the value retrieved from the table/sequence is the lower end of the pool. Upon retrieving value N, the new pool of identifiers will go from N to N + <allocation size> - 1, inclusive., pooledAssumes the value retrieved from the table/sequence is the higher end of the pool. Upon retrieving value N, the new pool of identifiers will go from N - <allocation size> to N + <allocation size> - 1, inclusive. The first value, 1, is handled differently to avoid negative identifiers. Use this to get the legacy behavior of Quarkus 2 / Hibernate ORM 5 or older., noneNo optimizer, resulting in a database call each and every time an identifier value is needed from the generator. Not recommended in production environments\: may result in degraded performance and/or frequent gaps in identifier values.

pooled-loAssumes the value retrieved from the table/sequence is the lower end of the pool. Upon retrieving value N, the new pool of identifiers will go from N to N + <allocation size> - 1, inclusive.

quarkus.hibernate-orm."persistence-unit-name".mapping.duration.preferred-jdbc-type

The preferred JDBC type to use for storing {@link java.time.Duration} values. <p> Can be overridden locally using @JdbcType, @JdbcTypeCode, and similar annotations. <p> Can also specify the name of the SqlTypes constant field, for example, quarkus.hibernate-orm.mapping.type.preferred_jdbc_type=INTERVAL_SECOND.

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_DURATION_PREFERRED_JDBC_TYPE

Show more

string

INTERVAL_SECOND

quarkus.hibernate-orm."persistence-unit-name".mapping.instant.preferred-jdbc-type

The preferred JDBC type to use for storing {@link java.time.Instant} values. <p> Can be overridden locally using @JdbcType, @JdbcTypeCode, and similar annotations. <p> Can also specify the name of the SqlTypes constant field, for example, quarkus.hibernate-orm.mapping.instant.preferred-jdbc-type=TIMESTAMP or quarkus.hibernate-orm.mapping.instant.preferred-jdbc-type=INSTANT.

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_INSTANT_PREFERRED_JDBC_TYPE

Show more

string

TIMESTAMP

quarkus.hibernate-orm."persistence-unit-name".mapping.boolean.preferred-jdbc-type

The preferred JDBC type to use for storing boolean values. <p> Can be overridden locally using @JdbcType, @JdbcTypeCode, and similar annotations. <p> Can also specify the name of the SqlTypes constant field, for example, quarkus.hibernate-orm.mapping.boolean.preferred-jdbc-type=BIT.

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_BOOLEAN_PREFERRED_JDBC_TYPE

Show more

string

BOOLEAN

quarkus.hibernate-orm."persistence-unit-name".mapping.uuid.preferred-jdbc-type

The preferred JDBC type to use for storing {@link java.util.UUID} values. <p> Can be overridden locally using @JdbcType, @JdbcTypeCode, and similar annotations. <p> Can also specify the name of the SqlTypes constant field, for example, quarkus.hibernate-orm.mapping.uuid.preferred-jdbc-type=CHAR.

Environment variable: QUARKUS_HIBERNATE_ORM_MAPPING_UUID_PREFERRED_JDBC_TYPE

Show more

string

UUID

Dialect related configuration

Tipo

Padrão

quarkus.hibernate-orm."persistence-unit-name".dialect

Name of the Hibernate ORM dialect.

For supported databases, this property does not need to be set explicitly: it is selected automatically based on the datasource, and configured using the DB version set on the datasource to benefit from the best performance and latest features.

If your database does not have a corresponding Quarkus extension, you will need to set this property explicitly. In that case, keep in mind that the JDBC driver and Hibernate ORM dialect may not work properly in GraalVM native executables.

For built-in dialects, the expected value is one of the names in the official list of dialects, without the Dialect suffix, for example Cockroach for CockroachDialect.

For third-party dialects, the expected value is the fully-qualified class name, for example com.acme.hibernate.AcmeDbDialect.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT

Show more

string

selected automatically for most popular databases

quarkus.hibernate-orm."persistence-unit-name".dialect.mariadb.bytes-per-character

Specifies the bytes per character to use based on the database’s configured charset.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MARIADB_BYTES_PER_CHARACTER

Show more

int

4

quarkus.hibernate-orm."persistence-unit-name".dialect.mariadb.no-backslash-escapes

Specifies whether the NO_BACKSLASH_ESCAPES sql mode is enabled.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MARIADB_NO_BACKSLASH_ESCAPES

Show more

booleano

false

quarkus.hibernate-orm."persistence-unit-name".dialect.mariadb.storage-engine

The storage engine to use.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MARIADB_STORAGE_ENGINE

Show more

string

quarkus.hibernate-orm."persistence-unit-name".dialect.mysql.bytes-per-character

Specifies the bytes per character to use based on the database’s configured charset.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MYSQL_BYTES_PER_CHARACTER

Show more

int

4

quarkus.hibernate-orm."persistence-unit-name".dialect.mysql.no-backslash-escapes

Specifies whether the NO_BACKSLASH_ESCAPES sql mode is enabled.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MYSQL_NO_BACKSLASH_ESCAPES

Show more

booleano

false

quarkus.hibernate-orm."persistence-unit-name".dialect.mysql.storage-engine

The storage engine to use.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MYSQL_STORAGE_ENGINE

Show more

string

quarkus.hibernate-orm."persistence-unit-name".dialect.oracle.extended

Support for Oracle’s MAX_STRING_SIZE = EXTENDED.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_ORACLE_EXTENDED

Show more

booleano

false

quarkus.hibernate-orm."persistence-unit-name".dialect.oracle.autonomous

Specifies whether this database is running on an Autonomous Database Cloud Service.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_ORACLE_AUTONOMOUS

Show more

booleano

false

quarkus.hibernate-orm."persistence-unit-name".dialect.oracle.application-continuity

Specifies whether this database is accessed using a database service protected by Application Continuity.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_ORACLE_APPLICATION_CONTINUITY

Show more

booleano

false

quarkus.hibernate-orm."persistence-unit-name".dialect.mssql.compatibility-level

The compatibility_level as defined in sys.databases.

Environment variable: QUARKUS_HIBERNATE_ORM_DIALECT_MSSQL_COMPATIBILITY_LEVEL

Show more

string

Query related configuration

Tipo

Padrão

quarkus.hibernate-orm."persistence-unit-name".query.query-plan-cache-max-size

The maximum size of the query plan cache. see #org.hibernate.cfg.AvailableSettings#QUERY_PLAN_CACHE_MAX_SIZE

Environment variable: QUARKUS_HIBERNATE_ORM_QUERY_QUERY_PLAN_CACHE_MAX_SIZE

Show more

int

2048

quarkus.hibernate-orm."persistence-unit-name".query.default-null-ordering

Default precedence of null values in ORDER BY clauses.

Valid values are: none, first, last.

Environment variable: QUARKUS_HIBERNATE_ORM_QUERY_DEFAULT_NULL_ORDERING

Show more

noneNull precedence not specified., firstNull values occur at the beginning of the ORDER BY clause., lastNull values occur at the end of the ORDER BY clause.

noneNull precedence not specified.

quarkus.hibernate-orm."persistence-unit-name".query.in-clause-parameter-padding

Enables IN clause parameter padding which improves statement caching.

Environment variable: QUARKUS_HIBERNATE_ORM_QUERY_IN_CLAUSE_PARAMETER_PADDING

Show more

booleano

true

quarkus.hibernate-orm."persistence-unit-name".query.fail-on-pagination-over-collection-fetch

When limits cannot be applied on the database side, trigger an exception instead of attempting badly-performing in-memory result set limits.

When pagination is used in combination with a fetch join applied to a collection or many-valued association, the limit must be applied in-memory instead of on the database. This should be avoided as it typically has terrible performance characteristics.

Environment variable: QUARKUS_HIBERNATE_ORM_QUERY_FAIL_ON_PAGINATION_OVER_COLLECTION_FETCH

Show more

booleano

false

JDBC related configuration

Tipo

Padrão

quarkus.hibernate-orm."persistence-unit-name".jdbc.timezone

The time zone pushed to the JDBC driver. See quarkus.hibernate-orm.mapping.timezone.default-storage.

Environment variable: QUARKUS_HIBERNATE_ORM_JDBC_TIMEZONE

Show more

string

quarkus.hibernate-orm."persistence-unit-name".jdbc.statement-fetch-size

How many rows are fetched at a time by the JDBC driver.

Environment variable: QUARKUS_HIBERNATE_ORM_JDBC_STATEMENT_FETCH_SIZE

Show more

int

quarkus.hibernate-orm."persistence-unit-name".jdbc.statement-batch-size

The number of updates (inserts, updates and deletes) that are sent by the JDBC driver at one time for execution.

Environment variable: QUARKUS_HIBERNATE_ORM_JDBC_STATEMENT_BATCH_SIZE

Show more

int

Fetching logic configuration

Tipo

Padrão

quarkus.hibernate-orm."persistence-unit-name".fetch.batch-size

The size of the batches used when loading entities and collections.

-1 means batch loading is disabled.

Environment variable: QUARKUS_HIBERNATE_ORM_FETCH_BATCH_SIZE

Show more

int

16

quarkus.hibernate-orm."persistence-unit-name".fetch.max-depth

The maximum depth of outer join fetch tree for single-ended associations (one-to-one, many-to-one).

A 0 disables default outer join fetching.

Environment variable: QUARKUS_HIBERNATE_ORM_FETCH_MAX_DEPTH

Show more

int

Caching configuration

Tipo

Padrão

quarkus.hibernate-orm."persistence-unit-name".cache."cache".expiration.max-idle

The maximum time before an object of the cache is considered expired.

Environment variable: QUARKUS_HIBERNATE_ORM_CACHE__CACHE__EXPIRATION_MAX_IDLE

Show more

Duration 

100s

quarkus.hibernate-orm."persistence-unit-name".cache."cache".memory.object-count

The maximum number of objects kept in memory in the cache.

Environment variable: QUARKUS_HIBERNATE_ORM_CACHE__CACHE__MEMORY_OBJECT_COUNT

Show more

long

10000

Discriminator related configuration

Tipo

Padrão

quarkus.hibernate-orm."persistence-unit-name".discriminator.ignore-explicit-for-joined

Existing applications rely (implicitly or explicitly) on Hibernate ignoring any DiscriminatorColumn declarations on joined inheritance hierarchies. This setting allows these applications to maintain the legacy behavior of DiscriminatorColumn annotations being ignored when paired with joined inheritance.

Environment variable: QUARKUS_HIBERNATE_ORM_DISCRIMINATOR_IGNORE_EXPLICIT_FOR_JOINED

Show more

booleano

false

Logging configuration

Tipo

Padrão

Logs SQL bind parameters.

Setting it to true is obviously not recommended in production.

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_BIND_PARAMETERS

Show more

booleano

false

quarkus.hibernate-orm."persistence-unit-name".log.sql

Show SQL logs and format them nicely.

Setting it to true is obviously not recommended in production.

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_SQL

Show more

booleano

false

quarkus.hibernate-orm."persistence-unit-name".log.format-sql

Format the SQL logs if SQL log is enabled

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_FORMAT_SQL

Show more

booleano

true

quarkus.hibernate-orm."persistence-unit-name".log.highlight-sql

Highlight the SQL logs if SQL log is enabled

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_HIGHLIGHT_SQL

Show more

booleano

true

quarkus.hibernate-orm."persistence-unit-name".log.jdbc-warnings

Whether JDBC warnings should be collected and logged.

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_JDBC_WARNINGS

Show more

booleano

depends on dialect

quarkus.hibernate-orm."persistence-unit-name".log.queries-slower-than-ms

If set, Hibernate will log queries that took more than specified number of milliseconds to execute.

Environment variable: QUARKUS_HIBERNATE_ORM_LOG_QUERIES_SLOWER_THAN_MS

Show more

long

Schema management configuration

Tipo

Padrão

quarkus.hibernate-orm."persistence-unit-name".schema-management.strategy

Select whether the database schema is generated or not.

drop-and-create is awesome in development mode.

This defaults to 'none'.

However if Dev Services is in use and no other extensions that manage the schema are present the value will be automatically overridden to 'drop-and-create'.

Accepted values: none, create, drop-and-create, drop, update, validate.

Environment variable: QUARKUS_HIBERNATE_ORM_SCHEMA_MANAGEMENT_STRATEGY

Show more

noneNo schema action., createCreate the schema., drop-and-createDrop and then recreate the schema., dropDrop the schema., updateUpdate (alter) the database schema., validateValidate the database schema.

noneNo schema action.

quarkus.hibernate-orm."persistence-unit-name".schema-management.create-schemas

If Hibernate ORM should create the schemas automatically (for databases supporting them).

Environment variable: QUARKUS_HIBERNATE_ORM_SCHEMA_MANAGEMENT_CREATE_SCHEMAS

Show more

booleano

false

quarkus.hibernate-orm."persistence-unit-name".schema-management.halt-on-error

Whether we should stop on the first error when applying the schema.

Environment variable: QUARKUS_HIBERNATE_ORM_SCHEMA_MANAGEMENT_HALT_ON_ERROR

Show more

booleano

false

quarkus.hibernate-orm."persistence-unit-name".schema-management.extra-physical-table-types

Additional database object types to include in schema management operations.

By default, Hibernate ORM only considers tables and sequences when performing schema management operations. This setting allows you to specify additional database object types that should be included, such as "MATERIALIZED VIEW", "VIEW", or other database-specific object types.

The exact supported values depend on the underlying database and dialect.

Environment variable: QUARKUS_HIBERNATE_ORM_SCHEMA_MANAGEMENT_EXTRA_PHYSICAL_TABLE_TYPES

Show more

string

Database scripts related configuration

Tipo

Padrão

quarkus.hibernate-orm."persistence-unit-name".scripts.generation

Select whether the database schema DDL files are generated or not. Accepted values: none, create, drop-and-create, drop, update, validate.

Environment variable: QUARKUS_HIBERNATE_ORM_SCRIPTS_GENERATION

Show more

noneNo schema action., createCreate the schema., drop-and-createDrop and then recreate the schema., dropDrop the schema., updateUpdate (alter) the database schema., validateValidate the database schema.

noneNo schema action.

quarkus.hibernate-orm."persistence-unit-name".scripts.generation.create-target

Filename or URL where the database create DDL file should be generated.

Environment variable: QUARKUS_HIBERNATE_ORM_SCRIPTS_GENERATION_CREATE_TARGET

Show more

string

quarkus.hibernate-orm."persistence-unit-name".scripts.generation.drop-target

Filename or URL where the database drop DDL file should be generated.

Environment variable: QUARKUS_HIBERNATE_ORM_SCRIPTS_GENERATION_DROP_TARGET

Show more

string

Flush configuration

Tipo

Padrão

quarkus.hibernate-orm."persistence-unit-name".flush.mode

The default flushing strategy, or when to flush entities to the database in a Hibernate session: before every query, on commit, …​

This default can be overridden on a per-session basis with Session#setHibernateFlushMode() or on a per-query basis with the hint HibernateHints#HINT_FLUSH_MODE.

See the javadoc of org.hibernate.FlushMode for details.

Environment variable: QUARKUS_HIBERNATE_ORM_FLUSH_MODE

Show more

manualThe org.hibernate.Session is only flushed when org.hibernate.Session#flush() is called explicitly. This mode is very efficient for read-only transactions., commitThe org.hibernate.Session is flushed when org.hibernate.Transaction#commit() is called. It is never automatically flushed before query execution., autoThe org.hibernate.Session is flushed when org.hibernate.Transaction#commit() is called, and is sometimes flushed before query execution in order to ensure that queries never return stale state. This is the default flush mode., alwaysThe org.hibernate.Session is flushed when org.hibernate.Transaction#commit() is called and before every query. This is usually unnecessary and inefficient.

autoThe org.hibernate.Session is flushed when org.hibernate.Transaction#commit() is called, and is sometimes flushed before query execution in order to ensure that queries never return stale state. This is the default flush mode.

About the Duration format

To write duration values, use the standard java.time.Duration format. See the Duration#parse() Java API documentation for more information.

Você também pode usar um formato simplificado, começando com um número:

  • Se o valor for apenas um número, ele representará o tempo em segundos.

  • Se o valor for um número seguido de 'ms', ele representa o tempo em milissegundos.

Em outros casos, o formato simplificado é traduzido para o formato 'java.time.Duration' para análise:

  • Se o valor for um número seguido de 'h', 'm' ou 's', ele é prefixado com 'PT'.

  • Se o valor for um número seguido de 'd', ele é prefixado com 'P'.

Related content