Hello I'm developing a web application using Vaadin framework, JPA EclipseLink as ORM, MYSQL as database. Currently I'm working to implement Multitenant structure for my app. Here I've to choose TABLE_PER_TENANT with different schema in a shared database strategy as I already have some tenants.
Here is an example of my tenant specific entity:
@Entity
@Multitenant(MultitenantType.TABLE_PER_TENANT)
@TenantTableDiscriminator(type = TenantTableDiscriminatorType.SCHEMA, contextProperty = PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT)
public class UserAccount implements Serializable {
......
}
Here is my persistence unit for tenant in persistence.xml :
<persistence-unit name="GroupBuilderPU" transaction-type="RESOURCE_LOCAL">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<class>Includes all tenant table class</class>
<properties>
<property name="eclipselink.cache.shared.default" value="false"/>
<!-- container isn upcloud ??-->
<property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/?rewriteBatchedStatements=true&characterEncoding=UTF-8&connectionCollation=utf8_general_ci&zeroDateTimeBehavior=convertToNull&useUnicode=true&connectionCollation=utf8_general_ci&characterSetResults=utf8&characterEncoding=utf8&characterEncoding=UTF-8&characterSetResults=UTF-8"/>
<property name="javax.persistence.jdbc.user" value="root"/>
<property name="javax.persistence.jdbc.password" value="root"/>
<property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
<property name="eclipselink.ddl-generation" value="create-or-extend-tables"/>
<property name="eclipselink.jdbc.batch-writing" value="JDBC"/>
<property name="eclipselink.jdbc.batch-writing.size" value="1000"/>
<property name="hibernate.connection.useUnicode" value="true"/>
<property name="hibernate.connection.characterEncoding" value="UTF-8"/>
</properties>
</persistence-unit>
Now I'm getting an entitymanager like this:
public static EntityManager createTenantSpecificEntityManager(){
EntityManager em = Persistence.createEntityManagerFactory(GroupBuilderApp.PERSISTENCE_UNIT).createEntityManager(getProperties());
return em;
}
private static Map<String, Object> getProperties(){
Map<String, Object> properties = new HashMap<>();
properties.put("javax.persistence.jdbc.url", getDataBaseConnectionURL(COMPANY_NAME_AS_TENENT_ID));
return properties;
}
public static String getDataBaseConnectionURL(String schemaName){
String str = "jdbc:mysql://localhost:3306/?rewriteBatchedStatements=true&characterEncoding=UTF-8&connectionCollation=utf8_general_ci&zeroDateTimeBehavior=convertToNull&useUnicode=true&connectionCollation=utf8_general_ci&characterSetResults=utf8&characterEncoding=utf8&characterEncoding=UTF-8&characterSetResults=UTF-8";//for testing purpose
StringBuilder sb = new StringBuilder(str);
sb.insert(sb.indexOf("?"), schemaName);
return sb.toString();
}
Now I'm using entitymanager like this:
em = createTenantSpecificEntityManager();
em.getTransaction().begin();
em.setProperty(EntityManagerProperties.MULTITENANT_PROPERTY_DEFAULT, GroupBuilderApp.COMPANY_NAME_AS_TENENT_ID);
.......
Do any operation here
.......
em.getTransaction().commit();
em.close();
In the app user can log in to a specific tenant (where he has given the access). So at a time only one tenant's data can be accessed.
Is it the right approach for my app to make it Multi-tenant?
Is there any improvement I can do?