<entity-mappings>
<mapped-superclass class="com.cmobilecom.af.entity.PersistenceEntityBase" >
<multitenant enabled="#{multitenant.enabled}">
<!-- Support application-managed multitenancy. -->
<discriminator-column name="instanceId" type="java.lang.Long"
value-mapping-property="instance.id"
tenant-entity="com.cmobilecom.af.module.system.entity.InstanceImpl"
attribute="instance"/>
</multitenant>
</mapped-superclass>
</entity-mappings>
All entity types extends PersistenceEntityBase, and entity multitenancy is inheritable by
class hierarchy. So the multitenancy of all entities are controlled by the expression
#{multitenant.enabled} that can be resolved by persistence-unit property multitenant.enabled
in META-INF/persistence.xml.
For example,
<persistence-unit name="hr" transaction-type="RESOURCE_LOCAL">
<mapping-file>System/conf/orm.xml</mapping-file>
<mapping-file>Website/conf/orm.xml</mapping-file>
<mapping-file>HR/conf/orm.xml</mapping-file>
<properties>
<!-- properties to resolve expressions in ORM mappings -->
<property name="multitenant.enabled" value="true"/>
<property name="user.multitenant.enabled" value="false"/>
</properties>
</persistence-unit>
To disable multitenancy for an entity type when its class hierarchy is enabled
for multitenancy, add <multitenant> element for the entity type and set its
attribute "enabled" to "false". For example, to disable Employee multitenancy:
<entity class="Employee" >
<multitenant enabled="false"/>
</entity>
The multitenancy of the entity type and all its subclass types will be disabled.
See Cmobilecom JPA developer guide for more details on Multitenancy.
<system-config>
<instance-type id="hr" name="HR">
<moduleNode module="HR"/>
<moduleNode module="System"/>
<persistenceUnit>hr</persistenceUnit>
<multitenant>
<type>SHARED_TABLE</type>
<schema>#{db.schemaName}_#{instanceType.id}</schema>
<!-- users: single identity (shared by system and all instances) -->
<shared-entity>
<class>com.cmobilecom.af.entity.security.User</class>
<access>
<create/>
<edit/>
<view/>
<owner-access/>
<privacy/>
</access>
<shared-with>system</shared-with>
<param name="paramName" value="paramValue"/>
</shared-entity>
</multitenant>
</instance-type>
</system-config>
Each instanceType has its own separate database schema, and instances of
an instanceType can share the same schema or have its own separate schema.
#{db.schemaName}Example 2: shared table, use one schema for all the instances of an InstanceType
#{db.schemaName}_#{instanceType.id}Example 3: separate schemas for different instances of an InstanceType
#{db.schemaName}_#{instanceType.id}_#{instance.id}For the system InstanceType, it must be #{db.schemaName}. For a non-system InstanceType, it can contain #{instanceType.id} and/or #{instance.id}.
If User entities is not shared, each DataAccessUnit will have its own users. In this case, set property "user.multitenant.enabled" to "true" to enable User multitenancy (i.e., disable user entity sharing) in META-INF/persistence.xml.
<properties> <property name="user.multitenant.enabled" value="true"/> </properties>For the system InstanceType, if the User entity is configured as shared-table multitenancy (i.e., the User table is shared with instances of other instanceTypes and each instance has its own users), the installation seed/seed.xml must include the following seed sql file to add "instanceId" column to User table.
<seedSql>System/db/@DBMS_TYPE@/multitenant/seed-user.sql</seedSql>
For example, multitenant seed sql files in the example HR module for MySql and Oracle databases:
db/mysql/multitenant/seed.sql db/oracle/multitenant/seed.sqlMySql database: alter Address and Employee tables:
ALTER TABLE `Address` add `instanceId` bigint(20) NOT NULL;
ALTER TABLE `Address` add INDEX `instanceId` (`instanceId`);
ALTER TABLE `Employee` add `instanceId` bigint(20) NOT NULL;
ALTER TABLE `Employee` drop KEY `nid`;
ALTER TABLE `Employee` add UNIQUE KEY `nid` (`instanceId`, `nid`);
Oracle database: alter Address and Employee tables:
ALTER TABLE Address add instanceId NUMBER(19,0) NOT NULL;
CREATE INDEX IX_HR_ADDR_instanceId on Address (instanceId);
ALTER TABLE Employee add instanceId NUMBER(19,0) NOT NULL;
ALTER TABLE Employee drop CONSTRAINT UK_HR_EMP_nid;
ALTER TABLE Employee add CONSTRAINT UK_HR_EMP_nid UNIQUE (instanceId, nid);
The discriminator column should have index for performance, and needs to be added to
unique keys if they are unique in the scope of a tenant. If the discriminator column
is in a unique key, it will have index automatically.