MongoDB and multi-tenancy [message #1385844] |
Wed, 11 June 2014 15:24 |
GianMaria Romanato Messages: 72 Registered: July 2009 |
Member |
|
|
Hi,
I am trying to use MongoDB via EclipseLink and to enable multi-tenant support.
I started from the EclipseLink Address/Customer/Order/OrderLine example which works fine with MongoDB, then I started adding the multi-tenant specific annotations.
In my first try I specified the annotations to use a discriminator column for holding the tenant-id, and this did not work and EclipseLink raises an exception claiming that the requested feature is not supported for NoSQL platforms.
I then reverted to the TABLE_PER_TENANT method of partitioning data, and this time the EntityManager is created and I am able to save orders to the database.
However, Multi-tenancy settings seem to be ignored, infact, the MongoDB for the Order entity is called ORDER and is not suffixed with the tenant identifier, as I would have expected given that the default behaviour for TABLE_PER_TENANT is to suffix the table name (at least according to the annotation javadoc).
@Entity
@NoSql(dataFormat=DataFormatType.MAPPED)
@Multitenant(value=MultitenantType.TABLE_PER_TENANT)
public class Order implements Serializable
Here is the sample code I am using to try to insert data for two tenants:
Map properties = new HashMap();
properties.put(PersistenceUnitProperties.SESSION_NAME, tenantId);
properties.put(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, tenantId);
properties.put(PersistenceUnitProperties.MULTITENANT_SHARED_EMF, Boolean.FALSE.toString());
EntityManagerFactory factory = Persistence.createEntityManagerFactory("mongo", properties);
EntityManager em = factory.createEntityManager(properties);
em.getTransaction().begin();
em.setProperty(EntityManagerProperties.MULTITENANT_PROPERTY_DEFAULT, tenantId);
Order o1 = new Order();
o1.setDescription("Customer");
em.persist(o1);
em.getTransaction().commit();
em.close();
I am calling the above code twice from a main, using different value for the tenantId variable, but the above results in two entries in the same collection named ORDER
I also tried forcing the tenant-id in the entity manager, both before and after opening the transaction (btw which is the correct way?) with no luck:
em.setProperty(EntityManagerProperties.MULTITENANT_PROPERTY_DEFAULT, tenantId);
Can anyone give me some advice? Thanks
Developing for Virgo using PDE: http://bit.ly/1w0tTit
Global JNDI in Virgo: http://bit.ly/1to42mn
Hyperic to monitor Virgo: http://bit.ly/W1Fst9
Profile Virgo with JProfiler http://bit.ly/1FBLGCw
|
|
|
|
|
Re: MongoDB and multi-tenancy [message #1717601 is a reply to message #1717570] |
Tue, 15 December 2015 08:55 |
GianMaria Romanato Messages: 57 Registered: November 2015 |
Member |
|
|
I don't know which part of Eclipselink should be fixed, but I think that the following work-around may work for you:
a) Add a SessionCustomizer [1] to your persistence unit, either via persistence.xml, annotations or by using a custom MetadataSource [2]
b) In the SessionCustomizer modify the ClassDescriptors for your JPA entities so that the table names are suffixed or prefixed with the tenant id.
As an alternative to the above you may use a custom MetadataSource and override the @Table annotation for each entity in order to specify a different table name.
The SessionCustomizer looks simpler to me than using a custom MetadataSource because you will just change the meta-data model already built by Eclipselink while if you used a MetadataSource you would need to build a correct meta-data specification up front.
In fact, customizers are called by Eclipselink to post-process the meta-data that Eclipselink has built out of annotations, mapping files, MetadaSources etc before the actual persistence unit is created. Customizers can change virtually everything (table names, indices names etc.). However, because this is a post-processing, if you change a table name you must also change any references to it (indices, constraints etc), but it's relatively simple.
Finally, given that customizers are specified as a class and that it is EclipseLink that instantiates them you will have to find a way to pass the tenant-id to the customizer. For example using a thread-local field.
[1] https://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Customizers
[2] https://wiki.eclipse.org/EclipseLink/Examples/JPA/MetadataSource
|
|
|
Powered by
FUDForum. Page generated in 0.03560 seconds