Question

Tenants in eclipselink (or Hibernate) are a great concept to separate data domains from each other. I am using eclipselink with single-table strategy.

Sometimes it is necessary to access data from more than just one tenant (e.g. for admin purposes). Is there a good way to achieve that? (I do not want to run through all tenants to collect the data...)

Example:

@Entity
@Multitenant
@TenantDiscriminatorColumn(name = "TENANT", contextProperty = "tenant.id")
public class TenantEntity {
    ...

I can access the objects in a specific tenant with a parameterized entity manager:

private static EntityManager newEntityManager(String tenant) {
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("tenant.id", tenant);
    return emf.createEntityManager(map);
}

Is there any convenient way to query over all tenants? (Or is the identity of a persisted object only defined in a single tenant?)

Was it helpful?

Solution

EclipseLink has an open feature request to allow a better way of allowing an admin server to access multi tenant data: https://bugs.eclipse.org/bugs/show_bug.cgi?id=355458 - vote for it if it is important to you.

The way around it would be to create a separate persistence unit for your admin console. One way to go about this would be to move the multitenant metadata to an EclipseLink orm.xml file, and use it in your tenant persitence units, while the admin persistence unit just use the entity classes. You might want a field in the entities that can be mapped to the tenant column that the admin console could use and query against, but be read-only or inaccessible to the tenant specific persistence units.

OTHER TIPS

I found an alternative approach that I will try out: Instead of using the @Multitenant annotation to filter out those entities that belong to my tenant I will use @AdditionalCriteria. My example from the question above becomes

@Entity
@AdditionalCriteria(":ADMINACCESS = 1 or this.tenant=:TENANT")
public class TenantEntity {

    private String tenant;
    ...

Here I need to take care of the tenant column myself. I can create two entity managers. One for tenant access:

private static EntityManager newEntityManager(String tenant) {
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("TENANT", tenant);
    map.put("ADMINACCESS", 0);
    return emf.createEntityManager(map);
}

And another one for admin access:

private static EntityManager newEntityManager() {
    Map<String, Object> map = new HashMap<String, Object>();
    map.put("TENANT", "");
    map.put("ADMINACCESS", 1);
    return emf.createEntityManager(map);
}

See details for @AdditionalCriteria here. Any comments?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top