michael wrote:
You can use the normal transaction handling code in a CMT environment (eg. session.beginTransaction(), tx.commit())
commiting the Hibernate transaction will not commit the underlying CMT transaction if it was not opened by session.beginTransaction(), that means you can simply integrate your transaction handling stuff portably into a CMT environment (and it will do a flush, too)
OK I think I ALMOST have this now.
I had modified my Persistent base class, HibernateSession (ThreadLocal) and DAO base class (HibernateDao) to do a flush and close on the session.
What I get from this is that I can do a begin and commit transaction instead.
Can you maybe give me some pseudo code for each of these?
i.e. StatelessSessionBean, Dao, Persistent...
Below is my actual code. I am a bit confused on the use of begin/commit vs flush/close. Specifically can you comment on where I would/should use begindTransaction/commit vs flush/close.
Note: my sessionBean will utilize the HibernateSession as well for currentConnection and closeConnection.
Thanks
Troy
---------------------------------
/**
* @author troy mckinnon
*/
public abstract class HibernateSupport {
public Log log = LogFactory.getLog(...);
private Session _session = null;
public HibernateSupport() throws HibernateException {}
public static void rollback(Transaction tx) {
try {
if (tx != null) {
tx.rollback();
}
} catch (HibernateException e) {
/* Eat this error..
if this point is reached
it is most likely another
error already occurred.
No point in burying the
original error. */
e.printStackTrace();
}
}
public Connection getConnection() throws HibernateException {
return currentSession().connection();
}
/**
* Shortcut to HibernateSession method
* @return
*/
public Session currentSession() throws HibernateException {
if (_session == null)
_session = HibernateSession.currentSession();
return _session;
}
/**
* @param jobOffer
*/
protected void saveOrUpdate(Persistent obj) throws HibernateException {
// TODO: ??? can't do transaction stuff.. if we want to use DAO in Session Bean (CMP)
// Transaction tx = currentSession().beginTransaction();
try{
// getSession().saveOrUpdate(obj);
System.out.println("Persisting");
obj.persist(currentSession());
// tx.commit();
} catch (HibernateException e) {
log.error(this, e);
throw e;
} catch (SQLException ex) {
log.error(this, ex);
throw new HibernateException( ex );
}finally {
close();
// if(tx != null){
// tx.commit();
// }
}
}
/**
* Use a single point to handle hibernate session.
* @see HibernateSession.closeSession()
*/
private void close() throws HibernateException {
HibernateSession.closeSession();
}
protected Persistent find(Class clazz, String id)
throws HibernateException {
Persistent existingItem = null;
existingItem = (Persistent)currentSession().load(clazz, id);
close();
return existingItem;
}
protected List find(String query) throws HibernateException {
System.out.println("Start of HibernateSupport.find() - " + query);
List list = currentSession().find(query);
close();
return list;
}
protected void delete(Persistent obj) throws HibernateException {
System.out.println("Start of HibernateSupport.delete()");
// Transaction tx =_session.beginTransaction();
try {
if (obj != null)
obj.delete(currentSession());
} catch (Exception e) {
// if(tx != null)
// tx.rollback();
} finally {
close();
// if(tx!=null)
// tx.commit();
}
System.out.println("End of HibernateSupport.delete()");
}
}
public class HibernateSession {
public static final ThreadLocal session = new ThreadLocal();
public static Session currentSession() throws HibernateException {
Session s = (Session)session.get();
if (s == null) {
SessionFactory sf = null;
try {
sf =
(SessionFactory)new InitialContext().lookup(
HIBERNATE_SESSION_FACTORY_JNDI);
if(sf==null) // need this for use with WSAD test environment. Reloading causes null reference in JNDI.
throw new NamingException("Session factory was null in JNDI");
} catch (NamingException e) {
sf =
new Configuration()
.configure(HIBERNATE_CONFIGURATION_URL)
.buildSessionFactory();
if(sf == null)
throw new HibernateException("Could not configure SessionFactory from resource - returned null " + HIBERNATE_CONFIGURATION_URL);
}
if(sf == null)
throw new HibernateException("Could not obtain SessionFactory from JNDI - returned null " + HIBERNATE_SESSION_FACTORY_JNDI);
s = sf.openSession();
session.set(s);
}
return s;
}
// TODO: Flush and close are necessary for CMT ???
// Flush: tells hibernate to execute any pending sql now.
// Close: releases database connection from Session. (This won't commit in CMT - container will manage that)
// TODO: might want to throw Hibernate exception here so that SessionBeans using this will
// be able to catch it and then do a setRollbackOnly() on the context.
public static void closeSession() throws HibernateException {
Session s = (Session)session.get();
session.set(null);
if (null != s && s.isOpen()) {
try {
s.flush();
} finally{
s.close();
}
}
}
}
public abstract class Persistent implements Lifecycle, Validatable, Marshalable, Serializable {
protected Serializable _id;
protected int _version;
protected Serializable getIdentifier() {
return _id;
}
public final void setId(Serializable id){
setIdentifier(id);
}
public final Serializable getId(){
return getIdentifier();
}
protected void setIdentifier(Serializable id) {
_id = id;
}
public int getVersion() {
return _version;
}
public void setVersion(int version) {
_version = version;
}
public Serializable persist(Session session) throws HibernateException, SQLException {
if(session == null) session = HibernateSession.currentSession();
session.saveOrUpdate(this);
return _id;
}
public Serializable persist() throws HibernateException, SQLException {
return persist(HibernateSession.currentSession());
}
public void delete() throws HibernateException, SQLException {
delete(HibernateSession.currentSession());
}
public void delete(Session session) throws HibernateException, SQLException {
if(session == null) session = HibernateSession.currentSession();
session.delete(this);
}
public void refresh(Session session) throws HibernateException, SQLException {
if(session == null) session = HibernateSession.currentSession();
session.load(this, _id);
}
public void refresh() throws HibernateException, SQLException {
refresh(HibernateSession.currentSession());
}
public void lock(Session session) throws HibernateException, SQLException {
if(session == null) session = HibernateSession.currentSession();
session.lock(this, LockMode.UPGRADE);
}
public void lock() throws HibernateException, SQLException {
lock(HibernateSession.currentSession());
}
public boolean onSave(Session s) throws CallbackException {
return NO_VETO;
}
public boolean onDelete(Session s) throws CallbackException {
return NO_VETO;
}
public boolean onUpdate(Session s) throws CallbackException {
return NO_VETO;
}
public void onLoad(Session s, Serializable id) {
_id = id;
}
/**
* Method validate
* <em>This was pulled down out of Caster POJO's</em>
*/
public void validate()
throws ValidationFailure {
org.exolab.castor.xml.Validator validator = new org.exolab.castor.xml.Validator();
try {
validator.validate(this);
} catch(ValidationException e) {
throw new ValidationFailure(e);
}
} //-- void validate()
/**
* <em>This was pulled down out of Caster POJO's</em>
* @return
*/
public boolean isValid() {
try {
validate();
} catch(ValidationFailure validationFailure) {
return false;
}
return true;
}
public void marshal(java.io.Writer out)
throws org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
Marshaller.marshal(this, out);
} //-- void marshal(java.io.Writer)
/**
* Method marshal
*
* @param handler
*/
public void marshal(org.xml.sax.ContentHandler handler)
throws java.io.IOException, org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
Marshaller.marshal(this, handler);
} //-- void marshal(org.xml.sax.ContentHandler)
}