【问题标题】:What is the right approach for Multi-tenancy using eclipselink使用 eclipselink 进行多租户的正确方法是什么
【发布时间】:2017-04-19 09:58:41
【问题描述】:

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

这是我的租户特定实体的示例:

@Entity
@Multitenant(MultitenantType.TABLE_PER_TENANT)
@TenantTableDiscriminator(type = TenantTableDiscriminatorType.SCHEMA, contextProperty = PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT)
public class UserAccount implements Serializable {
......
}

这是我在 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>

现在我得到了一个这样的实体管理器:

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();
    }

现在我正在使用这样的实体管理器:

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();

在应用程序中,用户可以登录特定租户(他已授予访问权限)。因此,一次只能访问一个租户的数据。

将我的应用设置为多租户是否正确? 有什么可以改进的吗?

【问题讨论】:

    标签: java eclipselink multi-tenant


    【解决方案1】:

    可以使用ThreadLocal,如下所示:

    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 时,可以使用上面的租户,如下所示:

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

    我使用 Eclipse Link 和 Spring Data 创建了一个关于多租户(每个租户的表)的 java 示例。只需对代码进行最少的更改,即可将现有应用程序转换为多租户。这是使用字节码检测完成的。选择这个想法是为了充分利用 Spring Data 的强大功能。

    可以执行MultiTenantTest 来查看它的工作情况。

    这个想法是开源的,可以在Maven Central获得

    【讨论】:

      猜你喜欢
      • 2020-08-02
      • 2014-12-22
      • 1970-01-01
      • 1970-01-01
      • 2019-12-13
      • 2016-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多