-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 37 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
 Post subject: Use built in
PostPosted: Tue Mar 02, 2004 5:12 pm 
Regular
Regular

Joined: Mon Nov 03, 2003 6:10 am
Posts: 75
michael wrote:
You can also include the standard hibernate transaction handling in the code, it will integrate with a CMT and do a flush on commit, too (tx.commit() will not commit really when using CMT)


Michael,

what do you mean by use Hibernates built in handling. Can you provide some psuedo?



Also,

I have been trying to implement something similar to what is discussed in this thread. I am having trouble determining how to handle the use of 'flush' 'commit' and 'close' within a CMT.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 03, 2004 3:53 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
Look here:
http://www.hibernate.org/hib_docs/api/net/sf/hibernate/Session.html

A typical transaction should use the following idiom:
Code:
Session sess = factory.openSession();
Transaction tx;
try {
     tx = sess.beginTransaction();
     //do some work
     ...
     tx.commit();
}
catch (Exception e) {
     if (tx!=null) tx.rollback();
     throw e;
}
finally {
     sess.close();
}


With CMT I use this idiom:
Code:
HibernateUtil.openSession():
Context ctx = new InitialContext();
SessionFactory factory = (SessionFactory) ctx.lookup("java:/hibernate/ArsolHibernateFactory");
sess = factory.openSession();
....
Session session = null;
try
{
    session = HibernateUtil.openSession();
    .....
    session.flush(); // It is not obligatory, but I do it.
}
catch(..)
{
    sessionContext.setRollbackOnly();
    log.error(...)
}
finally
{
     if (null != session)
        session.close()
}

It works fine if you configured CMT support.
Using Hibernate With JBoss links:
http://www.hibernate.org/66.html
http://www.hibernate.org/82.html
http://nemesisit.rdsnet.ro/opendocs/simplearch/simplejboss.html


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 03, 2004 9:59 am 
Pro
Pro

Joined: Wed Oct 08, 2003 10:31 am
Posts: 247
shl wrote:
With CMT I use this idiom:
Code:
HibernateUtil.openSession():
Context ctx = new InitialContext();
SessionFactory factory = (SessionFactory) ctx.lookup("java:/hibernate/ArsolHibernateFactory");
sess = factory.openSession();
....
Session session = null;
try
{
    session = HibernateUtil.openSession();
    .....
    session.flush(); // It is not obligatory, but I do it.
}
catch(..)
{
    sessionContext.setRollbackOnly();
    log.error(...)
}
finally
{
     if (null != session)
        session.close()
}

It works fine if you configured CMT support.
...



How can "session.flush()" not be needed?
Without it, the changes were not being persisted by the Transaction Manager. When I put this line, then it began to work correctly.

Is there a reason for this?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 03, 2004 10:14 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
As I got, flush could be called before transaction commit.
http://www.hibernate.org/hib_docs/api/net/sf/hibernate/Transaction.html#commit()
Quote:
commit()
Flush the associated Session and end the unit of work.

Maybe it is a bug, post it to JIRA. Then inform us in that thread about results :).

I don't remember why I use session.flush(), maybe because I saw it in examples of using Hibernate with JBoss.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 03, 2004 10:22 am 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
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)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 03, 2004 3:12 pm 
Regular
Regular

Joined: Mon Nov 03, 2003 6:10 am
Posts: 75
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)





}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 03, 2004 3:18 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
You can do the following:

open session
* do stuff
session.flush()
session.close()

or

open session
tx = session.beginTransaction()
* do stuff
tx.commit()
session.close()

Both will provide identical results in a CMT environment, except the second one is also easier portable to a non-CMT environment.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 03, 2004 6:04 pm 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
michael,

It is a bad practice to mix Container Manager Transactions with HIbernate transactions (session.beginTransaction(); tx.commit()).

For example we have the following long transaction:
Code:
SessionFacade.doSmth: begin transaction
   AccountBean.check: debit checking account
   AccountBean.changeDebit: debit savings account
   AccountBean.changeCredit: credit savings account
   HistoryLogMDBean.logHistory: update history log
[list=]SessionFacade.doSmth: commit transaction

SessionFacade.doSmth -- managed by container
AccountBean.changeDebit -- managed by hibernate (hibernate trx.commit())
AccountBean.changeCredit -- managed by container[/list]

J2EE tutorial, "What Is a Transaction?"
Quote:
Either all three of these steps must complete, or none of them at all. Otherwise, data integrity is lost. Because the steps within a transaction are a unified whole, a transaction is often defined as an indivisible unit of work.


If you commit transaction manually using hibernate transaction API (tx.commit) this transaction falls from the global transaction context. Bankers will not appreciate if changeDebit is commited but changeCredit is not after some kind of exceptions :)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 03, 2004 6:07 pm 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
It is a good practice.
If you configured properly Hibernate, it'll delegate Tx to the JTA context and thus use the same Tx.
That's the whole purpose of Hibernate transaction API

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 03, 2004 6:44 pm 
Hibernate Team
Hibernate Team

Joined: Tue Sep 09, 2003 2:10 pm
Posts: 3246
Location: Passau, Germany
As I already said, tx.commit() will not really commit the transaction when you are in a CMT environment and the transaction was not started by Hibernate. You can see yourself in the code of net.sf.hibernate.transaction.JTATransaction


Top
 Profile  
 
 Post subject: new error
PostPosted: Wed Mar 03, 2004 6:57 pm 
Regular
Regular

Joined: Mon Nov 03, 2003 6:10 am
Posts: 75
I made the changes and now the items persist correctly EXCEPT I do get this error on the next FIND call.

identifier of an instance of com.avn.view.struts.wrapper.staffing.JobOffer altered from 768a2bd7-9ffc-44b7-9a93-2afdb2ae3a38 to
net.sf.hibernate.HibernateException: identifier of an instance of com.avn.view.struts.wrapper.staffing.JobOffer altered from 768a2bd7-9ffc-44b7-9a93-2afdb2ae3a38 to at net.sf.hibernate.impl.SessionImpl.checkId(SessionImpl.java:2606) at net.sf.hibernate.impl.SessionImpl.flushEntity(SessionImpl.java:2429) at net.sf.hibernate.impl.SessionImpl.flushEntities(SessionImpl.java:2422) at net.sf.hibernate.impl.SessionImpl.flushEverything(SessionImpl.java:2224) at net.sf.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:1769) at net.sf.hibernate.impl.SessionImpl.getQueries(SessionImpl.java:1536) at net.sf.hibernate.impl.SessionImpl.find(SessionImpl.java:1501) at net.sf.hibernate.impl.SessionImpl.find(SessionImpl.java:1491) at net.sf.hibernate.impl.SessionImpl.find(SessionImpl.java:1483) at com.avn.model.hibernate.dao.HibernateSupport.find(HibernateSupport.java:156) at


I think it is because of the ThreadLocal pattern. The session I am using must still have a reference to the old pojo or something?? not really sure.

all I am doing is the following:

protected List find(String query) throws HibernateException {
List list = HibernateSession.currentSession().find(query);
HibernateSession.closeSession();
return list;
}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Mar 04, 2004 4:28 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
michael wrote:
As I already said, tx.commit() will not really commit the transaction when you are in a CMT environment and the transaction was not started by Hibernate. You can see yourself in the code of net.sf.hibernate.transaction.JTATransaction

I understands nothing... And what is the purpose of that tx.commit() if it does not commit the transaction in the CMT environment? Only for possibility to port the code to non-CMT environment?

And one more question. Is it a bag that net.sf.hibernate.transaction.JTATransaction does not flush session before commit? And what is the default flush mode? And how to configure it (I mean configure via XML descriptors, not programmatically)?
Code:
public class JTATransaction implements Transaction {
...
public void commit() throws HibernateException {
                                                                                                                   ....                                                                                                                   
[b]                if ( session.getFlushMode()!=FlushMode.NEVER ) session.flush();[/b]
...}

nerotnt wrote:
How can "session.flush()" not be needed?
Without it, the changes were not being persisted by the Transaction Manager. When I put this line, then it began to work correctly.


Thanks,
Leonid


Top
 Profile  
 
 Post subject: read above
PostPosted: Thu Mar 04, 2004 4:33 am 
Regular
Regular

Joined: Mon Nov 03, 2003 6:10 am
Posts: 75
shl wrote:
michael wrote:
As I already said, tx.commit() will not really commit the transaction when you are in a CMT environment and the transaction was not started by Hibernate. You can see yourself in the code of net.sf.hibernate.transaction.JTATransaction

I understands nothing... And what is the purpose of that tx.commit() if it does not commit the transaction in the CMT environment? Only for possibility to port the code to non-CMT environment?


I included the transaction because of Michaels comments.

I am using session beans, but wanted to leave it flexible.
Since the tx doesn't really do anything. I did'nt see it hurting anything.


I actually modified my HibernateSession class to do a threadlocal for Session and Transaction. This way I can open and close tx just using the static currentSession and closeSession commands.

Troy


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 05, 2004 4:54 am 
Hibernate Team
Hibernate Team

Joined: Sun Sep 14, 2003 3:54 am
Posts: 7256
Location: Paris, France
shl wrote:
Only for possibility to port the code to non-CMT environment?

Yes and that's huge

shl wrote:
net.sf.hibernate.transaction.JTATransaction does not flush session before commit?

I'm happy with that (and use it actually).

_________________
Emmanuel


Top
 Profile  
 
 Post subject:
PostPosted: Fri Mar 05, 2004 5:07 am 
Expert
Expert

Joined: Fri Feb 06, 2004 7:49 am
Posts: 255
Location: Moscow, Russia
Hi emmanuel!

Yes, code protability. It is ok. But if you use three tx.commit() inside one CMT transaction you have one long business transaction. Yes?

But if you use the same code with those three tx.commit() outside CMT... How much transactions do you have?

Portability is cool, but I don't think that it is a good idea to use tx.commit() instead of session.flush() inside CMT environment. If you want that your CMT code will be portable to non-CMT env you need to think alot about each transaction, than you don't need CMT that make your life easier with transactions managed by container :)

emmanuel, I would like to ask how to set default session flush mode not programmatically, via XML descriptors?

Thanks,
Leonid


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 37 posts ]  Go to page Previous  1, 2, 3  Next

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.