如何使用JPA / EclipseLink实现动态多租户或动态表过滤?

时间:2014-03-25 15:44:16

标签: java jpa eclipselink multi-tenant

我有一个JavaEE 6,JPA 2.1应用程序,我需要管理 用户属于多个租户。这是必需的,所以他们是 例如,能够将数据的所有权从一个租户更改为 另一个。

租户结构按照树的分层方式设置 像这样的实现(格式为[Role:Tenant-ID] 参考):

                [SysAdmin:1]
                   /   \
                  /     \
                 /       \
                /         \
               /           \
  [Admin Tenant A:2]   [Admin Tenant B:3]
           / \               \
          /   \               \
 [User TA:4] [Manager TA:5] [User TB:6]
                \
                 \
             [User TA:7]

现在,当我使用活动用户[User TA:4]查询数据库时 期待与“租户ID”相关的结果4.当我与活动用户查询时 [Admin Tenant B:3]我希望结果来自租户3和6以及 当我查询为[SysAdmin:1]时,我只想要返回所有数据 基本上没有过滤器。

由于我将EclipseLink 2.5.1作为JPA实现,我尝试使用 最初的@Multitenant实现,显然不是 似乎工作,因为它有望一次为单个租户工作 只是,这是完全有道理的,因为它正在使用该信息 也可以写入数据库。

对于写入到数据库,我想我可以设法得到一些东西 沿着自定义@Produces @MultitenantWriteAware EntityManager方法的路线,我分配了 eclipselink.tenant-id向目标租户写信 操作。然而,通过这种方法,你失去了漂亮的容器 您@PersistenceContext管理@Inject(CMT) EntityManager然后。

尝试使用自定义PersistenceProvider来实现此功能时 在EclipseLink上提供的捎带让我尽可能地遇到问题 不从任何地方检索活动用户。通过它的唯一方法 信息似乎是通过

中提供的Map
public
EntityManagerFactory 
createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties)

我也调查了QueryRedirector这些似乎让我自定义的内容 查询并附加一个条件,如' AND tenant_id IN(2,3,4)'成 活动查询,这是一种有点手动的实现方式 (多)@Multitenant,但我不能像我一样工作 并没有与ExpressionBuilder相提并论 无法从某个地方查询该活跃用户。

我认为我忽略了一些东西,因为我觉得必须有一种 通用和自动方式来实现这个而不是手动 使用。将额外条件附加到查询 CriteriaBuilder

是否有关于如何实现此目的的建议/提示/链接/最佳实践 那种设置?

1 个答案:

答案 0 :(得分:1)

我认为到目前为止这是一个悬而未决的问题。我发布了一个类似的question。一个答案包含link日食虫追踪器提出这一点。所描述的解决方法是对具有不同多租户设置的相同表使用多个持久性单元。根据您使用的EntityManagerFactory,数据库查询具有不同的范围。我没有在实践中使用它(我害怕这两个持久性单元中可能存在的不一致)。

我正在尝试使用here与@AdditionalCriteria描述的不同方法。我将该注释添加到应该由租户过滤的所有实体,但也应该由管理员访问:

@AdditionalCriteria(":ADMINACCESS = 1 or this.tenant=:TENANT")

标志ADMINACCESS决定是否应用租户过滤器。我想你可以轻松地将它扩展到你的场景。这样可以保证始终应用此动态过滤器。但是你需要自己处理租户属性。对我来说,这是一个很好的妥协。我将所有数据库操作封装在一个点上。以统一方式实现该方法的一种方法是记住ThreadLocal EntityManager中的当前租户,并确保所有租户相关实体实现定义方法setTenant(String tenant)的接口TenantSpecific。如果持久保存新对象,将始终设置此项。