首页 > 解决方案 > 在 Micronaut 中获取多个数据源的 EntityManager 的特定实例

问题描述

我对 Micronaut 应用程序的 application.yml 中的两个不同数据源有以下定义 -

datasources:
  default:
    url: <jdbc-url>
    driverClassName: org.postgresql.Driver
    username: <username>
    password: <password>
    dialect: POSTGRES
    schema: <schema>
  ms-sql:
    url: <jdbc-url>
    driverClassName: com.microsoft.sqlserver.jdbc.SQLServerDriver
    username: <username>
    password: <password>
    dialect: org.hibernate.dialect.SQLServer2012Dialect
    schema: <schema>

如何在下面的服务类中注入 EntityMananger 的特定实例?

服务类片段:

@Inject
private EntityManager em;

@Transactional
@Override
public int callSP(int num) {
    StoredProcedureQuery query = em.createStoredProcedureQuery("storelist.testSP1")
                                    .registerStoredProcedureParameter("InputInt", Integer.class, ParameterMode.IN)
                                    .registerStoredProcedureParameter("OutputInt", Integer.class, ParameterMode.OUT)
                                    .setParameter("InputInt", num);
    query.execute();
    Integer result = (Integer) query.getOutputParameterValue("OutputInt");
    
    return result;
}

标签: javajpadatasourcemicronautmicronaut-data

解决方案


对于每个DataSource配置(也注入到由DataSourceConfiguration驱动的 bean ConfigurationProperties),Micronaut将创建一个合格的SessionFactorybean。

在下面,每个合格SessionFactory的都会导致一个TransactionManager合格的 bean 创建。

根据io.micronaut.context.annotation.EachBean注入机制,创建的每个 bean 都将@Named位于驱动其创建的 bean 限定名称之后。

从配置到创建 bean 的短注入路径如下:

datasources.some-datasource-name (configuration item within your .yaml, .properties...)
              |
              |
              v
    DataSourceConfiguration @Named("some-datasource-name")
              |
              |
              v
         DataSource @Named("some-datasource-name")
              |
              |
              v
        SessionFactory @Named("some-datasource-name")
              |
              |
              v
      TransactionManager @Named("some-datasource-name")
              |
              |
              v
     RepositoryOperations @Named("some-datasource-name")

然后,您将不得不以TransactionManager编程方式使用限定符和事务感知 EntityManager来执行JPA操作(请注意,@Transactional在编程事务样式中不再需要注释):

@Singleton
public class MyServiceImpl implements MyService {

    private EntityManager em; // transaction-aware bean

    private final SynchronousTransactionManager<Connection> transactionManager;

    public MyServiceImpl(@NonNull EntityManager entityManager, @NonNull @Named("ms-sql") SynchronousTransactionManager<Connection> transactionManager) {
        this.em = entityManager;
        this.transactionManager = transactionManager;
    }

    @Override
    public int callSP(int num) {
        return transactionManager.executeRead(status -> {
            StoredProcedureQuery query = em.createStoredProcedureQuery("storelist.testSP1")
                    .registerStoredProcedureParameter("InputInt", Integer.class, ParameterMode.IN)
                    .registerStoredProcedureParameter("OutputInt", Integer.class, ParameterMode.OUT)
                    .setParameter("InputInt", num);
            query.execute();    
            return (Integer) query.getOutputParameterValue("OutputInt");
        });
    }
}

或者注入一个合格的RepositoryOperations,这将是HibernateJpaOperations你的情况的一个实例,并用它来查询你的数据源。


推荐阅读