【问题标题】:Dynamic dialect with Hibernate and Hikari使用 Hibernate 和 Hikari 的动态方言
【发布时间】:2021-09-27 15:58:37
【问题描述】:

我是 Hibernate 的新手。 在我的代码中,与 DB 的连接由 Hikari 数据源管理。

我的代码现在是多租户的,但它为所有租户管理相同的休眠方言。

是否可以创建每个租户可以使用不同方言的配置? 方言的类型可以作为租户的属性提供。


这是 entityManagerFactory 的示例:

     @Bean
     public LocalContainerEntityManagerFactoryBean entityManagerFactory() {

        Map<String, Object> jpaProperties = new HashMap<>();
        jpaProperties.put(..., ...);
        jpaProperties.put(org.hibernate.cfg.Environment.DIALECT, "myDialect");
        
        LocalContainerEntityManagerFactoryBean emfBean = new LocalContainerEntityManagerFactoryBean();
        emfBean.setPackagesToScan(new String[] {MyEntity.class.getPackage().getName()});
        emfBean.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        emfBean.setJpaPropertyMap(jpaProperties);
        return emfBean;
    }

编辑

我正在寻找这个solution:它建议为每种方言创建一个重复的 LocalContainerEntityManagerFactoryBean。 我不明白的是,我如何判断何时使用一个 EntityManager (MySQL) 和另一个 (Postgres 或 MsSQL):solution 区分实体(每个实体都有自己的数据库)但在我的情况下,所有实体在所有数据库上。是歧视的租户。

例如:如果我创建了第二个 LocalContainerEntityManagerFactoryBean 实例(即 msSQLEntityManagerFactory())并设置了 SQL Server 方言,则应用程序无法启动:

Application failed to start due to an exceptionorg.springframework.beans.factory.NoUniqueBeanDefinitionException:
 No qualifying bean of type 'javax.persistence.EntityManagerFactory' available:
 expected single matching bean but found 2: 
msSQLEntityManagerFactory,entityManagerFactory

【问题讨论】:

  • 多租户代码是什么意思?
  • 我有一个一体化架构:同一个软件实例和同一个 MySQL 可以用于不同的租户。每个租户由一个输入参数标识,该参数映射到一组配置(例如:租户数据库的凭据和 URL)。每个租户只能用于连接到其数据库(但所有租户都在同一个 MySQL 实例上。将来,我希望在 MySQL 上拥有一个租户,在 PostgresSQL 上拥有一个租户,在 SQL Server 上拥有一个租户,但都在软件的相同实例。
  • 对不起,我仍然很难理解多租户代码。也许您需要将方言放入属性文件中,将此属性文件作为属性源添加到 spring 的环境抽象中,然后在配置类中结合使用 PropertySourcesPlaceholderConfigurer 和 Value 注释来设置适当的方言。然后对于每个租户,您将拥有不同的属性文件。
  • 我不明白...如何动态设置方言?软件的同一个实例如何从一个切换到另一个?
  • 在你的程序中什么时候需要改变方言?如果您的程序同时使用多个数据库,那么也许您可以使用不同的方言为每个数据库声明 EntityManager。

标签: java spring hibernate hikaricp dialect


【解决方案1】:

这实际上是不可能的,因为方言会影响某些引用规则等,您不能在运行时根据租户标识符“交换”这些规则。只需创建两个持久性单元,每个都指向每种数据库类型的不同数据源。您将不得不根据您的租户标识符以某种方式查找适当的EntityManager/EntityManagerFactory,这使得当您想要使用 Spring Data JPA 时变得更加困难,因为这需要实体管理器工厂的编译静态名称引用。也许您可以创建一个自定义EntityManagerFactory,它将所有方法调用委托给基于租户标识符的适当实例。总的来说,这并不容易,您可能需要进行大量的试验和错误。

IMO 如果可能的话,最好根据数据库类型进行单独的应用程序部署和单独的配置。

【讨论】:

    【解决方案2】:

    我终于设法找到了解决这个问题的方法。 通过为每种方言(在本例中为 MySQL、Postgres 和 MS SQL Server)建立一个实体管理器工厂,我设法解决了方言的问题。

    为 EntityManagerFactory 创建一个 bean 并返回该接口的代理,并在处理程序中,根据您的逻辑,您可以切换使用哪个 emf 以适合使用的数据源。

    我为此制作了一个视频,因为似乎没有在线文档。

    Session Scoped Connection

    这与您尝试实现的目标非常相似,但在我的情况下,用户正在提供凭据,因此更加复杂。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-17
      • 1970-01-01
      • 2013-08-04
      • 2011-09-05
      相关资源
      最近更新 更多