org.compass.gps.device.hibernate.HibernateSyncTransaction Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of compass Show documentation
Show all versions of compass Show documentation
Compass Search Engine Framework
/*
* Copyright 2004-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.compass.gps.device.hibernate;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.compass.core.CompassException;
import org.compass.core.CompassSession;
import org.compass.core.spi.InternalCompassSession;
import org.compass.core.transaction.AbstractTransaction;
import org.compass.core.transaction.TransactionException;
import org.compass.core.transaction.TransactionFactory;
import org.hibernate.FlushMode;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.engine.SessionImplementor;
/**
* @author kimchy
*/
public class HibernateSyncTransaction extends AbstractTransaction {
private static final Log log = LogFactory.getLog(HibernateSyncTransaction.class);
private SessionFactory sessionFactory;
/**
* Did we start the Hibernate transaction
*/
private boolean newTransaction;
/**
* Is this the up most level controlling the Compass transaction
*/
private boolean controllingNewTransaction = false;
private InternalCompassSession session;
private boolean commitFailed;
private boolean commitBeforeCompletion;
private Transaction transaction;
public HibernateSyncTransaction(SessionFactory sessionFactory, boolean commitBeforeCompletion, TransactionFactory transactionFactory) {
super(transactionFactory);
this.sessionFactory = sessionFactory;
this.commitBeforeCompletion = commitBeforeCompletion;
}
public void begin(InternalCompassSession session) throws CompassException {
this.session = session;
try {
controllingNewTransaction = true;
SessionImplementor hibernateSession = ((SessionImplementor) sessionFactory.getCurrentSession());
newTransaction = !hibernateSession.isTransactionInProgress();
transaction = sessionFactory.getCurrentSession().getTransaction();
if (newTransaction) {
if (log.isDebugEnabled()) {
log.debug("Beginning new Hibernate transaction, and a new compass transaction on thread ["
+ Thread.currentThread().getName() + "]");
}
session.getSearchEngine().begin();
if (session.isReadOnly()) {
hibernateSession.setFlushMode(FlushMode.MANUAL);
}
transaction.begin();
} else {
// joining an exisiting transaction
session.getSearchEngine().begin();
if (log.isDebugEnabled()) {
log.debug("Joining an existing Hibernate transaction, starting a new compass transaction on thread ["
+ Thread.currentThread().getName() + "]");
}
}
transaction.registerSynchronization(new HibernateTransactionSynchronization(session, transaction, newTransaction, commitBeforeCompletion, transactionFactory));
} catch (Exception e) {
throw new TransactionException("Begin failed with exception", e);
}
setBegun(true);
}
/**
* Called by the factory when joining an already running compass transaction
*/
public void join(InternalCompassSession session) throws CompassException {
this.session = session;
controllingNewTransaction = false;
if (log.isDebugEnabled()) {
log.debug("Joining an existing compass transcation on thread [" + Thread.currentThread().getName() + "]");
}
}
protected void doCommit() throws CompassException {
if (!controllingNewTransaction) {
if (log.isDebugEnabled()) {
log.debug("Not committing Hibernate transaction since compass does not control it on thread ["
+ Thread.currentThread().getName() + "]");
}
return;
}
if (newTransaction) {
if (log.isDebugEnabled()) {
log.debug("Committing Hibernate transaction controlled by compass on thread ["
+ Thread.currentThread().getName() + "]");
}
try {
transaction.commit();
} catch (Exception e) {
commitFailed = true;
// so the transaction is already rolled back, by Hibernate spec
throw new TransactionException("Commit failed", e);
}
} else {
if (log.isDebugEnabled()) {
log.debug("Commit called, let Hibernate synchronization commit the transaciton on thread ["
+ Thread.currentThread().getName() + "]");
}
}
}
protected void doRollback() throws CompassException {
try {
if (newTransaction) {
if (log.isDebugEnabled()) {
log.debug("Rolling back Hibernate transaction controlled by compass on thread [" + Thread.currentThread().getName() + "]");
}
if (!commitFailed)
transaction.rollback();
} else {
if (log.isDebugEnabled()) {
log.debug("Marking Hibernate transaction as rolled back since compass controlls it on thread [" +
Thread.currentThread().getName() + "]");
}
// no way to mark a transaction as rolled back, assume throwing the exception will make it
// transaction.setRollbackOnly();
}
} catch (Exception e) {
throw new TransactionException("Rollback failed with exception", e);
}
}
public boolean wasRolledBack() throws TransactionException {
if (!isBegun())
return false;
if (commitFailed)
return true;
return transaction.wasRolledBack();
}
public boolean wasCommitted() throws TransactionException {
if (!isBegun() || commitFailed)
return false;
return transaction.wasCommitted();
}
public CompassSession getSession() {
return this.session;
}
private static class HibernateTransactionSynchronization implements Synchronization {
private static final Log log = LogFactory.getLog(HibernateTransactionSynchronization.class);
private InternalCompassSession session;
private Transaction tx;
private boolean compassControlledHibernateTransaction;
private boolean commitBeforeCompletion;
private TransactionFactory transactionFactory;
public HibernateTransactionSynchronization(InternalCompassSession session, Transaction tx,
boolean compassControlledHibernateTransaction, boolean commitBeforeCompletion,
TransactionFactory transactionFactory) {
this.transactionFactory = transactionFactory;
this.session = session;
this.tx = tx;
this.compassControlledHibernateTransaction = compassControlledHibernateTransaction;
this.commitBeforeCompletion = commitBeforeCompletion;
}
public void beforeCompletion() {
if (!commitBeforeCompletion) {
return;
}
if (log.isDebugEnabled()) {
log.debug("Committing compass transaction using Hibernate synchronization beforeCompletion on thread [" +
Thread.currentThread().getName() + "]");
}
session.getSearchEngine().commit(true);
}
public void afterCompletion(int status) {
try {
if (!commitBeforeCompletion) {
if (status == Status.STATUS_COMMITTED) {
if (log.isDebugEnabled()) {
log.debug("Committing compass transaction using Hibernate synchronization afterCompletion on thread [" +
Thread.currentThread().getName() + "]");
}
session.getSearchEngine().commit(true);
} else {
if (log.isDebugEnabled()) {
log.debug("Rolling back compass transaction using Hibernate synchronization afterCompletion on thread [" +
Thread.currentThread().getName() + "]");
}
session.getSearchEngine().rollback();
}
}
} catch (Exception e) {
// TODO swallow??????
log.error("Exception occured when sync with transaction", e);
} finally {
session.evictAll();
((HibernateSyncTransactionFactory) transactionFactory).unbindSessionFromTransaction(tx, session);
// close the session AFTER we cleared it from the transaction,
// so it will be actually closed (and only if we are not
// controlling the trnasction)
if (!compassControlledHibernateTransaction) {
session.close();
}
}
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy