-->
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.  [ 9 posts ] 
Author Message
 Post subject: Hibernate Transaction Demarcation in a non Web application.
PostPosted: Tue Feb 05, 2013 10:09 am 
Beginner
Beginner

Joined: Tue Feb 05, 2013 10:04 am
Posts: 20
Hello, I am new to Hibernate and I have some questions about transaction demarcations (I have already searched in Stack Overflow, the Hibernate Documentation.., but I haven't found the answer).

- First I generate the Hibernate Beans and DAOS with the Maven Hibernate Tools Plugin.

- After the generation process, I include my database access jar to my Java project.

Simple queries work fine, but when I execute complex queries with multiple joins, collections are not fetched (lazy fetching) and when I try to call the corresponding

get method to retrieve data, I get an lazy Initialization Exception since my session context is thread and the session has been closed with the transaction commit.

I need the session to live longer in order to fetch collections.

My hibernate cfg is:


<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.connection.url">jdbc:mysql://localhost:3306/mydatabase</property>
<property name="hibernate.connection.username">user</property>
<property name="hibernate.connection.password">1234</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.use_sql_comments">true</property>
</session-factory>
</hibernate-configuration>

In this case is it necessary to use JTA transactions (I don't use a Web Server) or is it possible to achieve longer sessions not attached to the transactions scope (JDBC)?


Thank you.


Top
 Profile  
 
 Post subject: Re: Hibernate Transaction Demarcation in a non Web application.
PostPosted: Wed Feb 06, 2013 8:29 am 
Beginner
Beginner

Joined: Tue Feb 05, 2013 10:04 am
Posts: 20
I have modified the hibernate tools code templates (ftl files) to generate custom DAOs and Beans.

With the Maven Hibernate Tools Plugin, I generate my database access layer.

Would it be reasonable to add to the Hibenate Beans, a method to reattach a detached object to a new Hibernate session? something like:

s.getCurrentSession().beginTransaction();
r.lock(p, LockMode.NONE);

once data would be retrieved by the getter method the transaction would be commited and the session would be closed. With this strategy I think the lazy initialization problem would be avoided.

Though I'm not sure if there would be any problems in multithread or multiprocess cases.


Thank you.


Top
 Profile  
 
 Post subject: Re: Hibernate Transaction Demarcation in a non Web application.
PostPosted: Wed Feb 06, 2013 8:29 am 
Beginner
Beginner

Joined: Tue Feb 05, 2013 10:04 am
Posts: 20
Is it possible to configure an Hibernate interceptor that executes before a getter method from an Hibernate Bean is called?

If this is possible, could the Hibernate Bean be attached to a session and detached after data is retrieved from database?

Thank you.


Top
 Profile  
 
 Post subject: Re: Hibernate Transaction Demarcation in a non Web application.
PostPosted: Thu Feb 07, 2013 10:12 am 
Beginner
Beginner

Joined: Tue Feb 05, 2013 10:04 am
Posts: 20
Hello where could I find a complete Hibernate 4 event listener example?

Is it possible to achieve on demand fetch of collections with listeners?

What is the best approach to fetch collections in a non web application with jdbc transactions?


Thank you.


Top
 Profile  
 
 Post subject: Re: Hibernate Transaction Demarcation in a non Web application.
PostPosted: Sun Feb 10, 2013 2:57 pm 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
Hi,
you can definitely use Hibernate without web servers: it's not coupled to it.

You would still need to open sessions and transactions; the problems you are referring to let me think that this tool you use to generate DAOs and other code is wrong, just avoid it and invoke Hibernate APIs directly, I'm sure you will find it much easier to understand what/when is going on.

On demand fetching of collection is automatic: it's the default behavior of Hibernate. Just make sure you don't close the session if you expect you still need to load something.

_________________
Sanne
http://in.relation.to/


Top
 Profile  
 
 Post subject: Re: Hibernate Transaction Demarcation in a non Web application.
PostPosted: Mon Feb 11, 2013 3:59 am 
Beginner
Beginner

Joined: Tue Feb 05, 2013 10:04 am
Posts: 20
Hello, thank you for your response.

My generated code is:

DAO:

Code:
public class ArtistDAOBase implements DaoElement
{
   
   private Transaction tx;
   
   private final SessionFactory sessionFactory = getSessionFactory();
       
        public SessionFactory getSessionFactory()
   {
      logInfo.info("[Class Artist] | getSessionFactory() : Getting new session factory");
      try
      {
        Configuration configuration = new Configuration();
        configuration.configure().setProperty("hibernate.show_sql", "false");
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()).buildServiceRegistry();
        logDebug.debug("[Class Artist] | getSessionFactory() : New session factory created successfully");
        return (configuration.buildSessionFactory(serviceRegistry));
      }
      catch (Exception e)
      {
         logError.error("[Class Artist] | getSessionFactory() : Could not locate SessionFactory in JNDI", e);
         throw new IllegalStateException("Could not locate SessionFactory in JNDI");
      }
   }

        protected void startOperation()
   {
      tx = sessionFactory.getCurrentSession().beginTransaction();
      logDebug.debug("[Class Artist] | startOperation() : New transaction started from current session.");
   }
   
   /**
       * Ends a transaction
       */
   public void endOperation()
   {
       tx.commit();
       logDebug.debug("[Class Artist] | endOperation() : Transaction commited, session ended.");
   }
       
         public List<Artist> findAll(int maxResults, int firstRow)
   {
      logInfo.info("[Class Artist] | findAll(int maxResults, int firstRow) : Getting all Artist instances");
      try
      {
         startOperation();
         Query query = sessionFactory.getCurrentSession().createQuery("from " + "Artist");
         query.setMaxResults(maxResults);
                        query.setFirstResult(firstRow);
         List<Artist> ret = (List<Artist>)query.list();
             endOperation();
         logDebug.debug("[Class Artist] | findAll(int maxResults, int firstRow) :  Get all Artist instances success");
         return ret;
      }   
      catch (RuntimeException re)
      {
         logError.error("[Class Artist] | findAll(int maxResults, int firstRow) : Get all Artist instances exception failure", re);
         throw re;
      }
   }
}

Bean Artist:

Code:
import java.util.HashSet;
import java.util.Set;


import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonElement;

public class Artist  implements java.io.Serializable, DboBean
{


  private Long id;
  private String name;
  private Set<Item> items = new HashSet<Item>(0);

   public Artist() {
   }
   
    public Long getId() {
        return this.id;
    }
   
    public void setId(Long id) {
        this.id = id;
    }
    public String getName() {
        return this.name;
    }
   
    public void setName(String name) {
        this.name = name;
    }
    public Set<Item> getItems() {
        return this.items;
    }
   
    public void setItems(Set<Item> items) {
        this.items = items;
    }
}


An artist is bound to one or more items, that's why the artist bean has an attribute items of type set.

Bean Item:

Code:
public class Item  implements java.io.Serializable, DboBean
{

  private Long id;
  private Artist artist;
  private int kind;
  private String name;
 
    public Item() {
    }
 
     public Long getId() {
        return this.id;
    }
   
    public void setId(Long id) {
        this.id = id;
    }

    public Artist getArtist() {
        return this.artist;
    }
   
    public void setArtist(Artist artist) {
        this.artist = artist;
    }
   
     public int getKind() {
        return this.kind;
    }
   
    public void setKind(int kind) {
        this.kind = kind;
    }
   
    public String getName() {
        return this.name;
    }
   
    public void setName(String name) {
        this.name = name;
    }
}


When I try to fetch an item from an artist I always get a Lazy initialization error since my session has been closed by the DAO in the method endoperation() with tx.commit. My sessions are always bound to transactions. I have generated this code with Hibernate tools and I am not sure if it is correct. My question is, would it be better to use opensession() instead of getcurrentsession()? Is it a good practice to manage sessions and transactions from the DAO or is it better to create a session manager? Should I leave the session open when I start group of database operations? When and where should I close the session? In my case I would like to encapsulate all the session and transaction management in my infrastructure layer, so I would no have to manage it in my domain layer, though this approach would limit the funtionality of my layer.

Many thanks.

Thank you for your help.


Top
 Profile  
 
 Post subject: Re: Hibernate Transaction Demarcation in a non Web application.
PostPosted: Mon Feb 11, 2013 5:39 am 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
The problem is in trying to handle the transactions in the DAO. This leads to your business logic (or whatever else needing to load these entities) to use the entities out of a transaction.

Avoid invoking _startOperation_ and _endOperation_ in the DAO: invoke start explicitly from your business logic code before needing any entity, and use the end operation after you don't need anything anymore, and want to potentially apply changes you have made to the entities.

_________________
Sanne
http://in.relation.to/


Top
 Profile  
 
 Post subject: Re: Hibernate Transaction Demarcation in a non Web application.
PostPosted: Mon Feb 11, 2013 6:13 am 
Beginner
Beginner

Joined: Tue Feb 05, 2013 10:04 am
Posts: 20
Thank you for your help. I am stuck with this session-transaction problem since last week.

I'm aware of the restriction it would mean that the management of the sessions and transactions is encapsulated in the DAO, but I would like to develop a kind of session and transaction manager that would permit both possibilities. Since this database module I'm trying to develop must be used in different applications, I would like it, the module, to be flexible.

Would it be possible to develop an interceptor or event listener that is able to detect a call to a get collection method in a bean and reattaches the Bean to a session in order to obtain the collection data? After that
could the session be closed with another event or interceptor?

Thank you for your advice and help.


Top
 Profile  
 
 Post subject: Re: Hibernate Transaction Demarcation in a non Web application.
PostPosted: Mon Feb 11, 2013 7:13 am 
Hibernate Team
Hibernate Team

Joined: Fri Oct 05, 2007 4:47 pm
Posts: 2536
Location: Third rock from the Sun
No you can't develop something like that and have it behave correctly, simply because if you use a different transaction the database might be inconsistent; for example the user you are using might not exist anymore, or point to a different user.

The pattern you're trying to implement is wrong, it's ok that you are developing a module used by different applications but you just have to mandate that all of them do their own transaction scope management.

_________________
Sanne
http://in.relation.to/


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 9 posts ] 

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.