Hibernate parts of AVM now based on Spring PlatformTransactionManager

abstraction.  Configurations to match.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3286 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Britt Park 2006-07-06 02:08:21 +00:00
parent c54b07f607
commit cdef918e07
8 changed files with 183 additions and 65 deletions

View File

@ -14,7 +14,7 @@
</bean> </bean>
<!-- A read only DefaultTransactionDefinition --> <!-- A read only DefaultTransactionDefinition -->
<bean id="readOnlyTransactionDefinition" <bean id="readTransactionDefinition"
class="org.springframework.transaction.support.DefaultTransactionDefinition"> class="org.springframework.transaction.support.DefaultTransactionDefinition">
<property name="propagationBehaviorName"> <property name="propagationBehaviorName">
<value>PROPAGATION_REQUIRES_NEW</value> <value>PROPAGATION_REQUIRES_NEW</value>
@ -92,11 +92,31 @@
</property> </property>
</bean> </bean>
<!-- The HibernateTransactionManager -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<!-- The Hibernate Transaction wrapper. --> <!-- The Hibernate Transaction wrapper. -->
<bean id="hibernateTxn" class="org.alfresco.repo.avm.hibernate.HibernateTxn"> <bean id="hibernateTxn" class="org.alfresco.repo.avm.hibernate.HibernateTxn">
<property name="sessionFactory"> <property name="sessionFactory">
<ref bean="sessionFactory"/> <ref bean="sessionFactory"/>
</property> </property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="readTransactionDefinition">
<ref bean="readTransactionDefinition"/>
</property>
<property name="writeTransactionDefinition">
<ref bean="writeTransactionDefinition"/>
</property>
</bean> </bean>
<bean id="orphanReaper" class="org.alfresco.repo.avm.OrphanReaper" <bean id="orphanReaper" class="org.alfresco.repo.avm.OrphanReaper"

View File

@ -12,6 +12,6 @@ hibernate.connection.isolation=2
hibernate.default_batch_fetch_size=16 hibernate.default_batch_fetch_size=16
hibernate.jdbc.batch_versioned_data=true hibernate.jdbc.batch_versioned_data=true
hibernate.cache.use_second_level_cache=true hibernate.cache.use_second_level_cache=true
hibernate.hbm2ddl.auto=create hibernate.hbm2ddl.auto=update
# AVM specific properties. # AVM specific properties.
avm.initialize=true avm.initialize=false

View File

@ -64,11 +64,59 @@
</property> </property>
</bean> </bean>
<!-- The HibernateTransactionManager -->
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="dataSource">
<ref bean="dataSource"/>
</property>
<property name="sessionFactory">
<ref bean="sessionFactory"/>
</property>
</bean>
<!-- A read only DefaultTransactionDefinition -->
<bean id="readTransactionDefinition"
class="org.springframework.transaction.support.DefaultTransactionDefinition">
<property name="propagationBehaviorName">
<value>PROPAGATION_REQUIRES_NEW</value>
</property>
<property name="isolationLevelName">
<value>ISOLATION_READ_COMMITTED</value>
</property>
<property name="readOnly">
<value>true</value>
</property>
</bean>
<!-- A write DefaultTransactionDefinition -->
<bean id="writeTransactionDefinition"
class="org.springframework.transaction.support.DefaultTransactionDefinition">
<property name="propagationBehaviorName">
<value>PROPAGATION_REQUIRES_NEW</value>
</property>
<property name="isolationLevelName">
<value>ISOLATION_READ_COMMITTED</value>
</property>
<property name="readOnly">
<value>false</value>
</property>
</bean>
<!-- The Hibernate Transaction wrapper. --> <!-- The Hibernate Transaction wrapper. -->
<bean id="hibernateTxn" class="org.alfresco.repo.avm.hibernate.HibernateTxn"> <bean id="hibernateTxn" class="org.alfresco.repo.avm.hibernate.HibernateTxn">
<property name="sessionFactory"> <property name="sessionFactory">
<ref bean="sessionFactory"/> <ref bean="sessionFactory"/>
</property> </property>
<property name="transactionManager">
<ref bean="transactionManager"/>
</property>
<property name="readTransactionDefinition">
<ref bean="readTransactionDefinition"/>
</property>
<property name="writeTransactionDefinition">
<ref bean="writeTransactionDefinition"/>
</property>
</bean> </bean>
<bean id="orphanReaper" class="org.alfresco.repo.avm.OrphanReaper" <bean id="orphanReaper" class="org.alfresco.repo.avm.OrphanReaper"

View File

@ -8,7 +8,7 @@ db.pool.max=32
# Hibernate properties # Hibernate properties
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
hibernate.current_session_context_class=thread hibernate.current_session_context_class=thread
hibernate.connection.isolation=2 hibernate.connection.isolation=4
hibernate.default_batch_fetch_size=16 hibernate.default_batch_fetch_size=16
hibernate.jdbc.batch_versioned_data=true hibernate.jdbc.batch_versioned_data=true
hibernate.cache.use_second_level_cache=true hibernate.cache.use_second_level_cache=true

View File

@ -956,7 +956,7 @@ public class AVMServiceImpl implements AVMService
} }
} }
HTxnCallback doit = new HTxnCallback(); HTxnCallback doit = new HTxnCallback();
fTransaction.perform(doit, false); fTransaction.perform(doit, true);
} }
/** /**

View File

@ -261,9 +261,11 @@ public class OrphanReaper implements Runnable
delete.setEntity("parent", node); delete.setEntity("parent", node);
delete.executeUpdate(); delete.executeUpdate();
} }
session.delete(node);
} }
else if (node instanceof PlainFileNode) else if (node instanceof PlainFileNode)
{ {
session.delete(node);
// FileContent should be purged if nobody else references it. // FileContent should be purged if nobody else references it.
FileContent content = ((PlainFileNode)node).getContent(); FileContent content = ((PlainFileNode)node).getContent();
if (content.getRefCount() == 1) if (content.getRefCount() == 1)
@ -272,10 +274,13 @@ public class OrphanReaper implements Runnable
session.delete(content); session.delete(content);
} }
} }
else
{
session.delete(node); session.delete(node);
} }
} }
} }
}
try try
{ {
HTxnCallback doit = new HTxnCallback(); HTxnCallback doit = new HTxnCallback();

View File

@ -0,0 +1,42 @@
/**
*
*/
package org.alfresco.repo.avm.hibernate;
import java.sql.SQLException;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateCallback;
/**
* This is a wrapper around HibernateTxnCallback implementation.
* @author britt
*/
public class HibernateCallbackWrapper implements HibernateCallback
{
/**
* The HibernateTxnCallback to execute.
*/
private HibernateTxnCallback fCallback;
/**
* Make one up.
* @param callback
*/
public HibernateCallbackWrapper(HibernateTxnCallback callback)
{
fCallback = callback;
}
/**
* Call the HibernateTxnCallback internally.
* @param session The Hibernate Session.
*/
public Object doInHibernate(Session session) throws HibernateException,
SQLException
{
fCallback.perform(session);
return null;
}
}

View File

@ -21,15 +21,14 @@ import java.util.Random;
import org.alfresco.repo.avm.AVMException; import org.alfresco.repo.avm.AVMException;
import org.alfresco.repo.avm.AVMNotFoundException; import org.alfresco.repo.avm.AVMNotFoundException;
import org.hibernate.HibernateException;
import org.hibernate.JDBCException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.dao.DataRetrievalFailureException; import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.dao.DeadlockLoserDataAccessException; import org.springframework.dao.DeadlockLoserDataAccessException;
import org.springframework.dao.OptimisticLockingFailureException; import org.springframework.dao.OptimisticLockingFailureException;
import org.springframework.orm.hibernate3.HibernateTemplate; import org.springframework.orm.hibernate3.HibernateTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
/** /**
* Helper for DAOs. * Helper for DAOs.
@ -38,9 +37,19 @@ import org.springframework.orm.hibernate3.HibernateTemplate;
public class HibernateTxn extends HibernateTemplate public class HibernateTxn extends HibernateTemplate
{ {
/** /**
* The SessionFactory. * The transaction manager.
*/ */
private SessionFactory fSessionFactory; private PlatformTransactionManager fTransactionManager;
/**
* The read transaction definition.
*/
private TransactionDefinition fReadDefinition;
/**
* The write transaction definition.
*/
private TransactionDefinition fWriteDefinition;
/** /**
* The random number generator for inter-retry sleep. * The random number generator for inter-retry sleep.
@ -56,16 +65,6 @@ public class HibernateTxn extends HibernateTemplate
fRandom = new Random(); fRandom = new Random();
} }
/**
* Set the Hibernate Session factory.
* @param factory
*/
public void setSessionFactory(SessionFactory factory)
{
super.setSessionFactory(factory);
fSessionFactory = factory;
}
/** /**
* Perform a set of operations under a single Hibernate transaction. * Perform a set of operations under a single Hibernate transaction.
* Keep trying if the operation fails because of a concurrency issue. * Keep trying if the operation fails because of a concurrency issue.
@ -74,44 +73,34 @@ public class HibernateTxn extends HibernateTemplate
*/ */
public void perform(HibernateTxnCallback callback, boolean write) public void perform(HibernateTxnCallback callback, boolean write)
{ {
Session sess = null;
Transaction txn = null;
while (true) while (true)
{ {
TransactionStatus status = null;
try try
{ {
sess = fSessionFactory.openSession(); status =
txn = sess.beginTransaction(); fTransactionManager.getTransaction(write ? fWriteDefinition : fReadDefinition);
callback.perform(sess); execute(new HibernateCallbackWrapper(callback));
txn.commit(); try
{
fTransactionManager.commit(status);
}
catch (TransactionException te)
{
throw new AVMException("Transaction Exception.", te);
}
return; return;
} }
catch (Throwable t) catch (Throwable t)
{ {
// TODO Add appropriate logging. if (!status.isCompleted())
if (txn != null)
{ {
try fTransactionManager.rollback(status);
{
txn.rollback();
}
catch (HibernateException he)
{
// Do nothing.
}
}
// Translate the exception.
if (t instanceof JDBCException)
{
t = convertJdbcAccessException((JDBCException)t);
}
else if (t instanceof HibernateException)
{
t = convertHibernateAccessException((HibernateException)t);
} }
// If we've lost a race or we've deadlocked, retry. // If we've lost a race or we've deadlocked, retry.
if (t instanceof DeadlockLoserDataAccessException) if (t instanceof DeadlockLoserDataAccessException)
{ {
System.err.println("Deadlock.");
try try
{ {
long interval; long interval;
@ -120,7 +109,6 @@ public class HibernateTxn extends HibernateTemplate
interval = fRandom.nextInt(1000); interval = fRandom.nextInt(1000);
} }
Thread.sleep(interval); Thread.sleep(interval);
continue;
} }
catch (InterruptedException ie) catch (InterruptedException ie)
{ {
@ -130,6 +118,7 @@ public class HibernateTxn extends HibernateTemplate
} }
if (t instanceof OptimisticLockingFailureException) if (t instanceof OptimisticLockingFailureException)
{ {
System.err.println("Lost Race.");
continue; continue;
} }
if (t instanceof AVMException) if (t instanceof AVMException)
@ -138,24 +127,38 @@ public class HibernateTxn extends HibernateTemplate
} }
if (t instanceof DataRetrievalFailureException) if (t instanceof DataRetrievalFailureException)
{ {
System.err.println("Data Retrieval Error.");
throw new AVMNotFoundException("Object not found.", t); throw new AVMNotFoundException("Object not found.", t);
} }
throw new AVMException("Unrecoverable error.", t); throw new AVMException("Unrecoverable error.", t);
} }
finally }
}
/**
* Set the transaction manager we are operating under.
* @param manager
*/
public void setTransactionManager(PlatformTransactionManager manager)
{ {
if (sess != null) fTransactionManager = manager;
}
/**
* Set the read Transaction Definition.
* @param def
*/
public void setReadTransactionDefinition(TransactionDefinition def)
{ {
try fReadDefinition = def;
}
/**
* Set the write Transaction Definition.
* @param def
*/
public void setWriteTransactionDefinition(TransactionDefinition def)
{ {
sess.close(); fWriteDefinition = def;
}
catch (HibernateException he)
{
// Do nothing.
}
}
}
}
} }
} }