package org.hibernate.test.cache.infinispan.functional;
import org.hibernate.MultiTenancyStrategy;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cache.infinispan.entity.EntityRegionImpl;
import org.hibernate.cache.internal.DefaultCacheKeysFactory;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.jdbc.connections.spi.AbstractMultiTenantConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.hibernate.test.cache.infinispan.functional.entities.Item;
import org.hibernate.test.cache.infinispan.tm.XaConnectionProvider;
import org.hibernate.testing.env.ConnectionProviderBuilder;
import org.infinispan.AdvancedCache;
import org.infinispan.commons.util.CloseableIterator;
import org.infinispan.context.Flag;
import org.junit.Test;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
/**
* @author Radim Vansa <rvansa@redhat.com>
*/
public class MultiTenancyTest extends SingleNodeTest {
private static final String DB1 = "db1";
private static final String DB2 = "db2";
private final ConnectionProvider db1
= new XaConnectionProvider(ConnectionProviderBuilder.buildConnectionProvider(DB1));
private final ConnectionProvider db2
= new XaConnectionProvider(ConnectionProviderBuilder.buildConnectionProvider(DB2));
@Override
public List<Object[]> getParameters() {
return Collections.singletonList(READ_ONLY_INVALIDATION);
}
@Override
protected void addSettings(Map settings) {
super.addSettings( settings );
settings.put( Environment.CACHE_KEYS_FACTORY, DefaultCacheKeysFactory.SHORT_NAME );
}
@Override
protected void configureStandardServiceRegistryBuilder(StandardServiceRegistryBuilder ssrb) {
super.configureStandardServiceRegistryBuilder(ssrb);
ssrb.addService(MultiTenantConnectionProvider.class, new AbstractMultiTenantConnectionProvider() {
@Override
protected ConnectionProvider getAnyConnectionProvider() {
return db1;
}
@Override
protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
if (DB1.equals(tenantIdentifier)) return db1;
if (DB2.equals(tenantIdentifier)) return db2;
throw new IllegalArgumentException();
}
});
}
@Override
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
super.configureSessionFactoryBuilder(sfb);
sfb.applyMultiTenancyStrategy(MultiTenancyStrategy.DATABASE);
}
@Override
protected void cleanupTest() throws Exception {
db1.getConnection().close();
db2.getConnection().close();
}
@Test
public void testMultiTenancy() throws Exception {
final Item item = new Item("my item", "description" );
withTxSession(sessionFactory().withOptions().tenantIdentifier(DB1), s -> s.persist(item));
for (int i = 0; i < 5; ++i) { // make sure we get something cached
withTxSession(sessionFactory().withOptions().tenantIdentifier(DB1), s -> {
Item item2 = s.get(Item.class, item.getId());
assertNotNull(item2);
assertEquals(item.getName(), item2.getName());
});
}
// The table ITEMS is not created in DB2 - we would get just an exception
// for (int i = 0; i < 5; ++i) { // make sure we get something cached
// withTx(tm, new Callable<Void>() {
// @Override
// public Void call() throws Exception {
// Session s = sessionFactory().withOptions().tenantIdentifier(DB2).openSession();
// s.getTransaction().begin();
// Item item2 = s.get(Item.class, id);
// s.getTransaction().commit();
// s.close();
// assertNull(item2);
// return null;
// }
// });
// }
EntityRegionImpl region = (EntityRegionImpl) sessionFactory().getSecondLevelCacheRegion(Item.class.getName());
AdvancedCache localCache = region.getCache().withFlags(Flag.CACHE_MODE_LOCAL);
assertEquals(1, localCache.size());
try (CloseableIterator iterator = localCache.keySet().iterator()) {
assertEquals("CacheKeyImplementation", iterator.next().getClass().getSimpleName());
}
}
}