package org.genedb.db.audit; import org.gmod.schema.cfg.ChadoAnnotationConfiguration; import org.gmod.schema.cfg.ChadoSessionFactoryBean; import org.apache.log4j.Logger; import org.hibernate.CacheMode; import org.hibernate.Hibernate; import org.hibernate.SQLQuery; import org.hibernate.ScrollMode; import org.hibernate.ScrollableResults; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.hibernate.dialect.Dialect; import org.springframework.orm.hibernate3.SessionFactoryUtils; import org.springframework.transaction.annotation.Transactional; import java.sql.SQLException; import javax.annotation.Resource; public class HibernateChangeTracker implements ChangeTracker { private static final Logger logger = Logger.getLogger(HibernateChangeTracker.class); @Resource(name="sessionFactory") private SessionFactory sessionFactory; @Resource(name="&sessionFactory") private ChadoSessionFactoryBean sessionFactoryBean; @Override @Transactional public HibernateChangeSet changes(String key) throws SQLException { Session session = SessionFactoryUtils.getSession(sessionFactory, false); Number checkpointAuditIdInteger = (Number) session.createSQLQuery( "select audit_id from audit.checkpoint where key = :key" ).setString("key", key) .uniqueResult(); long checkpointAuditId = checkpointAuditIdInteger == null ? 0 : checkpointAuditIdInteger.longValue(); logger.debug("CheckPointAuditId: '" + checkpointAuditId + "'"); Configuration configuration = sessionFactoryBean.getConfiguration(); if (!(configuration instanceof ChadoAnnotationConfiguration)) { throw new RuntimeException(); } long currentAuditId = ((Number)session.createSQLQuery( Dialect.getDialect(configuration.getProperties()).getSequenceNextValString("audit.audit_seq") ).uniqueResult()).longValue(); logger.debug("Current Audit ID: " + currentAuditId); HibernateChangeSet changeSet = new HibernateChangeSet(session, key, currentAuditId); changeSet.setChadoAnnotationConfiguration((ChadoAnnotationConfiguration) configuration); processFeatureAuditRecords(checkpointAuditId, currentAuditId, changeSet); processFeatureRelationshipAuditRecords(checkpointAuditId, currentAuditId, changeSet); processFeatureLocAuditRecords(checkpointAuditId, currentAuditId, changeSet); return changeSet; } /** * @param session * @param checkpointAuditId * @param changeSet */ private void processFeatureAuditRecords(long checkpointAuditId, long currentAuditId, HibernateChangeSet changeSet) { Session session = SessionFactoryUtils.getSession(sessionFactory, false); SQLQuery sqlQuery = (SQLQuery) session.createSQLQuery( "select audit_id, feature_id, type, uniquename, type_id" + " from audit.feature" + " where audit_id > :checkpoint and audit_id < :currentAuditId" + " order by audit_id" ).addScalar("audit_id", Hibernate.INTEGER) .addScalar("feature_id", Hibernate.INTEGER) .addScalar("type", Hibernate.STRING) .addScalar("uniquename", Hibernate.STRING) .addScalar("type_id", Hibernate.INTEGER) .setLong("checkpoint", checkpointAuditId) .setLong("currentAuditId", currentAuditId); sqlQuery.setReadOnly(true); sqlQuery.setCacheMode(CacheMode.IGNORE); sqlQuery.setCacheable(false); sqlQuery.setFetchSize(1000); ScrollableResults sr = sqlQuery.scroll(ScrollMode.FORWARD_ONLY); boolean more = sr.next(); while (more) { int auditId = sr.getInteger(0); int featureId = sr.getInteger(1); String type = sr.getString(2); String uniqueName = sr.getString(3); int typeId = sr.getInteger(4); logger.trace(String.format("[%d] %s of feature '%s' (ID=%d)", auditId, type, uniqueName, featureId)); if (type.equals("INSERT")) { changeSet.insertedFeature(auditId, featureId, typeId); } else if (type.equals("UPDATE")) { changeSet.updatedFeature(auditId, featureId, typeId); } else if (type.equals("DELETE")) { changeSet.deletedFeature(auditId, featureId, typeId); } more = sr.next(); } } private void processFeatureRelationshipAuditRecords(long checkpointAuditId, long currentAuditId, HibernateChangeSet changeSet) { Session session = SessionFactoryUtils.getSession(sessionFactory, false); SQLQuery sqlQuery = (SQLQuery) session.createSQLQuery( "select feature_relationship.audit_id" + " , feature_relationship.type" + " , feature_relationship.feature_relationship_id" + " , feature_relationship.object_id" + " , feature.type_id" + " from audit.feature_relationship" + " join public.feature on feature.feature_id = feature_relationship.object_id" + " where audit_id > :checkpoint and audit_id < :currentAuditId" + " order by audit_id" ).addScalar("audit_id", Hibernate.INTEGER) .addScalar("type", Hibernate.STRING) .addScalar("feature_relationship_id", Hibernate.INTEGER) .addScalar("object_id", Hibernate.INTEGER) .addScalar("type_id", Hibernate.INTEGER) .setLong("checkpoint", checkpointAuditId) .setLong("currentAuditId", currentAuditId); sqlQuery.setReadOnly(true); sqlQuery.setCacheMode(CacheMode.IGNORE); sqlQuery.setCacheable(false); sqlQuery.setFetchSize(1000); ScrollableResults sr = sqlQuery.scroll(ScrollMode.FORWARD_ONLY); boolean more = sr.next(); while (more) { int auditId = sr.getInteger(0); String type = sr.getString(1); int featureRelationshipId = sr.getInteger(2); int featureId = sr.getInteger(3); int typeId = sr.getInteger(4); logger.trace(String.format("[%d] %s of feature_relationship ID=%d, " + "counts as update of object feature ID=%d (type ID=%d)", auditId, type, featureRelationshipId, featureId, typeId)); if (type.equals("INSERT") || type.equals("DELETE")) { changeSet.updatedFeature(auditId, featureId, typeId); } more = sr.next(); } } private void processFeatureLocAuditRecords(long checkpointAuditId, long currentAuditId, HibernateChangeSet changeSet) { Session session = SessionFactoryUtils.getSession(sessionFactory, false); SQLQuery sqlQuery = (SQLQuery) session.createSQLQuery( "select featureloc.audit_id" + " , featureloc.type" + " , featureloc.featureloc_id" + " , featureloc.srcfeature_id" + " , feature.type_id" + " from audit.featureloc" + " join public.feature on feature.feature_id = featureloc.srcfeature_id" + " where audit_id > :checkpoint and audit_id < :currentAuditId" + " order by audit_id" ).addScalar("audit_id", Hibernate.INTEGER) .addScalar("type", Hibernate.STRING) .addScalar("featureloc_id", Hibernate.INTEGER) .addScalar("srcfeature_id", Hibernate.INTEGER) .addScalar("type_id", Hibernate.INTEGER) .setLong("checkpoint", checkpointAuditId) .setLong("currentAuditId", currentAuditId); sqlQuery.setReadOnly(true); sqlQuery.setCacheMode(CacheMode.IGNORE); sqlQuery.setCacheable(false); sqlQuery.setFetchSize(1000); ScrollableResults sr = sqlQuery.scroll(ScrollMode.FORWARD_ONLY); boolean more = sr.next(); while (more) { int auditId = sr.getInteger(0); String type = sr.getString(1); int featureLocId = sr.getInteger(2); int featureId = sr.getInteger(3); int typeId = sr.getInteger(4); logger.trace(String.format("[%d] %s of featureloc ID=%d, " + "counts as update of source feature ID=%d (type ID=%d)", auditId, type, featureLocId, featureId, typeId)); if (type.equals("INSERT") || type.equals("DELETE")) { changeSet.updatedFeature(auditId, featureId, typeId); } more = sr.next(); } } }