14 Tenant Isolation Using EclipseLink
14.2 Using Single-Table Multi-Tenancy
14.2.1 Main Tasks for Using Single-Table Multi-Tenancy
14.2.1.3 Task 3: Specify Tenant Discriminator Columns
Discriminator columns are used together with an associated application context to indicate which rows in a table an application tenant can access.
Tenant discriminator columns can be specified declaratively using the
@TenantDiscriminatorColumn annotation or in an object-relational (ORM) XML file using the <tenant-discriminator-column> element.
The following characteristics apply to discriminator columns:
■ Tenant discriminator column(s) must always be used with @Multitenant (or
<multitenant> in the ORM XML file). You cannot specify the tenant discriminator column(s) only.
■ The tenant discriminator column is assumed to be on the primary table unless another table is explicitly specified.
■ On persist, the values of tenant discriminator columns are populated from their associated context properties.
■ When a multi-tenant entity is specified, the tenant discriminator column can default. Its default values are:
– Name = TENANT_ID (the database column name)
– Context property = eclipselink.tenant.id (the context property used to populate the database column)
■ Tenant discriminator columns are application definable. That is, the discriminator column is not tied to a specific column for each shared entity table. You can use TENANT_ID, T_ID, etc.
■ There is no limit on the number of tenant discriminator columns an application can define.
■ Any name can be used for a discriminator column.
■ Generated schemas include specified tenant discriminator columns.
■ Tenant discriminator columns can be mapped or unmapped:
– When a tenant discriminator column is mapped, its associated mapping attribute must be marked as read only.
– Both mapped and unmapped properties are used to form the additional criteria when issuing a SELECT query.
14.2.1.3.1 Use the @TenantDiscriminatorColumn Annotation To use the
@TenantDiscriminatorColumn annotation, include it with @Multitenant annotation on an entity or mapped superclass, and optionally include the name and contextProperty attributes. If you do not specify these attributes, the defaults name = "TENANT-ID" and contextProperty = "eclipselink.tenant-id" are used.
For example:
@Entity
@Multitenant(SINGLE_TABLE)
@TenantDiscriminatorColumn(name = "TENANT", contextProperty = "multitenant.id") public class Employee {
}
To specify multiple tenant discriminator columns, include multiple
@TenantDiscriminatorColumn annotations within the @TenantDiscriminatorColumns
Using Single-Table Multi-Tenancy
Tenant Isolation Using EclipseLink 14-5 annotation, and include the table where the column is located if it is not located on the primary table. For example:
@Entity
@Table(name = "EMPLOYEE")
@SecondaryTable(name = "RESPONSIBILITIES")
@Multitenant(SINGLE_TABLE)
@TenantDiscriminatorColumns({
@TenantDiscriminatorColumn(name = "TENANT_ID",
contextProperty = "employee-tenant.id", length = 20) @TenantDiscriminatorColumn(name = "TENANT_CODE",
contextProperty = "employee-tenant.code", discriminatorType = STRING, table = "RESPONSIBILITIES")
14.2.1.3.2 Use the <tenant-discriminator-column> Element To use the
<tenant-discriminator-column> element, include the element within a
<multitenant> element and optionally include the name and context-property attributes. If you do not specify these attributes, the defaults name = "TENANT-ID" and contextProperty = "eclipselink.tenant-id" are used.
For example:
<entity class="model.Employee">
<multitenant>
<tenant-discriminator-column name="TENANT"
context-property="multitenant.id"/>
</multitenant>
...
</entity>
To specify multiple columns, include additional <tenant-discriminator-column>
elements, and include the table where the column is located if it is not located on the primary table. For example:
<entity class="model.Employee">
<multitenant type="SINGLE_TABLE">
<tenant-discriminator-column name="TENANT_ID"
context-property="employee-tenant.id" length="20"/>
<tenant-discriminator-column name="TENANT_CODE"
context-property="employee-tenant.id" discriminator-type="STRING"
table="RESPONSIBILITIES"/>
</multitenant>
<table name="EMPLOYEE"/>
<secondary-table name="RESPONSIBILITIES"/>
...
</entity>
14.2.1.3.3 Map Tenant Discriminator Columns Tenant discriminator columns can be mapped to a primary key or to another column. The following example maps the tenant discriminator column to the primary key on the table during DDL generation:
@Entity
@Table(name = "ADDRESS")
@Multitenant
Using Single-Table Multi-Tenancy
@TenantDiscriminatorColumn(name = "TENANT", contextProperty = "tenant.id", primaryKey = true)
public Address() { ...
}
The following example uses the ORM XML file to map the tenant discriminator column to a primary key:
<entity class="model.Address">
<multitenant>
<tenant-discriminator-column name="TENANT"
context-property="multitenant.id" primary-key="true"/>
</multitenant>
<table name="ADDRESS"/>
...
</entity>
The following example maps the tenant discriminator column to another column named AGE:
@Entity
@Table(name = "Player")
@Multitenant
@TenantDiscriminatorColumn(name = "AGE", contextProperty = "tenant.age") public Player() {
...
@Basic
@Column(name="AGE", insertable="false", updatable="false") public int age;
}
The following example uses the ORM XML file to map the tenant discriminator column to another column named AGE:
<entity class="model.Player">
<multitenant>
<tenant-discriminator-column name="AGE" context-property="tenant.age"/>
</multitenant>
<table name="PLAYER"/>
...
<attributes>
<basic name="age" insertable="false" updatable="false">
<column name="AGE"/>
14.2.1.3.4 Define Persistence Unit and Entity Mappings Defaults In addition to configuring discriminator columns at the entity and mapped superclass levels, you can also configure them at the persistence-unit-defaults and entity-mappings levels to provide defaults. Defining the metadata at the these levels follows similar JPA metadata defaulting and overriding rules.
Specify default tenant discriminator column metadata at the
persistence-unit-defaults level in the ORM XML file. When defined at this level, the defaults apply to all entities of the persistence unit that have specified a
Using Single-Table Multi-Tenancy
Tenant Isolation Using EclipseLink 14-7 multi-tenant type of SINGLE_TABLE minus those that specify their own tenant
discriminator metadata. For example:
<persistence-unit-metadata>
<persistence-unit-defaults>
<tenant-discriminator-column name="TENANT_ID" context-property="tenant.id"/>
</persistence-unit-defaults>
</persistence-unit-metadata>
You can also specify tenant discriminator column metadata at the entity-mappings level in the ORM XML file. A setting at this level overrides a persistence unit default and applies to all entities with a multi-tenant type of SINGLE_TABLE of the mapping file, minus those that specify their own tenant discriminator metadata. For example:
<entity-mappings>
...
...
<tenant-discriminator-column name="TENANT_ID" context-property="tenant.id"/>
...
</entity-mappings>