2014-03-25 41 views
3

我有一个JavaEE 6,JPA 2.1应用程序,我需要管理 用户属于多个租户。这是必需的,因此它们是 ,例如可以将一个承租人的数据所有权更改为另一个承租人 。如何使用JPA/EclipseLink实现动态多租户或动态表过滤?

租户结构分层方式设置,下面一棵树 像执行这样的(格式为[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]查询数据库我 与'tenant-id'预期结果4.当我查询与活动用户 [Admin Tenant B:3]我期望结果来自租户3和6和 当我查询为[SysAdmin:1]我只想要返回所有数据 基本上没有过滤器。

由于我有作为JPA实现我试图利用 在@Multitenant实现首先,这显然不 似乎因为预计在同一时间只 ,这使得单个租户上班工作的EclipseLink 2.5.1完美的意义,因为它正在使用该信息,以及 actualy写入数据库。

对于来,我想我可以设法相处的定制@Produces @MultitenantWriteAware EntityManager方法去的东西,在这里我分配 eclipselink.tenant-id到目标租户写 操作线的东西 数据库。用这种方法,你会丢失漂亮的容器 托管@PersistenceContext(CMT)@Inject你的 EntityManager然后。

当试图用一个自定义PersistenceProvider是 捎带上一个的EclipseLink提供我所面临的问题,因为我可以 没有从任何地方获取活跃用户实现这一点。只有这样,才能传递 信息似乎是通过提供Map

public 
EntityManagerFactory 
createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) 

我也看了成QueryRedirector S的似乎让我定制 查询并追加像“条件,并tenant_id IN(2, 3,4)'变成 积极的查询,这是实施 (多)@Multitenant的某种手动方式,但我不能得到那个工作,因为我 没有得到与那ExpressionBuilder和另外似乎 无法从某处查询该活动用户。

我觉得我忽略的东西,我想一定是通用的,自动的方式排序 实现这个,而不是手动 使用 CriteriaBuilder

附加额外条件,查询是否有任何建议/提示/链接/最佳做法如何实现这种 种类的设置?

回答

1

我相信这是迄今为止的一个悬而未决的问题。我已发布类似question。一个答案包含了一个link日食臭虫跟踪器也提高了这一点。此处描述的解决方法是使用具有不同多租户设置的相同表的多个持久性单元。根据您使用的EntityManagerFactory,数据库查询具有不同的作用域。我在实践中并没有这样做(我害怕这两个持久单元中存在潜在的不一致)。

我想用@AdditionalCriteria使用不同的方法描述here。我是注释到,应该由房客来过滤所有的实体,但也应该是访问被管理员:

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

标志ADMINACCESS决定租户是否应用滤波器,或没有。我想你可以很容易地将它扩展到你的场景。这样就保证了这个动态过滤器始终得到应用。但是你需要自己照顾租户属性。对我来说这是一个很好的妥协。我将所有数据库操作封装在一个点上。以统一的方式实现这一点的一种方式是记住ThreadLocal EntityManager中的当前租户,并确保所有租户相关实体实现定义方法setTenant(字符串租户)的接口TenantSpecific。如果你坚持新的对象,这将始终被设置。

+0

这样,当您使用此批注连接表时,可以禁用共享高速缓存。当JPA查询缓存时,您是否知道如何设置附加条件? – Orbita