package org.hivedb.hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.shards.strategy.access.SequentialShardAccessStrategy;
import org.hivedb.Hive;
import org.hivedb.meta.Node;
import org.hivedb.util.Lists;
import org.hivedb.util.classgen.GenerateInstance;
import org.hivedb.util.classgen.GeneratedClassFactory;
import org.hivedb.util.classgen.GeneratedInstanceInterceptor;
import org.hivedb.util.classgen.ReflectionTools;
import org.hivedb.util.database.HiveDbDialect;
import org.hivedb.util.database.Schemas;
import org.hivedb.util.database.test.Continent;
import org.hivedb.util.database.test.HiveTest;
import org.hivedb.util.database.test.HiveTest.Config;
import org.hivedb.util.database.test.WeatherEvent;
import org.hivedb.util.database.test.WeatherReport;
import org.hivedb.util.functional.Atom;
import org.junit.Assert;
import static org.junit.Assert.*;
import org.junit.Test;
import java.util.Date;
import java.util.Properties;
@Config("hive_default")
public class HiveSessionFactoryBuilderTest extends HiveTest {
@Test
public void testCreateConfigurationFromNode() throws Exception {
Node node = new Node(Hive.NEW_OBJECT_ID, "node", getHiveDatabaseName(), "", HiveDbDialect.H2);
Configuration config = HiveSessionFactoryBuilderImpl.createConfigurationFromNode(node, new Properties());
assertEquals(node.getUri(), config.getProperty("hibernate.connection.url"));
assertEquals(H2Dialect.class.getName(), config.getProperty("hibernate.dialect"));
assertEquals(node.getId().toString(), config.getProperty("hibernate.connection.shard_id"));
}
@Test
public void testGetSessionFactory() throws Exception {
HiveSessionFactoryBuilderImpl factoryBuilder = getHiveSessionFactoryBuilder();
assertNotNull(factoryBuilder.getSessionFactory());
factoryBuilder.openSession();
}
@Test
public void testOpenSessionByPrimaryKey() throws Exception {
HiveSessionFactoryBuilderImpl factoryBuilder = getHiveSessionFactoryBuilder();
final WeatherReport report = newInstance();
save(factoryBuilder, report);
assertNotNull(factoryBuilder.getSessionFactory());
factoryBuilder.openSession(config.getEntityConfig(getGeneratedClass(WeatherReport.class)).getPrimaryIndexKey(report));
}
@Test
public void testOpenSessionByResourceId() throws Exception {
HiveSessionFactoryBuilderImpl factoryBuilder = getHiveSessionFactoryBuilder();
assertNotNull(factoryBuilder.getSessionFactory());
final WeatherReport report = newInstance();
save(factoryBuilder, report);
factoryBuilder.openSession("WeatherReport", config.getEntityConfig(getGeneratedClass(WeatherReport.class)).getId(report));
}
@SuppressWarnings("unchecked")
private HiveSessionFactoryBuilderImpl getHiveSessionFactoryBuilder() {
HiveSessionFactoryBuilderImpl factoryBuilder =
new HiveSessionFactoryBuilderImpl(
getConnectString(getHiveDatabaseName()),
Lists.newList(Continent.class, WeatherReport.class, WeatherEvent.class),
new SequentialShardAccessStrategy());
return factoryBuilder;
}
@Test
public void testOpenSessionBySecondaryIndex() throws Exception {
HiveSessionFactoryBuilderImpl factoryBuilder = getHiveSessionFactoryBuilder();
final WeatherReport report = newInstance();
save(factoryBuilder, report);
factoryBuilder.openSession("WeatherReport", "weatherEventEventId", Atom.getFirstOrThrow(report.getWeatherEvents()).getEventId());
}
@Test
public void testInsert() throws Exception {
HiveSessionFactoryBuilderImpl factoryBuilder = getHiveSessionFactoryBuilder();
final WeatherReport report = newInstance();
for (Node node : getHive().getNodes()) {
if (! Schemas.tableExists("WEATHER_REPORT", node.getUri())) {
throw new RuntimeException("Can't find WEATHER_REPORT table on node " + node.getUri());
}
}
save(factoryBuilder, report);
Hive hive = getHive();
assertTrue(hive.directory().doesResourceIdExist("WeatherReport", report.getReportId()));
assertTrue(hive.directory().doesResourceIdExist("Temperature", report.getTemperature()));
}
@Test
public void testInsertFail() throws Exception {
HiveSessionFactoryBuilderImpl factoryBuilder = getHiveSessionFactoryBuilder();
final WeatherReport report = newInstance();
Session session = factoryBuilder.getSessionFactory().openSession();
SessionCallback callback = new SessionCallback(){
public void execute(Session session) {
session.saveOrUpdate(report);
}};
for (Node node : getHive().getNodes()) {
if (! Schemas.tableExists("WEATHER_REPORT", node.getUri())) {
throw new RuntimeException("Can't find WEATHER_REPORT table on node " + node.getUri());
}
}
doInTransactionAndFailBeforeCommit(callback, session);
Hive hive = getHive();
assertFalse(hive.directory().doesResourceIdExist("WeatherReport", report.getReportId()));
assertFalse(hive.directory().doesResourceIdExist("Temperature", report.getTemperature()));
assertTrue(factoryBuilder.getDefaultInterceptor().isTransient(report));
}
@Test
public void testInsertAndRetrieve() throws Exception {
HiveSessionFactoryBuilderImpl factoryBuilder = getHiveSessionFactoryBuilder();
final WeatherReport report = newInstance();
save(factoryBuilder, report);
WeatherReport fetched = (WeatherReport) factoryBuilder.openSession().get(getGeneratedClass(WeatherReport.class), report.getReportId());
Assert.assertEquals(report, fetched);
}
@Test
public void testDelete() throws Exception {
HiveSessionFactoryBuilderImpl factoryBuilder = getHiveSessionFactoryBuilder();
final WeatherReport report = newInstance();
save(factoryBuilder, report);
SessionCallback deleteCallback = new SessionCallback(){
public void execute(Session session) {
session.delete(report);
}};
doInTransaction(deleteCallback, factoryBuilder.openSession());
WeatherReport fetched = (WeatherReport) factoryBuilder.openSession().get(getGeneratedClass(WeatherReport.class), report.getReportId());
assertEquals(fetched, null);
}
@Test
public void testUpdate() throws Exception {
HiveSessionFactoryBuilderImpl factoryBuilder = getHiveSessionFactoryBuilder();
final WeatherReport report = newInstance();
SessionCallback callback = new SessionCallback(){
public void execute(Session session) {
session.saveOrUpdate(report);
}};
doInTransaction(callback, factoryBuilder.openSession());
final WeatherReport mutated = newInstance();
//System.err.println(((WeatherReport) factoryBuilder.openSession().get(getGeneratedClass(WeatherReport.class), report.getReportId())).getWeatherEvents().size());
GeneratedInstanceInterceptor.setProperty(mutated, "reportId", report.getReportId());
GeneratedInstanceInterceptor.setProperty(mutated, "continent", report.getContinent());
GeneratedInstanceInterceptor.setProperty(mutated, "temperature", report.getTemperature());
GeneratedInstanceInterceptor.setProperty(mutated, "reportTime", new Date(System.currentTimeMillis()));
// Updating collection items requires more advanced persistence login (see BaseDataAccessObject)
// so we leave these values identical
GeneratedInstanceInterceptor.setProperty(mutated, "weatherEvents", report.getWeatherEvents());
GeneratedInstanceInterceptor.setProperty(mutated, "sources", report.getSources());
assertTrue("You have to change something if you want to test update.", ReflectionTools.getDifferingFields(report, mutated, WeatherReport.class).size() != 0);
SessionCallback updateCallback = new SessionCallback(){
public void execute(Session session) {
session.saveOrUpdate(mutated);
}};
doInTransaction(updateCallback, factoryBuilder.openSession());
WeatherReport fetched = (WeatherReport) factoryBuilder.openSession().get(getGeneratedClass(WeatherReport.class), report.getReportId());
assertNotNull(fetched);
assertFalse(ReflectionTools.getDifferingFields(report, fetched, WeatherReport.class).size() == 0);
Assert.assertEquals(report, fetched);
}
@Test
public void testUpdateFail() throws Exception {
HiveSessionFactoryBuilderImpl factoryBuilder = getHiveSessionFactoryBuilder();
final WeatherReport report = newInstance();
SessionCallback callback = new SessionCallback(){
public void execute(Session session) {
session.saveOrUpdate(report);
}};
doInTransaction(callback, factoryBuilder.openSession());
final WeatherReport mutated = newInstance();
//System.err.println(((WeatherReport) factoryBuilder.openSession().get(getGeneratedClass(WeatherReport.class), report.getReportId())).getWeatherEvents().size());
GeneratedInstanceInterceptor.setProperty(mutated, "reportId", report.getReportId());
GeneratedInstanceInterceptor.setProperty(mutated, "continent", report.getContinent());
GeneratedInstanceInterceptor.setProperty(mutated, "temperature", report.getTemperature());
GeneratedInstanceInterceptor.setProperty(mutated, "reportTime", new Date(System.currentTimeMillis()));
// Updating collection items requires more advanced persistence login (see BaseDataAccessObject)
// so we leave these values identical
GeneratedInstanceInterceptor.setProperty(mutated, "weatherEvents", report.getWeatherEvents());
GeneratedInstanceInterceptor.setProperty(mutated, "sources", report.getSources());
assertTrue(
"You have to change something if you want to test update.",
ReflectionTools.getDifferingFields(report, mutated, WeatherReport.class).size() != 0);
SessionCallback updateCallback = new SessionCallback(){
public void execute(Session session) {
session.saveOrUpdate(mutated);
}};
doInTransactionAndFailBeforeCommit(updateCallback, factoryBuilder.openSession());
WeatherReport fetched = (WeatherReport) factoryBuilder.openSession().get(getGeneratedClass(WeatherReport.class), report.getReportId());
assertNotNull(fetched);
assertEquals(ReflectionTools.getDifferingFields(report, fetched, WeatherReport.class).toString(), report, fetched);
Assert.assertFalse(ReflectionTools.getDifferingFields(mutated, fetched, WeatherReport.class).size() == 0);
}
private void save(HiveSessionFactoryBuilderImpl factoryBuilder, final WeatherReport report) {
Session session = factoryBuilder.openSession();
SessionCallback callback = new SessionCallback(){
public void execute(Session session) {
session.saveOrUpdate(report);
}};
doInTransaction(callback, session);
}
@SuppressWarnings("unchecked")
private Class<?> getGeneratedClass(Class clazz) {
return GeneratedClassFactory.getGeneratedClass(clazz);
}
private WeatherReport newInstance() {
return new GenerateInstance<WeatherReport>(WeatherReport.class).generate();
}
public static void doInTransaction(SessionCallback callback, Session session) {
Transaction tx = null;
try {
tx = session.beginTransaction();
callback.execute(session);
tx.commit();
} catch( RuntimeException e ) {
if(tx != null)
tx.rollback();
throw e;
} finally {
session.close();
}
}
public static void doInTransactionDontCloseSession(SessionCallback callback, Session session) {
Transaction tx = null;
try {
tx = session.beginTransaction();
callback.execute(session);
tx.commit();
} catch( RuntimeException e ) {
if(tx != null)
tx.rollback();
throw e;
}
}
public static void doInTransactionAndFailBeforeCommit(SessionCallback callback, Session session) {
Transaction tx = null;
try {
tx = session.beginTransaction();
callback.execute(session);
throw new RuntimeException("mreh");
} catch( RuntimeException e ) {
if(tx != null)
tx.rollback();
} finally {
session.close();
}
}
}