
本教程详细阐述了如何在 quarkus 应用中集成并使用多种不同类型的数据库,例如 postgresql 和 mysql。文章涵盖了多数据源的配置、hibernate orm 多持久化单元的设置,以及如何将实体与特定数据库关联并进行数据持久化操作,旨在提供清晰的实践指导。
Quarkus 多数据源配置
Quarkus 框架原生支持在单个应用中配置和使用多个数据源,即使这些数据源是不同类型的数据库。这通过在 application.properties 文件中为每个数据源定义独立的配置前缀来实现。
首先,确保 pom.xml 中包含了相应数据库的 JDBC 驱动依赖。例如,对于 PostgreSQL 和 MySQL:
io.quarkus quarkus-jdbc-postgresql io.quarkus quarkus-jdbc-mysql
接着,在 application.properties 文件中为每个数据源指定配置。Quarkus 推荐使用 quarkus.datasource. 的命名约定。
# PostgreSQL 数据源配置quarkus.datasource.pg.db-kind=postgresqlquarkus.datasource.pg.username=pg_userquarkus.datasource.pg.password=pg_passwordquarkus.datasource.pg.jdbc.url=jdbc:postgresql://localhost:5432/pg_dbquarkus.datasource.pg.max-pool-size=10# MySQL 数据源配置quarkus.datasource.mysql.db-kind=mysqlquarkus.datasource.mysql.username=mysql_userquarkus.datasource.mysql.password=mysql_passwordquarkus.datasource.mysql.jdbc.url=jdbc:mysql://localhost:3306/mysql_dbquarkus.datasource.mysql.max-pool-size=10
在上述配置中,pg 和 mysql 是我们为各自数据源定义的逻辑名称。这些名称将在后续的持久化单元配置中被引用。
配置 Hibernate ORM 多持久化单元
仅仅配置了多个数据源不足以让 Hibernate ORM 知道如何将实体映射到特定的数据库。为此,我们需要为每个数据源定义一个独立的 Hibernate ORM 持久化单元 (Persistence Unit)。
每个持久化单元都需要通过 quarkus.hibernate-orm. 前缀进行配置,并明确关联到一个已定义的数据源。
# PostgreSQL 数据源的持久化单元quarkus.hibernate-orm.pg-unit.datasource=pgquarkus.hibernate-orm.pg-unit.packages=com.example.pg.entitiesquarkus.hibernate-orm.pg-unit.generate-ddl=true # 根据实体自动生成表结构# MySQL 数据源的持久化单元quarkus.hibernate-orm.mysql-unit.datasource=mysqlquarkus.hibernate-orm.mysql-unit.packages=com.example.mysql.entitiesquarkus.hibernate-orm.mysql-unit.generate-ddl=true # 根据实体自动生成表结构
这里,pg-unit 和 mysql-unit 是我们定义的持久化单元名称。datasource 属性将持久化单元与前面定义的数据源关联起来。packages 属性则指示 Hibernate ORM 扫描指定包下的实体类,将它们归属于当前持久化单元。通过 generate-ddl=true,Quarkus 会在应用启动时为每个持久化单元自动创建或更新其关联数据库中的表结构。
实体与持久化操作
为了将实体持久化到正确的数据库,我们需要确保:
实体类被正确地扫描并关联到相应的持久化单元。在执行持久化操作时,使用对应持久化单元的 EntityManager。
1. 实体类组织
建议将属于不同数据库的实体类放置在不同的 Java 包中,以便通过 quarkus.hibernate-orm..packages 进行精确控制。
无阶未来模型擂台/AI 应用平台
无阶未来模型擂台/AI 应用平台,一站式模型+应用平台
35 查看详情
例如:
com.example.pg.entities.PgProduct 对应 PostgreSQLcom.example.mysql.entities.MySqlOrder 对应 MySQL
// src/main/java/com/example/pg/entities/PgProduct.javapackage com.example.pg.entities;import io.quarkus.hibernate.orm.panache.PanacheEntity;import jakarta.persistence.Entity;import jakarta.persistence.Table;@Entity@Table(name = "products") // 明确表名public class PgProduct extends PanacheEntity { public String name; public double price; public PgProduct() { } public PgProduct(String name, double price) { this.name = name; this.price = price; }}
// src/main/java/com/example/mysql/entities/MySqlOrder.javapackage com.example.mysql.entities;import io.quarkus.hibernate.orm.panache.PanacheEntity;import jakarta.persistence.Entity;import jakarta.persistence.Table;@Entity@Table(name = "orders") // 明确表名public class MySqlOrder extends PanacheEntity { public String orderNumber; public int quantity; public MySqlOrder() { } public MySqlOrder(String orderNumber, int quantity) { this.orderNumber = orderNumber; this.quantity = quantity; }}
2. 使用特定持久化单元的 EntityManager
Quarkus 允许通过 @PersistenceContext 注解结合持久化单元名称来注入特定的 EntityManager。
import jakarta.enterprise.context.ApplicationScoped;import jakarta.inject.Inject;import jakarta.persistence.EntityManager;import jakarta.persistence.PersistenceContext;import jakarta.transaction.Transactional;import com.example.pg.entities.PgProduct;import com.example.mysql.entities.MySqlOrder;@ApplicationScopedpublic class MultiDbService { // 注入用于 PostgreSQL 的 EntityManager @Inject @PersistenceContext(unitName = "pg-unit") EntityManager pgEntityManager; // 注入用于 MySQL 的 EntityManager @Inject @PersistenceContext(unitName = "mysql-unit") EntityManager mysqlEntityManager; @Transactional public void createPgProduct(String name, double price) { PgProduct product = new PgProduct(name, price); pgEntityManager.persist(product); } @Transactional public void createMySqlOrder(String orderNumber, int quantity) { MySqlOrder order = new MySqlOrder(orderNumber, quantity); mysqlEntityManager.persist(order); }}
3. 使用 Panache ORM 进行操作
对于 Panache 用户,可以通过 Panache.using() 方法来指定操作的持久化单元,或者为每个持久化单元创建独立的 Panache Repository。
方法一:使用 Panache.using() 动态切换持久化单元
import io.quarkus.hibernate.orm.panache.Panache;import jakarta.enterprise.context.ApplicationScoped;import jakarta.transaction.Transactional;import com.example.pg.entities.PgProduct;import com.example.mysql.entities.MySqlOrder;@ApplicationScopedpublic class PanacheMultiDbService { @Transactional public void createPgProductWithPanache(String name, double price) { // 在 pg-unit 上下文中执行操作 Panache.using("pg-unit", () -> { PgProduct product = new PgProduct(name, price); product.persist(); // 此操作将使用 pg-unit 的 EntityManager }); } @Transactional public void createMySqlOrderWithPanache(String orderNumber, int quantity) { // 在 mysql-unit 上下文中执行操作 Panache.using("mysql-unit", () -> { MySqlOrder order = new MySqlOrder(orderNumber, quantity); order.persist(); // 此操作将使用 mysql-unit 的 EntityManager }); }}
方法二:为每个持久化单元创建独立的 Panache Repository
这种方法更适用于当您希望为每个数据库实体拥有独立的、类型安全的 Repository 接口时。
// src/main/java/com/example/pg/repositories/PgProductRepository.javapackage com.example.pg.repositories;import com.example.pg.entities.PgProduct;import io.quarkus.hibernate.orm.panache.PanacheRepository;import jakarta.enterprise.context.ApplicationScoped;import jakarta.persistence.PersistenceUnit;@ApplicationScoped@PersistenceUnit("pg-unit") // 指定此 Repository 关联的持久化单元public class PgProductRepository implements PanacheRepository { // 可以添加自定义查询方法}
// src/main/java/com/example/mysql/repositories/MySqlOrderRepository.javapackage com.example.mysql.repositories;import com.example.mysql.entities.MySqlOrder;import io.quarkus.hibernate.orm.panache.PanacheRepository;import jakarta.enterprise.context.ApplicationScoped;import jakarta.persistence.PersistenceUnit;@ApplicationScoped@PersistenceUnit("mysql-unit") // 指定此 Repository 关联的持久化单元public class MySqlOrderRepository implements PanacheRepository { // 可以添加自定义查询方法}
然后,您可以在服务中注入并使用这些 Repository:
import jakarta.enterprise.context.ApplicationScoped;import jakarta.inject.Inject;import jakarta.transaction.Transactional;import com.example.pg.repositories.PgProductRepository;import com.example.mysql.repositories.MySqlOrderRepository;@ApplicationScopedpublic class RepositoryMultiDbService { @Inject PgProductRepository pgProductRepository; @Inject MySqlOrderRepository mySqlOrderRepository; @Transactional public void createPgProductViaRepo(String name, double price) { PgProduct product = new PgProduct(name, price); pgProductRepository.persist(product); } @Transactional public void createMySqlOrderViaRepo(String orderNumber, int quantity) { MySqlOrder order = new MySqlOrder(orderNumber, quantity); mySqlOrderRepository.persist(order); }}
注意事项
事务管理: 默认情况下,Quarkus 的 @Transactional 注解管理的是当前线程的默认事务。当涉及多个数据库时,如果需要跨数据库的原子性操作(即分布式事务,XA 事务),会增加显著的复杂性,通常需要额外的配置和协调器。对于不要求强一致性的独立操作,使用各自数据库的本地事务通常是更简单且性能更好的选择。命名清晰: 为数据源和持久化单元选择清晰、有意义的名称(如 pg-unit, mysql-unit),有助于提高代码的可读性和可维护性。
以上就是在 Quarkus 应用中配置与管理多类型数据库持久化的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/314122.html
微信扫一扫
支付宝扫一扫