The @Multitenant
annotation specifies that a given entity is shared among multiple tenants of an application. The multitenant type specifies how the data for these entities are to be stored on the database for each tenant. Multitenancy can be specified at the entity or mapped superclass level.
Annotation Elements
Table 2-32 describes this annotation's elements.
Table 2-32 @Multitenant Annotation Elements
Annotation Element | Description | Default |
---|---|---|
|
Indicates if the database requires the tenant criteria to be added to the |
|
|
Specifies the multitenant strategy to use: |
|
Usage
To use the @Multitenant
annotation, include the annotation with an @Entity
or @MappedSuperclass
annotation. For example:
@Entity @Multitenant ... public class Employee() { ... }
Three types of multitenancy are available:
Example
Example 2-58 shows a simple example of a @Multitenant
annotation. In this example, the Player entity has rows for multiple tenants stored in its default PLAYER
table and that the default TENANT_ID
column is used as a discriminator along with the default context property eclipselink.tenant-id
.
Example 2-58 Minimal @Multitenant Annotation
@Entity @Multitenant public class Player { }
To have your application use a shared EntityManagerFactory
and have the EntityManager
be tenant specific, your runtime code might be:
Map<String, Object> emProperties = new HashMap<String, Object>(); emProperties.set("eclipselink.tenant-id", "HTHL"); EntityManager em = emf.createEntityManager(emProperties);
Review "Single-Table Multitenancy", "Table-Per-Tenanat Multitenancy", and "VPD Multitenancy" for more detailed examples.
The SINGLE_TABLE
multitenant type specifies that any table to which an entity or mapped superclass maps can include rows for multiple tenants. Access to tenant-specific rows is restricted to the tenant.
Tenant-specific rows are associated with the tenant by using tenant discriminator columns. The discriminator columns are used with application context values to limit what a persistence context can access.
The results of queries on the mapped tables are limited to the tenant discriminator value(s) provided as property values. This applies to all insert, update, and delete operations on the table. When multitenant metadata is applied at the mapped superclass level, it is applied to all subentities unless they specify their own multitenant metadata.
Note: In the context of single-table multitenancy, “single-table” means multiple tenants can share a single table, and each tenant's data is distinguished from other tenants' data via the discriminator column(s). It is possible to use multiple tables with single-table multitenancy; but in that case, an entity's persisted data is stored in multiple tables ( |
For more information how to use tenant discriminator columns to configure single-table multitenancy, see "@TenantDiscriminatorColumn".
The following example uses @Multitenant
, @TenantDiscriminatorColumn
, and a context property to define single-table multitenancy on an entity:
Example 2-59 Example Using @Multitenant
@Entity @Table(name=“EMP”) @Multitenant(SINGLE_TABLE) @TenantDiscriminatorColumn(name = “TENANT_ID”, contextProperty = "employee-tenant.id")
The following example uses the <multitenant>
element to specify a minimal single-table multitenancy. SINGLE_TABLE
is the default value and therefore does not have to be specified.
Example 2-60 Example Using <multitenant>
<entity class="model.Employee"> <multitenant/> <table name="EMP"/> ... </entity>
The TABLE_PER_TENANT
multitenant type specifies that the table(s) (Table
and SecondaryTable
) for an entity are tenant-specific tables based on the tenant context.. Access to these tables is restricted to the specified tenant. Relationships within an entity that use a join or collection table are also assumed to exist within that context.
As with other multitenant types, table-per-tenant multitenancy can be specified at the entity or mapped superclass level. At the entity level, a tenant context property must be provided on each entity manager after a transaction has started.
Table-per-tenant entities can be mixed with other multitenant-type entities within the same persistence unit.
All read, insert, update, and delete operations for the tenant apply only to the tenant's table(s).
Tenants share the same server session by default. The table-per-tenant identifier must be set or updated for each entity manager. ID generation is assumed to be unique across all the tenants in a table-per-tenant strategy.
To configure table-per-tenant multitenancy, you must specify:
A table-per-tenant property to identify the user. This can be set per entity manager, or it can be set at the entity manager factory to isolate table-per-tenant per persistence unit.)
A tenant table discriminator to identify and isolate the tenant's tables from other tenants' tables. The discriminator types are SCHEMA
, SUFFIX
, and PREFIX
. For more information about tenant discriminator types, see "@TenantTableDiscriminator".
The following example shows the @Multitenant
annotation used to define table-per-tenant multitenancy on an entity. @TenantTableDiscriminator(SCHEMA)
specifies that the discriminator table is identified by schema.
Example 2-61 Example Using @Multitenant with @TenantTableDiscriminator
@Entity @Table(name=“EMP”) @Multitenant(TABLE_PER_TENANT) @TenantTableDiscriminator(SCHEMA) public class Employee { ... }
The following example shows the <multitenant>
element and the <tenant-table-discriminator>
elements used to define a minimal table-per-tenant multitenancy.
Example 2-62 Example Using <multitenant> with <tenant-table-discriminator>
<entity class="Employee"> <multitenant type="TABLE_PER_TENANT"> <tenant-table-discriminator type="SCHEMA"/> </multitenant> <table name="EMP"> ... </entity>
The VPD
(Virtual Private Database) multitanancy type specifies that the database handles the tenant filtering on all SELECT, UPDATE and DELETE queries. To use this type, the platform used with the persistence unit must support VPD.
To use EclipseLink VPD multitenancy, you must first configure VPD in the database and then specify multitenancy on the entity or mapped superclass, using @Multitenant
and @TenantDiscriminatorColumn
:
Example 2-63 shows VPD multitenancy defined on an entity. As noted above, VPD in the database must also be configured to enable VPD multitenancy. In this case, the VPD database was configured to use the USER_ID column to restrict access to specified rows by specified clients. Therefore, USER_ID
is also specified as the tenant discriminator column for the EclipseLink multitenant operations.
@Entity @Multitenant(VPD) @TenantDiscriminatorColumn(name = "USER_ID", contextProperty = "tenant.id") @Cacheable(false) public class Task implements Serializable { ... ...
The following example shows...
Example 2-64 Example Using <multitenant>
<entity class="model.Employee"> <multitenant type="VPD"> <tenant-discriminator-column name="USER_ID" context-property="tenant.id"/> </multitenant> <table name="EMPLOYEE"/> ... </entity>
See Also
"Using Multitenancy" in Solutions Guide for EclispeLink
Multitenant Examples at http://wiki.eclipse.org/EclipseLink/Examples/JPA/Multitenant