使用eclipselink进行多租户的正确方法是什么 [英] What is the right approach for Multi-tenancy using eclipselink

查看:81
本文介绍了使用eclipselink进行多租户的正确方法是什么的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

您好,我正在使用Vaadin框架,JPA EclipseLink作为ORM,MYSQL作为数据库来开发Web应用程序.目前,我正在为我的应用程序实现Multitenant结构.在这里,我已经有一些租户,因此必须在共享数据库策略中选择具有不同架构的TABLE_PER_TENANT.

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 {
......
}

这是我在persistence.xml中用于租户的持久性单元:

Here is my persistence unit for tenant in persistence.xml :

<persistence-unit name="PU" 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&amp;characterEncoding=UTF-8&amp;connectionCollation=utf8_general_ci&amp;zeroDateTimeBehavior=convertToNull&amp;useUnicode=true&amp;connectionCollation=utf8_general_ci&amp;characterSetResults=utf8&amp;characterEncoding=utf8&amp;characterEncoding=UTF-8&amp;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("PU").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&amp;characterEncoding=UTF-8&amp;connectionCollation=utf8_general_ci&amp;zeroDateTimeBehavior=convertToNull&amp;useUnicode=true&amp;connectionCollation=utf8_general_ci&amp;characterSetResults=utf8&amp;characterEncoding=utf8&amp;characterEncoding=UTF-8&amp;characterSetResults=UTF-8";//for testing purpose
        StringBuilder sb = new StringBuilder(str);
        sb.insert(sb.indexOf("?"), schemaName);
        return sb.toString();
    }

现在我正在使用像这样的entitymanager:

Now I'm using entitymanager like this:

em = createTenantSpecificEntityManager();
em.getTransaction().begin();
       em.setProperty(EntityManagerProperties.MULTITENANT_PROPERTY_DEFAULT, \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?

推荐答案

一个人可以使用ThreadLocal,如下所示:

One can use ThreadLocal as shown below:

public class TenantContext {
  private static final ThreadLocal<String> TENANT_TL = new ThreadLocal<>();

  public static String getTenantId() {
    return TENANT_TL.get();
  }

  public static void setTenantId(String tenantId) {
    TENANT_TL.set(tenantId);
  }
}

tenantId可以在身份验证中设置,通常是在拦截器中.创建EntityManager时,可以使用以上租户,如下所示:

The tenantId can be set on authentication, usually in an Interceptor. While creating EntityManager, above tenant can be used as shown:

em.setProperty(EntityManagerProperties.MULTITENANT_PROPERTY_DEFAULT, TenantContext.getTenantId());

我已经使用Eclipse Link和Spring Data在Multi-Tenancy(每个租户表)上创建了一个Java示例.只需最少的代码更改,就可以将现有的应用程序转换为多租户.这是使用字节码检测完成的.选择这个想法是为了利用Spring Data的全部功能.

I have created a java example on Multi-Tenancy (Table per Tenant) using Eclipse Link and Spring Data. An existing application can be converted to Multi-Tenant with a minimal code change. This is done using bytecode instrumentation. This idea is chosen to utilize the complete power of Spring Data.

一个人可以执行 MultiTenantTest 才能看到它的正常运行.

One can execute MultiTenantTest to see it working.

该想法是开源的,可以在 Maven Central

The idea is open-sourced and is available at Maven Central

这篇关于使用eclipselink进行多租户的正确方法是什么的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆