[转载]数据层的多租户浅谈

原文:http://www.ibm.com/developerworks/cn/java/j-lo-dataMultitenant/index.html

 

以高达一致篇“浅析多租户当 Java 平台与一些 PaaS
上的实现”遭我们提到了使用规模的多租户架构,涉及到
PaaS、JVM、OS 等,与之对应的凡数据层也闹差不多租户的支持。

数据层的多租户综述

多租户(Multi Tenancy/Tenant)是同种植软件架构,其定义是:

以相同尊服务器上运行单个应用实例,它吗多个租户提供劳动。

在SaaS实施过程遭到,有一个引人注目的勘查点,就是什么样对下数据进行规划,以支撑多租户,而这种规划的笔触,是设以数额的共享、安全隔离和总体性间取得平衡。

污染
统的施用,仅仅服务为单个租户,数据库多配备在柜中网络环境,对于数据拥有者来说,这些数量是协调“私有”的,它可自己所定义的凡事安然无恙规范。而于
云计算时,随着以本身让放到云端,导致数据层也每每于公开化,但租户对数码安全性的要求,并无因的下降。同时,多租户应用在租户数量净增的状态下,会
比单租户应用面临更多的习性压力。本文就针对是主题展开探索:多租户在数据层的框架如何当共享、安全与性间进行抉择,同时询问一下市场上有的周边的数量
厂商怎样贯彻即片情节。

回页首

大面积的老三种植模式

每当 MSDN 的即刻首文章 Multi-Tenant Data
Architecture
中,系统的下结论了数据层的老三栽多租户架构:

  1. 独自数据库
  2. 共享数据库、独立 Schema
  3. 共享数据库、共享 Schema、共享数据表

独立数据库是一个租户独享一个数据库实例,它提供了极度强的分离度,租户的数码交互物理不可见,备份与回复都生灵活;共享数据库、独立
Schema 将每个租户关联到和一个数据库的不比
Schema,租户间数交互逻辑不可见,上层应用程序的落实同独门数据库一样简单,但备份恢复稍显复杂;
最后一栽模式则是租户数据在数据表级别实现共享,它提供了低于的本金,但引入了额外的编程复杂性(程序的多少访问需要因此
tenantId
来分不同租户),备份与还原为再次扑朔迷离。这三种模式的性状可以就此相同摆设图来概括:

图 1. 叔栽配备模式之异同

图片 1

直达图所总结的是屡见不鲜的定论,而以常规场景下需要综合考虑才能够决定那种方式是相当的。例如,在挤占资金高达,认为独立数据库会强,共享模式于逊色。但万一设想到那个租户潜在的数量扩展需求,有时可能会发相反的成本耗用结论。

倘多租户采用的挑,主要是资本由,对于绝大多数观而言,共享度越强,软硬件资源的利用效率更好,成本为重新低。但又也如解决好租户资源共享与隔离带来的安以及特性、扩展性等问题。毕竟,也有客户无法满意为以数据及其他租户放在共享资源中。

手上市场上各类数据厂商在多租户的支撑及,大抵都是按上文所陈述之立即几乎近似模式,或者夹杂了几乎种植政策,这有些情节将以脚介绍。

回页首

JPA Provider

JSR 338 定义了 JPA 规范 2.1,但若是我辈早已了解及的,Oracle
把多租户的绝大多数特性推迟到了 Java EE 8 中。尽管这些已经当 JavaOne
大会备受出了演示,但不论在 JPA 2.0(JSR 317)还是 2.1
规范着,都仍没有公开提及多租户。不过就并无伤一些 JPA provider
在马上部分领域的落实,Hibernate 和 EclipseLink
已提供了任何还是有的多租户数据层的化解方案。

Hibernate 是今日最流行的开源之目标关联映射(ORM)实现,并能够很好地及
Spring 等框架集成,目前 Hibernate 支持多租户的独自数据库和独立 Schema
模式。EclipseLink 也是企业级数据持久层JPA标准的参照实现,对时 JPA2.1
完整支持,在手上 JPA
标准尚未引入多租户概念之际,已针对性多租户支持完全,其前身是生已经老、功能丰富的靶子关系映射工具
Oracle TopLink。因此本文采用 Hibernate 和 EclipseLink
对多租户数据层进行剖析。

回页首

Hibernate

Hibernate 是一个绽放源代码的对象/关系映射框架和查询服务。它对 JDBC
进行了轻量级的目标封装,负责从 Java 类映射到数码库表,并打 Java
数据类型映射到 SQL 数据类型。在 4.0 版本 Hibenate
开始支持多租户架构——对两样租户使用独立数据库或独立 Sechma,并计划在 5.0
中支持共享数据表模式。

以 Hibernate 4.0 中之多租户模式发生三栽,通过 hibernate.multiTenancy
属性有下几乎种植配备:

  • NONE:非多租户,为默认值。
  • SCHEMA:一个租户一个 Schema。
  • DATABASE:一个租户一个 database。
  • DISCRIMINATOR:租户共享数据表。计划以 Hibernate5 中落实。

模式1:独立数据库

比方是单独数据库,每个租户的数额保存在大体及单独的数据库实例。JDBC
连接将本着具体的每个数据库,一个租户对应一个数据库实例。在 Hibernate
中,这种模式可以由此实现 MultiTenantConnectionProvider 接口或累
AbstractMultiTenantConnectionProvider
类等办法来贯彻。三栽模式中它的共享性最低,因此本文重点讨论以下简单种植模式。

模式 2:共享数据库,独立 Schema

于共享数据库,独立
Schema。所有的租户共享一个数据库实例,但是她们所有独立的 Schema 或
Catalog,本文将为多租赁家酒店管理网啊案例证明 Hibernate
对多租户的支撑以及用利用方法。

图 2. guest 表结构

图片 2

这是酒店客户信息表,我们特因为此表对这种模式展开说明,使用相同的申结构于
MySQL 中开创 DATABASE hotel_1 和 hotel_2。基于 Schema
的多租户模式,需要以 Hibernate 配置文件 Hibernate.cfg.xml 中装置
hibernate.multiTenancy 等有关属性。

清单 1. 配置文件 Hibernate.cfg.xml
<session-factory>
<property name="connection.url">
    jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&amp;characterEncoding=utf8
</property>
<property name="connection.username">root</property>
<property name="connection.password"></property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="dialect">org.hibernate.dialect.MySQLInnoDBDialect</property>
<property name="hibernate.connection.autocommit">false</property>
<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="show_sql">false</property>

<property name="hibernate.multiTenancy">SCHEMA</property>
<property name="hibernate.tenant_identifier_resolver">
     hotel.dao.hibernate.TenantIdResolver
</property>
<property name="hibernate.multi_tenant_connection_provider">
     hotel.dao.hibernate.SchemaBasedMultiTenantConnectionProvider
</property>

<mapping class="hotel.model.Guest" />
</session-factory>

<hibernate.tenant_identifier_resolver> 属性规定了一个合约,以要
Hibernate 能够分析出用时的 tenantId,该类必须兑现
CurrentTenantIdentifierResolver 接口,通常咱们可于报到信息遭受收获
tenatId。

清单 2. 获得当前 tenantId
public class TenantIdResolver implements CurrentTenantIdentifierResolver {
    public String resolveCurrentTenantIdentifier() {
        return Login.getTenantId();
    }
}

< hibernate.multi_tenant_connection_provider> 属性指定了
ConnectionProvider,即 Hibernate
需要懂得怎样为租户特有的道获取数据连接,SchemaBasedMultiTenantConnectionProvider
类实现了MultiTenantConnectionProvider 接口,根据 tenantIdentifier
获得对应的连天。在实际使用中,可构成使用 JNDI DataSource
技术得到连接为增强性能。

清单 3. 以租户特有的点子获取数据库连接
public class SchemaBasedMultiTenantConnectionProvider 
  implements MultiTenantConnectionProvider, Stoppable,
        Configurable, ServiceRegistryAwareService {

    private final DriverManagerConnectionProviderImpl connectionProvider 
         = new DriverManagerConnectionProviderImpl();
    @Override
    public Connection getConnection(String tenantIdentifier) throws SQLException {
        final Connection connection = connectionProvider.getConnection();
        connection.createStatement().execute("USE " + tenantIdentifier);

        return connection;
    }

    @Override
    public void releaseConnection(String tenantIdentifier, Connection connection)
 throws SQLException {
        connection.createStatement().execute("USE test");       
        connectionProvider.closeConnection(connection);
    }
    ……  
}

和表 guest 对应之 POJO 类 Guest,其中主要是一对 getter 和 setter方法。

清单 4. POJO 类 Guest
@Table(name = "guest")
public class Guest {

    private Integer id;
    private String name;
    private String telephone;
    private String address;
    private String email;

    //getters and setters
        ……  
}

咱用 ServiceSchemaBasedMain.java
来进展测试,并使了有些数为便于演示,如当起不同租户的总指挥登录后各自展开补给加客户之操作。

清单 5. 测试类 ServiceSchemaBasedMain
public class ServiceSchemaBasedMain {

    public static void main(String[] args) {
        Session session = null;
        Guest guest =null;
        List<Guest> list = null;
        Transaction tx = null;

        System.out.println("======== 租户 hotel_1 ========");
        Login.setTenantId("hotel_1");
        session = sessionFactory.openSession();
        tx = session.beginTransaction();
        guest = new Guest();
        guest.setName("张三");
        guest.setTelephone("56785678");
        guest.setAddress("上海市张扬路88号");
        guest.setEmail("zhangsan@gmail.com");
        session.saveOrUpdate(guest);
        list = session.createCriteria(Guest.class).list();
        for (Guest gue : list) {
            System.out.println(gue.toString());
        }
        tx.commit();
        session.close();


        System.out.println("======== 租户 hotel_2 ========");
        Login.setTenantId("hotel_2");
        session = sessionFactory.openSession();
        tx = session.beginTransaction();
        guest = new Guest();
        guest.setName("李四");
        guest.setTelephone("23452345");
        guest.setAddress("上海市南京路100号");
        guest.setEmail("lisi@gmail.com");
        session.saveOrUpdate(guest);
        list = session.createCriteria(Guest.class).list();
        for (Guest gue : list) {
            System.out.println(gue.toString());
        }
        tx.commit();
        session.close();
    }
}
清单 6. 运行程序 ServiceSchemaBasedMain 的出口
======== 租户 hotel_1 ========
Guest [id=1, name=Victor, telephone=56008888, address=上海科苑路399号, email=vic@gmail.com]
Guest [id=2, name=Jacky, telephone=66668822, address=上海金科路28号, email=jacky@sina.com]
Guest [id=3, name=张三, telephone=56785678, address=上海市张扬路88号, email=zhangsan@gmail.com]
======== 租户 hotel_2 ========
Guest [id=1, name=Anton, telephone=33355566, address=上海南京路8号, email=anton@gmail.com]
Guest [id=2, name=Gus, telephone=33355566, address=北京大道3号, email=gus@yahoo.com]
Guest [id=3, name=李四, telephone=23452345, address=上海市南京路100号, email=lisi@gmail.com]

模式3:共享数据库、共享 Schema、共享数据表

每当这种景象下,所有租户共享数据表存放数据,不同租户的数码经过 tenant_id
鉴别器来分别。但眼下底 Hibernate 4 还未支持是差不多租户鉴别器策略,要当
5.0 才支撑。但咱是否出可选的代方案吧?答案是采用 Hibernate Filter.

为区别多只租户,我于 Schema 的每个数据表需要添加一个字段 tenant_id
因判断数据是属哪个租户的。

图 3. 共享 Schema、共享数据表案例 E-R 图

图片 3

据悉达图在 MySQL 中创造 DATABASE hotel。

咱俩于 OR-Mapping 配置文件被使用了 Filter,以便在开展数量查询时,会因
tenant_id 自动查询有拖欠租户所持有的数额。

清单 7. 对象关联映射文件 Room.hbm.xml

点击查看代码清单

属下去我们以 HibernateUtil 类中经 ThreadLocal 存放和收获 Hibernate
Session,并拿用户登录信息遭的 tenantId 设置也 tenantFilterParam
的参数值。

清单 8. 拿走 Hibernate Session 的家伙类 HibernateUtil

点击查阅代码清单

但是 Filter 只是推进我们读取数据时展示地忽视掉
tenantId,但当开展多少插入的下,我们要不得不显式设置相应 tenantId
才能够进行持久化。这种情景只能于 Hibernate5 版本被获根本转。

清单 9. 运转程序 HotelServiceMain 输出

点击查看代码清单

大抵租户下的 Hibernate 缓存

依据独立 Schema 模式的多租户实现,其数据表无需附加的 tenant_id。通过
ConnectionProvider 来取得所急需的 JDBC 连接,对那个来说一级缓存(Session
级别的缓存)是安之可用之,一级缓存对事物级别之多少开展缓存,一旦事物了,缓存也尽管失效。但是该模式下之二级缓存是勿安全的,因为多个
Schema 的数据库的主键可能会见是跟一个价,这样便叫 Hibernate
无法正常下二级缓存来存放在对象。例如:在 hotel_1 的 guest 表中产生个 id
为 1 的数额,同时在 hotel_2 的 guest 表中吗有一个 id 为 1
的数目。通常我会根据 id 来覆盖类的 hashCode()
方法,这样一旦应用二级缓存,就无法区分 hotel_1 的 guest 和 hote_2 的
guest。

于共享数据表的模式下之缓存, 可以又使 Hibernate的一级缓存和二级缓存,
因为在共享的数表中,主键是绝无仅有的,数据表中的各条记下属于对应的租户,在二级缓存中之对象为不无唯一性。Hibernate
分别吗 EhCache、OSCache、SwarmCache 和 JBossCache 等缓存插件提供了内置的
CacheProvider 实现,读者可以根据需要选择成立的缓存,修改 Hibernate
配置文件设置并启用其,以增长多租户应用之习性。

回页首

EclipseLink

EclipseLink 是 Eclipse 基金会管理下之开源持久层服务项目,为 Java
开发人员与各种数据服务(比如:数据库、web
services、对象XML映射(OXM)、企业信息体系(EIS)等)交互提供了一个可是扩大框架,目前支持之持久层标准中概括:

  • Java Persistence API (JPA)
  • Java Architecture for XML Binding (JAXB)
  • Java Connector Architecture (JCA)
  • Service Data Objects (SDO)

EclipseLink 前身是 Oracle TopLink, 2007年 Oracle 将后者绝大部分输给了
Eclipse 基金会,次年 EclipseLink 被 Sun 挑选成为 JPA 2.0 的参照实现。

注: 目前 EclipseLink2.5 完全支持 2013 年发布之 JPA2.1(JSR 338) 。

于一体化兑现 JPA 标准外,针对 SaaS 环境,在差不多租户的断者 EclipseLink
提供了酷好的支撑与活地化解方案。

应用程序隔离

  • 隔断的器皿/应用服务器
  • 共享容器/应用服务器的应用程序隔离
  • 同应用程序外之共享缓存但隔离的 entity manager factory
  • 共享的 entity manager factory 但各隔离的 entity manager

数码隔离

  • 隔断的数据库
  • 隔离的Schema/表空间
  • 断的表明
  • 共享表但隔离的施行
  • 查询过滤
  • Oracle Virtual Private Database (VPD)

对此多租户数据源隔离主要发生以下方案

  • Single-Table Multi-tenancy,依靠租户区分列(tenant discriminator
    columns)来隔离表的尽,实现多租户共享表。
  • Table-Per-Tenant Multi-tenancy,依靠表底租户区分(table tenant
    discriminator)来隔离表,实现一租户一个阐明,大体类似于上文的共享数据库独立Schema模式。
  • Virtual Private Database(VPD ) Multi-tenancy,依靠 Oracle VPD
    自身之平安访问策略(基于动态SQL where子句特性),实现多租户共享表。

本节第一介绍多租户在 EclipseLink
中的共享数据表和一租户一个表明底落实方式,并为坐酒店大多租户使用之例证展现共享数据表方案的现实性实施。

EclipseLink Annotation @Multitenant

及 @Entity 或 @MappedSuperclass
一起行使,表明它在一个应用程序中于多租户共享, 如清单 10。

清单10. @Multitenant
@Entity
@Table(name="room")
@Multitenant
...
publicclass Room {
}
表 1. Multitenant 暗含两个属性
Annotation 属性 描述 缺省值
boolean includeCriteria 是否将租户限定应用到 select、update、delete 操作上 true
MultitenantType value 多租户策略,SINGLE_TABLE,
TABLE_PER_TENANT, VPD.
SINGLE_TABLE

共享数据表(SINGLE_TABLE)

  1. Metadata配置

赖租户区分列修饰符 @TenantDiscriminatorColumn 实现。

清单11. @TenantDiscriminatorColumn
@Entity
@Table(name="hotel_guest")
@Multitenant(SINGLE_TABLE)
@TenantDiscriminatorColumn(name="tenant_id", contextProperty="tenant.id")
publicclass HotelGuest {
}

或以EclipseLink描述文件orm.xml定义对象与表映射时进行界定,两者是齐价格的。

清单12. orm.xml
<entity class="mtsample.hotel.model.HotelGuest">
  <multitenant>
    <tenant-discriminator-column name="tenant_id" context-property="tenant.id"/>
  </multitenant>
  <table name="HotelGuest"/>
  ...
</entity>
  1. 特性配置

租户区分列定义好后,在运行时环境亟待安排具体属性值,以确定当前操作环境所属的租户。

其三栽方式的性配置,按先生效顺序排序如下

  1. EntityManager(EM)
  2. EntityManagerFactory(EMF)
  3. Application context (when in a Java EE container)

比如说 EntityManagerFactory 可以间接通过以 persistence.xml
中布局持久化单元(Persistence Unit)或直接传属性参数为初始化时
EntityManagerFactory。

清单 13. 配置 persistence.xml
<persistence-unit name="multi-tenant">
  ...
  <properties>
    <property name="tenant_id" value="开发部"/>
    ...
  </properties>
</persistence-unit>

或者

清单 14. 初始化 EntityManagerFactory

点击查看代码清单

本共享粒度可以发如下区分,

  • EntityManagerFactory 级别

用户需通过 eclipselink.session-name
提供单身的对话名,确保每个租户占有独立的对话和缓存。

清单 15. 吗 EntityManagerFactory 配置会话名

点击查阅代码清单

  • 共享的 EntityManagerFactory 级别

EntityManagerFactory 的默认模式, 此级别缺省配置为独立二级缓存(L2
cache), 即每个 mutlitenant 实体缓存设置也 ISOLATED,用户为不过装
eclipselink.multitenant.tenants-share-cache 属性为真为共享,此时多租户
Entity 缓存设置为 PROTECTED。

这种级别下,一个移动之 EntityManager 不可知换 tenantId。

  • EntityManager 级别

这种级别下,共享 session,共享 L2 cache,
用户需要好设置缓存策略,以安哪些租户信息是不克以二级缓存共享的。

清单 16. 安缓存

点击查看代码清单

一律,一个活动的EntityManager不能更换tenant ID。

几乎沾说明:

  • 每个表底界别列好来擅自多独,使用修饰符
    TenantDiscriminatorColumns。
清单 17. 多单分区列
@TenantDiscriminatorColumns({
@TenantDiscriminatorColumn(name="tenant_id", contextProperty="tenant.id"),
@TenantDiscriminatorColumn(name = "guest_id", contextProperty="guest.id")
})
  • 租户区分列的名字跟相应的光景文属性名可以取任意值,由应用程序开发者设定。
  • 转移的 Schema 可以吗得以无含租户区分列,如 tenant_id 或
    guest_id。
  • 租户区分列可以投到实体对象呢堪免。

顾:当映射的下,实体对象相应的属性必须标记为特念(insertable=false,
updatable=false),这种限制令区分列非可知同日而语实体表的 identifier。

  • TenantDiscriminatorColumn为以下 EntityManager 的操作与询问支持:

persist,find,refresh,named queries,update all,delete all 。

一租户一表(TABLE_PER_TENANT )

这种多租户类型使每个租户的多寡好占据专属它好之一个要多个说明,多租户间的这些发明得共享相同
Schema
也可是应用不同的,前者采用前缀(prefix)或后缀(suffix)命名模式之发明的租户区分符,后者以租户专属的
Schema 名来定义表的租户区分符。

  1. Metadata配置

仰数据表的租户区分修饰符 @TenantTableDiscriminator 实现

清单 18.
@Entity
@Table(name=“CAR”)
@Multitenant(TABLE_PER_TENANT)
@TenantTableDiscriminator(type=SCHEMA, contextProperty="eclipselink-tenant.id")
public class Car{
}

清单 19.
<entity class="Car">
  <multitenant type="TABLE_PER_TENANT">
    <tenant-table-discriminator type="SCHEMA" context-property="eclipselink.tenant-id"/>
  </multitenant>
  <table name="CAR">
</entity>

如前所述,TenantTableDiscriminatorType有 3 种类型:SCHEMA、SUFFIX 和
PREFIX。

  1. 性配置

同另外两栽多租户类型一样,默认情况下,多租户共享EMF,如不思量共享
EMF,可以透过部署 PersistenceUnitProperties.MULTITENANT_SHARED_EMF
以及 PersistenceUnitProperties.SESSION_NAME 实现。

清单 20.

点击查阅代码清单

要以 persistence.xml 配置属性。

酒吧大多租户使用实例(EclipseLink 共享(单)表)

数据库 Schema 和测试数据与上文 Hibernate 实现均等,关于目标关联映射(OR
mapping)的布局都采用 JPA 和 EclipseLink 定义的 Java Annotation 描述。

至于几只基本操作

  1. 加上一个目标实例, 利用EntityManager.persist()
清单 21. 添加
public <T> void save(T t) {
        em.persist(t);
    }
    public <T> void saveBulk(List<T> bulk) {
        for(T t:bulk){
            em.persist(t);
        }
    }
  1. 履新一个靶实例, 利用EntityManager.merge()
清单 22. 更新
public <T> void update(T t){
        em.merge(t);
    }
  1. 查询, 利用EntityManager的NamedQuery,
清单 23. 多规格多结果查询

点击查阅代码清单

如若用 JPQL 实现则示例如下:

清单 24. JPQL NamedQuery 定义

点击查阅代码清单

一些测试数据如下(MySQL):

hotel_admin

图片 4

hotel_guest

图片 5

room

图片 6

运转附件 MT_Test_Hotels.zip 中的测试代码(请参见
readme)来瞧多租户的组成部分一流场景。

清单 25. 运作测试代码

点击查看代码清单

可知获得输出片段如下:

清单 26. 输出

点击查阅代码清单

经共享表的测试数据及运行结果好见到,对于多只例外之租户(hotel_admin),在抬高、查找、更新操作没有出示声明租户标识的图景下,EntityManager
可以因自家之租户属性配置

落实租户分离。在按部就班实例,EntityManager 初始化时采取到 hotel_admin
登录后的对话上下文进行租户判断,这里不再赘述。

注:上文中提及的凡事源码都可以于附件面临找到。

回页首

外方面的考虑

数据备份

单身数据库与独立Sechma的模式,为每个租户备份数据比易于,因为她俩存放于不同之数量表中,只需要对普数据库或全Schema进行备份。


共享数据表的模式下,可以以有租户的多少并备份,但是如果一旦吧某某一个租户要以租户分开进行数据备份,就会见比麻烦。通常需要另外写sql脚论根据
tenant_id来赢得相应的数额然后还备份,但是如果以租户来导入的语句还比辛苦,所以必需时还是内需备份所有并为事后导入好。

性能

独自数据库:性能大,但价格也强,需要占用资源多,不可知共享,性价比没有。

共享数据库,独立 Schema:性能中等,但价格相当,部分共享,性价比中。

共享数据库,共享 Schema,共享数据表:性能中等(可使 Cache
可以提高性能),但价格便宜,完全共享,性价比大。如果当少数表中来大气底数,可能会见指向所有租户产生性能影响。

对于共享数据库的事态下,如果坐太多的最终用户同时做客数据库而招致应用程序性能问题,可以设想数据表分区等数据库端的优化方案。

经济考虑

以支持多租户应用,共享模式的应用程序往往比较下独立数据库模式的应用程序相对复杂,因为支付一个共享的架构,导致在应用设计上得费较生之不竭,因而起成本会较高。然而,共享模式之运用在营业成本上往往要小有,每个租户所花费之花费为会见比低。

回页首

结束语

多租户数据层方案的挑是一个归结的勘察过程,包括资金、数据隔离和维护、维护、容灾、性能相当于。但无论怎样选择,OR-Mapping
框架对多租户的支撑用巨的解放开发人员的行事,从而得以重新多小心于应用逻辑。最后我们因为一个
Hibernate 和 EclipseLink 的比较来终结本文。

表 2. Hibernate 同 EclipeLink 对多租户支持之于
  Hibernate EclipseLink
独立数据库 支持,通过实现 MultiTenantConnectionProvider 接口以连接独立的数据库 支持,为每个租户配置独立的 EntityManagerFactory
共享数据库,独立 Schema 支持,通过实现 MultiTenantConnectionProvider 接口以切换 Schema 支持,使用 TABLE_PER_TENANT MultitenantType 以及 SCHEMA TenantTableDiscriminatorType
共享数据库,共享 Schema,共享数据表 多租户 Discriminator 计划在 Hibernate 5.0 支持 支持, 使用 SINGLE_TABLE MultitenantType 以及 TenantDiscriminatorColumn

相关文章