Monday, July 29, 2013
Maven commands needed for a Portlet with service layer
Frequently Needed Maven commands in Liferay :
Tuesday, October 26, 2010
Hibernate Integration with Spring
Prerequisite Steps
1) Create java class (bean) Employee
2) Create Database and table employee
3) Create hbm.xml
4) make all mappings
3.4) Creating the Spring Configuration File
This section deals with configuring the various information needed for the Spring Framework. In Spring, all the business objects are configured in Xml file and the configured business objects are called Spring Beans. These Spring Beans are maintained by the IOC which is given to the Client Application upon request. Let us define a data source as follows,
spring-hibernate.xml
Refer : http://www.javabeat.net/articles/42-integrating-spring-framework-with-hibernate-orm-framewo-3.html
The above bean defines a data-source of type 'org.apache.commons.dbcp.BasicDataSource'
. More importantly, it defines the various connection properties that are needed for accessing the database. For accessing the MySql database, we need MySql database driver which can be downloaded from http://dev.mysql.com/downloads/connector/j/5.1.html. The first property called driverClassName
should point to the class name of the MySql Database Driver. The second property url represents the URL string which is needed to connect to the MySql Database. The third and the fourth properties represent the database username
and the password
needed to open up a database session.
Now, let us define the second Spring Bean which is the SessionFactoryBean
. If you would have programmed in Hibernate, you will realize that SessionFactoryBean
is responsible for creating Session
objects through which Transaction
and Data accessing is done. Now the same SessionFactoryBean
has to be configured in Spring's way as follows,
Refer :
http://www.javabeat.net/articles/42-integrating-spring-framework-with-hibernate-orm-framewo-3.html
To make the SessionFactoryBean
to get properly configured, we have given two mandatory information. One is the data-source information which contains the details for accessing the database. This we have configured already in the previous step and have referred it here using the 'ref'
attribute in the 'property'
tag. The second one is a list of Mapping files which contains the mapping information between the database tables and the Java class names. We have defined one such mapping file in section 2 and have referenced the same here with the 'list'
tag.
The 3rd important Spring Bean is the Hibernate Template. It provides a wrapper for low-level data accessing and manipulation. Precisely, it contains methods for inserting/delting/updating/finding data in the database. For the Hibernate Template to get configured, the only argument is the SessionFactoryBean
object as represented in the following section,
Refer : http://www.javabeat.net/articles/42-integrating-spring-framework-with-hibernate-orm-framewo-3.html
The final Bean definition is the Dao class which is the client facing class. Since this class has to be defined in the Application level, it can contain any number of methods for wrapping data access to the Client. Since we know that it is the Hibernate Template class that interacts with the database, it will be ideal a refer an instance of Hibernate Template to the Dao class.
Refer : http://www.javabeat.net/articles/42-integrating-spring-framework-with-hibernate-orm-framewo-3.html
Reference Link : http://www.javabeat.net/articles/
42-integrating-spring-framework-with-hibernate-orm-framewo-1.html
Tuesday, July 27, 2010
Lazy Initilization in Hibernate
when loading an object that has a collection, hibernate loads collection elements ONLY when actually you ask for them; so this improves performance.
2) lazy initialization improves performance by delaying the fetch from the database until the returned object is actually queried for the data...it works similar to write behind caching on your hard disk ;-) .
3)
when you use hibernate you can make lazy=true or lazy=false.
if you mentioned lazy=true
and you call from a company bean like
Collection x = company.getAllEmployees();
x will be empty;
if u mentioned lazy=false
x will contain the data as output of the getter funtion.
So if you put lazy=true then you need to write HQL query getting these kind of collections. else if lazy = false u can get the collection at the time when u fetch company object.
So taking performance(time cost and memory cost) as criteria the its better to make lazy=true.
Tuesday, June 29, 2010
Basic Spring AOP Tutorial
Aspect-Oriented Programming (AOP) complements Object-Oriented Programming (OOP) by providing another way of thinking about program structure. The key unit of modularity in OOP is the class, whereas in AOP the unit of modularity is the aspect. Aspects enable the modularization of concerns such as transaction management that cut across multiple types and objects.
AOP concepts:
• Aspect: a modularization of a concern that cuts across multiple classes. Transaction management is a good example of a crosscutting concern in J2EE applications. In my words: a trigger which can affect the multiple classes a one point….
• Join point: a point during the execution of a program, such as the execution of a method or the handling of an exception. In Spring AOP, a join point always represents a method execution. In my words: a locus of points where execution will happen.
• Advice: action taken by an aspect at a particular join point. Different types of advice include “around,” “before” and “after” advice. (Advice types are discussed below.) In my words : the action to be taken at the point.
• Pointcut: a predicate that matches join points. Advice is associated with a pointcut expression and runs at any join point matched by the pointcut (for example, the execution of a method with a certain name). The concept of join points as matched by pointcut expressions is central to AOP, and Spring uses the AspectJ pointcut expression language by default. In my words a criteria used to locate point.
• Introduction: declaring additional methods or fields on behalf of a type. Spring AOP allows you to introduce new interfaces (and a corresponding implementation) to any advised object. For example, you could use an introduction to make a bean implement an IsModified interface, to simplify caching. (An introduction is known as an inter-type declaration in the AspectJ community.)
• Target object: object being advised by one or more aspects. Also referred to as the advised object. Since Spring AOP is implemented using runtime proxies, this object will always be a proxied object.
• AOP proxy: an object created by the AOP framework in order to implement the aspect contracts (advise method executions and so on). In the Spring Framework, an AOP proxy will be a JDK dynamic proxy or a CGLIB proxy.
Consider the example:
Lets declare an interface:
public interface Foo {
Foo getFoo(String fooName,int age);
void getAfter();
void getBefore(String myName);
}
A class implementing the interface:
public class DefaultFooService implements FooService {
public Foo getFoo(String name, int age) {
return new Foo(name, age);
}
public void getAfter() {}
public void getBefore(String myName) {}
}
Till here we have simple java implementation.
Now let see come AOP concepts in picture.
Before - Now I want that before the getBefore() method is called I want to log message saying what is the parameter passed.
After - Also I want that once any method in the interface is called a message should be logged after it.
I have a class which will be called to satisfy the above criteria.
public class SimpleProfiler {
public void afterMethod() throws Throwable {
System.out.println(“After the method call”);
}
public void beforeMethod(String myName){
System.out.println(“My name is “+myName);
}
}
The afterMethod() will log message after any method is called and beforeMethod() will log message before getBefore() is called.
To configure this we will used xmlThis is how I configure my spring.xml.
<beans xmlns=“http://www.springframework.org/schema/beans”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xmlns:aop=“http://www.springframework.org/schema/aop”
xsi:schemaLocation=“http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd”>
<!– this is the object that will be proxied by Spring’s AOP infrastructure –>
1 <bean id=“fooService” class=“DefaultFooService”/>
2
3 <!– this is the actual advice itself –>
4 <bean id=“profiler” class=“SimpleProfiler”/>
5
6 <aop:config>
7 <aop:aspect ref=”profiler”>
14 <aop:pointcut id=“aopafterMethod”
expression=“execution(* FooService.*(..))”/>
15 <aop:after pointcut-ref=“aopafterMethod”
method=“afterMethod”/>
16 <aop:pointcut id=“aopBefore”
expression=“execution(* FooService.getBefore(String)) and args(myName)”/>
17 <aop:before pointcut-ref=“aopBefore”
method=“beforeMethod”/>
</aop:aspect>
</aop:config>
</beans>
Let see how we have configure the AOP .
Similarly for beforeMethod we define in Line 16,17.
In above example we have
Aspect – SimpleProfiler.class
Point-cut – aopafterMethod,aopBefore
Advice <aop:before> <aop:after>
Now I am ready to run my main class and class methods of FooService.
public class Boo {
public static void main(final String[] args) throws Exception {
BeanFactory ctx = new ClassPathXmlApplicationContext("spring.xml");
FooService foo = (FooService) ctx.getBean("fooService");
foo.getFoo("Pengo", 12);
foo.getAfter();
foo.getBefore("Manish");
}
}
OutPut is
After the method call ( log messagefor getAfter method )
My name is Manish (log message for getBefore)
After the method call (log message for getAfter method)
Saturday, June 26, 2010
Hibernate Object States/LifeCycle
Hibernate Object States/LifeCycle
Let's start off with the basics. Now imagine you have a JPA annotated User class, and you create an instance of it using the following code:
AdminUser u = new AdminUser ();
Will Hibernate automatically persist this object, given just this line of code alone? Of course not! When you create an object in your Java code, even if your application does use the Hibernate framework for persistence, the newly created instance will exist only in the memory of the Java program that created it, and Hibernate has nothing to do with it. In fact, there's a special term we use to describe objects in Java programs that have been instantiated, but have not been placed under the spell of the Hibernate Session; such instances are referred to as transient instances, as their state is never persisted to the database.
From Transient to Persistent
tran-sient [tran-shuhnt, -zhuhnt, -zee-uhnt] adjective 1. not lasting, enduring, or permanent; transitory. 2. lasting only a short time; existing briefly; temporary: transient authority. 3. staying only a short time
transient instance: a transient instance is one that is instantiated within a Java program, but is not managed by, or connected in any way to a Hibernate Session. Furthermore, transient objects do not have any existing representation in a database.
Now, if you create an instance of a class in your Java code, and you want Hibernate to manage the persistent state of that object, you have to associate you're newly created instance with the magical Hibernate Session. There are a number of ways to do this, with the easiest probably being to simply pass the Java instance to the saveOrUpdate method of the Hibernate Session.
AdminUser u = new AdminUser (); // transient at this point
session.saveOrUpdate(u); // no longer transient
Once an instance of a JavaBean has been associated with the Hibernate Session, it is no longer a transient instance, but instead, becomes what we call a persistent object, and the persistent state of the instance is then managed by the Hibernate Session for the duration of the transaction.
Now, that previous sentence was quite a mouthful, especially the part about the duration of the transaction. You see, whenever you want to perform any of the basic CRUD operations, you must first initiate a transaction, and when you are done, you must close the transaction. Don't let anyone tell you differently; that's the way database operations work.
The Transactional Context
As I said, any time you want Hibernate to manage the persistence of your JavaBeans, you must first initiate a transaction, which is just a simple method call on the Hibernate Session.
hibernateSession.beginTransaction();
Once you being a transaction, you can start associating your POJOs and JavaBeans with the Hibernate Session. If you don't initiate a transaction, you'll get a runtime exception telling you about no transactional context being in existence, and at all costs, we want to avoid runtime exceptions.
Now, the really cool thing about Hibernate is the fact that once a transaction has been started, all you have to do is associate an instance with the Session, and then Hibernate will take care of fully managing the persistent state of that instance, right up to and including the point where you commit the transaction. When you finally commit the transaction, the state of all of the POJO's that have been associated with the Hibernate Session will be saved to the database.
The following snippet of code demonstrates the art of beginning a transaction, creating an instance, associating that instance with the Hibernate Session, and then finally, committing the transaction:
hibernateSession.beginTransaction();
AdminUser user = new AdminUser ();
hibernateSession.saveOrUpdate(user);
hibernateSession.getTransaction().commit();
In this code snippet, a new transaction is created, after which a brand new, unassociated, transient instance of a User is created. This instance is then associated with the Hibernate Session when it is passed as an argument to the saveOrUpdate() method of the session, transitioning the instance from being a transient instance, to a persistent instance.
Affection for the saveOrUpdate Method
Now, I don't actually like the saveOrUpdate method. I mean, I love using it, but I don't really like the name, because I think the name is a little bit misleading as it implies that an instance that is passed to the method will be saved, or updated, immediately. You see, that's only partly true. Sure, when the saveOrUpdate method is invoked, the instance will eventually have its state persisted to the database, but more happens that just that. The instance in not only queued up for a database save, but the Hibernate Session keeps track of that instance, and if any further changes happen to the instance before the transaction is committed, then those changes to the instance's state will be persisted as well. I'd almost prefer it if the saveOrUpdate method was renamed to something more descriptive like saveOrUpdateAndAssociateInstanceWithSession, but then again, I guess there is an upper limit on how long good method names should be.
Take a look at the following code snippet:
Session session=HibernateUtil.beginTransaction();
User user = new User();
user.setPassword("abc123");
session.save(user);
user.setLoginName("mj");
user.setPassword("abc123");
user.setEncryptedPassword("zab012");
user.setEmailAddress("mj@scja.com");
user.setLastAccessTime(new java.util.Date());
user.setRegistrationDate(
new java.util.GregorianCalendar());
user.setVerified(Boolean.FALSE);
HibernateUtil.commitTransaction();
Notice that in this code snippet, an instance of the user class is created, the password is set to abc123, and then the save method of the Hibernate Session is passed the instance. The call to the save method triggers the following SQL statement to be executed against the database:
insert into examscam.user
(emailAddress, lastAccessTime, login_name, password, registrationDate, verified)
values (?, ?, ?, ?, ?, ?)
So, when the save method is invoked on the Hibernate Session, the state of the instance, which is really nothing more than a primary key and a password in this example, is persisted to the database. But look at the original code snippet, and see what happens after the save method is invoked. A bunch of other properties of the User instance are modified, and then the transaction is committed. The question is, will these changes to the state of the User instance be persisted to the database, or will the database only contain the primary key and the password once the transaction is committed? Well, in fact, all of the changes to the instance that took place even after the save method was invoked on the Hibernate Session will be persisted to the database. As the transaction is committed, Hibernate will issue the following SQL statement against the database:
update examscam.user set emailAddress=?, lastAccessTime=?, login_name=?, password=?, registrationDate=?, verified=? where id=?
You see, that's the great thing about Hibernate: as soon as an instance is associated with the Session, be it through a load, get, update or save invocation, the state of that instance will be managed by Hibernate right up to the point in which the current transaction is committed. Hibernate will keep track of any changes that happen to the instance throughout the course of the transaction, and update the corresponding record in the database accordingly.
Proper Hibernate Coding Practices
I often see developers that are new to Hibernate constantly calling the saveOrUpdate method whenever a set of changes have been made to a POJO. This isn't necessary. You only have to associate an instance with the Hibernate Session once within the scope of a transaction. From that point on, you can do whatever you want to your JavaBean instances. Hibernate will persist the final state of your instance when the current transaction is finally committed.
The following piece of code needlessly calls the saveOrUpdate method after instance variables have been updated. This is totally unnecessary, as the User instance was already associated with the Hibernate Session through the original call to saveOrUpdate.
hibernateSession.getTransaction();
User user = new User();
hibernateSession.saveOrUpdate(user);
user.setLoginName("mj");
user.setPassword("abc123");
hibernateSession.saveOrUpdate(user); /*This is BAD!*/
hibernateSession.getTransaction().commit();
With the first call to saveOrUpdate, the instance named u becomes associated with the Hibernate session. From that point on, you can mess around with the user instance as much as you want, and Hibernate will take care of the persistence. You can initialize, update, change, and modify any instance variable of the user instance that you want, and Hibernate will save the final state of the instance once the transaction has been committed..
hibernateSession.getTransaction();
User user = new User();
hibernateSession.saveOrUpdate(user);
user.setLoginName("Manish Jaiswal");
user.setPassword("abc123");
hibernateSession.getTransaction().commit();
Loading Instances and the Hibernate Session
Of course, the saveOrUpdate method, along with the save method, is great for associating brand new instances with the Hibernate Session, but more often than not, you'll want to pull a previously persisted instance from the database into your Java program, perhaps so you can update the instance and subsequently persist that new information to the database. For pulling existing instances out of the database, while at the same time, ensuring they are associated with the Hibernate Session for persistence management, we use either the load or the get method of the Hibernate Session.
Note that the load method is intended to be used when you know an instance actually exists in the database. This method actually returns proxy objects that alleviate database hits until transaction commit time, making it a little more efficient. The get method is better used when you don't know for sure if the instance you are loading, or getting, actually exists in the database.
Calling the load or get method on the Hibernate Session in order to obtain a persistent object from the database not only provides you access to the instance of interest, but it also associates that instance with the Hibernate Session. Take a look at the following code, which pulls an instance of a User out of the Hibernate Session.
Session hibernateSession = this.getCurrentSession();
hibernateSession.beginTransaction();
User u = (User)hibernateSession.get(User.class, 2);
u.setLoginName("manish");
u.setPassword("password");
hibernateSession.getTransaction().commit();
Notice that after updating the properties of the instance, namely the loginName and password, that we simply ask the Hibernate Session to commit the transaction, which will in turn, update the database. There is no need to call the saveOrUpdate method after changing the attributes of the instance, because the instance is already associated with the Hibernate Session, and as a result, any changes to the state of the persistent instance will be updated in the database.
Rushing the Update with a flush()
As you know, the Hibernate Session will be keeping track of all of the updates that happen to instances that are associated with it, and as you could imagine, the list of updates that may need to be committed might end up getting quite large. Using the default configuration of Hibernate, you can never be totally sure when the updates will be committed to the database; all you can be sure of is that once the transaction has been committed, the updates have happened. However, if you have some compelling reason to rush the updates, and have them sent immediately to the database, you can call the flush() method on the Hibernate Session.
FlushMode
You can override the default flushing behavior of the Hibernate Session if you so desire. To have more control over how and when Hibernate will flush the changes that the Session is marinating, you can set the Session's FlushMode. There are five flush modes, although one has been deprecated. They are:
- AUTO - the Session is typically flushed before query execution to ensure query results do not contain stale data
- ALWAYS - the Session is flushed before every query
- COMMIT - the Session is flushed when the transaction.commit() method is called
- MANUAL - the Session is only flushed when the flush() method is invoked on the Session
There is also a FlushMode of NEVER, although this has been deprecated, and the use of the MANUAL setting is promoted instead.
The opposite of flush()? refresh()?
So, if flush() takes the state of all of the instances in the Hibernate Session and forces a database update, I guess the Session's refresh() method could be considered the flush() method's inverse, as the refresh method is conversely passed a persistent instance, and Hibernate is asked to go to the database and update the already associated instance's properties with the data stored in the database.
For the most part, you won't likely run into too many circumstances where a persistent instance has fallen out of favor with the Hibernate Session, but if you believe such a thing has happened, perhaps due to a set of batch updates that may have been kicked off, or even due to some direct JDBC calls that may have sidestepped the Hibernate Session, calling the refresh method just might be required.
Here's the Hibernate API JavaDoc on the Session's refresh() method. Note the warning they give about the appropriate use of the method:
public void refresh(Object object) throws HibernateException
Parameters: object -a persistent or detached instance
Re-read the state of the given instance from the underlying database. It is inadvisable to use this to implement long-running sessions that span many business tasks.
This method is, however, useful in certain special circumstances:
-- where a database trigger alters the object state upon insert or update
-- after executing direct SQL (eg. a mass update) in the same session
-- after inserting a Blob or Clob
Terminology Review: Transient and Persistent
Transient instances are JavaBean instances that exist in your application, but do not have a representation in the database, and are not associated with a Hibernate Session.
A persistent instance is one that not only exists in your application code, but is also associated with a Hibernate Session within the scope of an active transaction, so that when the transaction is committed, the state of that instance will be persisted to the database.
Detached Instances
Okay, so we have a great appreciation for the fact that as soon as an instance has been associated with a Hibernate Session, Hibernate will take responsibility for the persistent state of that object until the current transaction is committed. But what happens after the transaction is committed? For example, take a look at the following code:
Session session=HibernateUtil.beginTransaction();
User user = new User();
user.setLoginName("manishjaiswal");
user.setPassword("111111111");
session.save(user);
user.setPassword("22222222");
HibernateUtil.commitTransaction();
user.setPassword("33333333")
So, if you peaked into the database after running this code snippet, what would the value of the password be for the associated database record? Would it be 111111111, 222222222 333333333? The answer is 2222222, since the instance is first persisted to the database with the value 11111111, then, as the transaction is committed, the password is updated to 2222222. But when the final Java based update to the password field is done, there is no open transaction, and Hibernate has no context with which it can update the user's password to cccccc.
After the transaction has been committed, the User instance is said to be a detached instance, because the instance is no longer associated with a Hibernate Session, and no mechanism exists to tie the state of the instance to the database.
Programmatically Detaching Instances
Sometimes you may have an instance whose persistent state is being managed by the Hibernate Session, but then, for some reason, you want to shake that instance free of Hibernate's grasp. If you can't wait for a transaction to commit and have the instance naturally become detached, you can explicitly detach an instance from the Hibernate Session by simply calling the evict method of the Session, just as I do in this following snippet of code:
Session session=HibernateUtil.beginTransaction();
User user = new User();
user.setLoginName("manish jaiswal");
user.setPassword("aaaaaa");
session.save(user);
session.evict(user);
user.setPassword("bbbbbb");
HibernateUtil.commitTransaction();
So, after the transaction is committed in this snippet of code, what value would the password column for the user's corresponding database record be? Would it be null, aaaaaa or bbbbbb? Well, the correct answer is aaaaaa.
You see, the instance has its password initialized to aaaaaa, after which it is passed to the save method of the Hibernate Session, and the Hibernate Session does just that - it saves the state of the instance. However, we programmatically evict the instance from the Session, at which point, Hibernate wipes its hands clean of any further changes to the User instance. The instance indeed has a representation in the database, but the evict method has detached the instance from its underlying representation, so further changes to the state of the User instance, such as the changing of the password to bbbbbb, are no longer the concern of the Hibernate Session, and such changes are not persisted to the database.
Object Comparisons
Once you start mixing and matching persistent and detached objects within your code, which pretty much any J2EE application will do at some point in time, you will find some not-so-funny, and potentially non-intuitive, problems that come up when you start doing comparisons of instances that you would think would be the same.
For example, take a look at the following code that creates two instances, user1 and user2, based on the same, identical, database record. What do you think the output of the code snippet would be?
Session session=HibernateUtil.beginTransaction();
User user1 = new User();
user1.setPassword("aaaaaa");
Long id = (Long)session.save(user1);
session.evict(user1);
User user2 = (User)session.get(User.class, id);
System.out.print("The instances are the same: ");
System.out.println( user1.equals(user2));
HibernateUtil.commitTransaction();
Since both instances of the User class are based on the same database record, they will have all of their properties set to the same values, which means the two objects are essentially the same, but the comparison of the two objects returns false. It's somewhat non-intuitive, but if you know what's going on under the covers of the Java Virtual Machine, it actually makes sense.
By default, when you compare two instances using .equals(), the compiler simply compares the memory locations of the two instances, as opposed to comparing their actual property values. Since we have two separate instances, we end up having two separate memory locations, and a .equals() comparison returns false. To overcome such situations, a Hibernate best practice is to have all of your JPA annotated classes properly override the inherited .hashcode() and .equals() methods, providing an implementation that makes sense for the class. That way, when two instances with exactly the same state are compared, the actual properties the object contains will be compared, and the compiler will not simply look at the memory locations of objects when performing an equality comparison.
The org.hibernate.NonUniqueObjectException
So, as we have seen, the following code snippet creates two instances, user1 and user2, both of which share the same set of properties, but with the main difference being the fact that user1 becomes a detached object after the evict(user1); method is called, whereas the instance user2 is a persistent object right up until the point that the transaction gets committed. Here's the code:
Session session=HibernateUtil.beginTransaction();
User user1 = new User();
user1.setPassword("aaaaaa");
Long id = (Long)session.save(user1);
session.evict(user1);
User user2 = (User)session.get(User.class, id);
HibernateUtil.commitTransaction();
Now, what do you think would happen if you changed some values in the detached instance, user1, and then tried to use the Hibernate Session to update that instance, considering the fact that user2, an instance that shares its id with user1, is already associated with the Hibernate Session? What would happen if you tried to run the following code:
Session session=HibernateUtil.beginTransaction();
User user1 = new User();
user1.setPassword("aaaaaa");
Long id = (Long)session.save(user1);
session.evict(user1);
User user2 = (User)session.get(User.class, id);
user1.setVerified(true);
session.saveOrUpdate(user1);
HibernateUtil.commitTransaction();
Well, here's another rule that Hibernate strictly enforces: only one instance of a class with a given unique primary key can be associated with the Session at a time. In this case, if we try to re-associate the evicted user1 with the Hibernate Session, Hibernate will kick out to us a NonUniqueObjectException, indicating that it is already managing an instance that represents that particular database record. So, Hibernate will gladly manage your unique instances, but fundamentally, it is that primary key that makes an object unique, and the developer must be careful not to add a second, non-unique instance of a class to an active Hibernate Session.
A Little Bit About Transactions
One of the things that you should know about a transaction is that it is an all or nothing type of thing. When you start a transaction, you can associate as many instances with your Hibernate Session as you like. Furthermore, you can perform an unlimited number of loads, gets, saves, updates, evictions or refreshes while a transaction is in progress. Hibernate, and the Hibernate Session, will keep track of all of your various method calls and state changes, and finally, when the transaction is committed, Hibernate will persist all of your changes to the database.
However, sometimes, when you are committing a transaction, something can go wrong. There are a multitude of reasons why a database write might fail, be it database deadlocking, or simply a connection timeout. But regardless of why a transaction fails, if a transaction does fail, all of the changes or updates that have taken place within that transaction are completely rolled back, taking the database back to the state it was in before the transaction was even started. Furthermore, if you have any instances in scope while the transaction failed, those instances will become detached instances, because the transaction and the Hibernate Session with which they were associated are junked, and no longer capable of persisting the state of your data. Furthermore, while data in the database will be rolled back to the state it was in before the transaction was committed, any JavaBeans that are still in scope will not have their internal state rolled back, making them out of sync with the database if they did have their state updated during the course of the failed transaction.
Any time we commit a transaction, the possibility of an exception being thrown looms large. As a result, if an exception does occur during the committing of a transaction, it is a best practice to catch the exception, explicitly rollback the transaction, and finally, close the session. Furthermore, since all of the POJO instances have become detached from the database, and are no longer under the Hibernate Session's spell, those instances should be allowed to simply go out of scope and be garbage collected, as they are no longer in sync with the database.
Finally, you can either re-throw the HibernateException, or potentially, throw a custom application exception that will be appropriately handled by an upper application layer, providing an appropriately formatted error message to the end user.
try {
Session hibernateSession = this.getCurrentSession();
hibernateSession.beginTransaction();
User u = (User)hibernateSession.get(User.class, 2);
hibernateSession.evict(u); /* u is now detached */
u.setLoginName("Joey");
u.setPassword("shabidew");
hibernateSession.getTransaction().commit();
} catch (HibernateException e) {
e.printStackTrace();
hibernateSession.getTransaction().rollback();
hibernateSession.close();
throw e;
}
In Summary
So, when we create instances in our Java code, the instance is considered to be a transient instance, which means there is no mechanism in place to manage the persistent state of that instance. However, once we pass a transient instance to the save, update, or saveOrUpdate method of the Hibernate Session, we consider the transient instance to have transitioned into a persistent instance, as Hibernate will begin to manage the persistent state of that instance. Any instance associated with the Hibernate Session is said to be a persistent instance.
Saving or updating a JavaBean isn't the only way to get your hands on a persistent instance. JavaBeans that have been loaded into the Hibernate Session, either by a get or load method call, or even an HQL or criteria query, are considered to be persistent instances, and as such, any changes or updates to the state of those instances will be persisted to the database by the Hibernate Session as well.
If you do have an instance that you want to release from Hibernate's control, you can always call the evict method of the Hibernate Session, passing in the name of the instance you want freed from Hibernate's control. When an instance is no longer having its state managed by the Hibernate Session, we call that a detached instance, because while it does have a representation in the database, Hibernate isn't doing anything to keep the instance in sync with the underlying persistence store. In effect, the instance is detached from its corresponding representation in the database.
Of course, when we work with Hibernate, all of our interactions with the database must occur within the scope of a transaction. By default, when we call methods like save or update, we can never be totally sure when the corresponding record in the database is updated - all we know for sure is that once the transaction is committed, all of the changes to any of the persistent instances associated with the Hibernate Session will be saved to the database. Of course, there is always the potential that the act of saving all of the data to the database will fail for some reason, and if that does happen, Hibernate will throw a runtime exception. At this point, there's really not too much you can do, other than roll back the current transaction, and close the Hibernate Session. At this point, all of the instances that were previously under the control of the Hibernate Session become detached objects, and quite likely, are no longer in sync with the database. In such a case, you can always start a new transaction, and try to turn your detached instances back into persistent instances by re-associating them with the Hibernate Session through save or update calls, but in the end, you're probably better off just sending a friendly error message to your client application, and start any request-response cycle over again from scratch.
And that's about it; a quick description of how hibernate works, along with a simple description of what we mean when we talk about transient, persistent and detached objects.
Wednesday, June 23, 2010
Hibernate Caches
Hibernate comes with three different caching mechanisms - first level, second level and query cache. Truly understanding how the Hibernate caches work and interact with each other is important when you need to increase performance - just enabling caching in your entity with an annotation (or in classic .hbm.xml mapping file) is easy. But understanding what and how things happens behind the scenes is not. You might even end up with a less performing system if you do not know what you are doing.
SessionFactory and Session
The purpose of the Hibernate SessionFactory (called EntityManager in JEE) is to create Sessions, initialize JDBC connections and pool them (using a pluggable provider like C3P0). A SessionFactory is immutable and built from a Configuration holding mapping information, cache information and a lot of other information usually provided by means of a hibernate.cfg.cml file or through a Spring bean configuration.
A Session is a unit of work at its lowest level - representing a transaction in database lingua. When a Session is created and operations are done on Hibernate entities, e.g. setting an attribute of an entity, Hibernate does not go of and update the underlying table immediately. Instead Hibernate keeps track of the state of an entity, whether it is dirty or not, and flushes (commits) updates at the end at the end of a unit of work. This is what Hibernate calls the first level cache.
The 1st level cache
Definition: The first level cache is where Hibernate keeps track of the possible dirty states of the ongoing Session's loaded and touched entities. The ongoing Session represents a unit of work and is always used and can not be turned of. The purpose of the first level cache is to hinder to many SQL queries or updates beeing made to the database, and instead batch them together at the end of the Session. When you think about the 1st level cache think Session.
The 2nd level cache is a process scoped cache that is associated with one SessionFactory. It will survive Sessions and can be reused in new Session by same SessionFactory (which usually is one per application). By default the 2nd level cache is not enabled.
The hibernate cache does not store instances of an entity - instead Hibernate uses something called dehydrated state. A dehydrated state can be thought of as a deserialized entity where the dehydrated state is like an array of strings, integers etc and the id of the entity is the pointer to the dehydrated entity. Conceptually you can think of it as a Map which contains the id as key and an array as value. Or something like below for a cache region:
{ id -> { atribute1, attribute2, attribute3 } }
{ 1 -> { "a name", 20, null } }
{ 2 -> { "another name", 30, 4 } }
If the entity holds a collection of other entities then the other entity also needs to be cached. In this case it could look something like:
{ id -> { atribute1, attribute2, attribute3, Set{item1..n} } }
{ 1 -> { "a name", 20, null , {1,2,5} } }
{ 2 -> { "another name", 30, 4 {4,8}} }
The actual implementation of the 2nd level cache is not done by Hibernate (there is a simple Hashtable cache available, not aimed for production though). Hibernate instead has a plugin concept for caching providers which is used by e.g. EHCache.
Enabling the 2nd level cache and EHCache
To get the 2nd level cache working you need to do 2 things:
1 Cache Strategy. Enable a cache strategy for your Hibernate entity - either in the class with an annotation or in the hibernate mapping xml file if you are stuck with pre java5. This can be done for an entity by providing this little snippet into your hbm.xml file (a better place is to store the cache setting strategy in hibernate.cg.xml file )
or using an annotation for your entity (if you are on java5 or greater)
@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Router { ... }
And as mentioned above if you want to cache collections of an entity you need to specify caching on collection level:Hibernate has something called a cache region which by default will be the full qualified name of your Java class. And if you like me are a fan of convention over configuration you will use the default region for an entity. A cache region will also be needed for the collection using the full qualified name of the Java class plus the name of the collection name (i.e. org.grouter.domain.entities.Router.nodes)
...
2 Cache provider. Setting up the physical caching for a cache provider. If you are using EHCache - which is the most common choice i dear to say - then you will need to specify some settings for the cache regions of your entities in a file called ehcache.xml. The EHCache will look for this file in the classpath and if not found it will fallback to ehcache-failsafe.xml which resides in the ehcache.jar library A typical sample for an EHCache configuration could look like (see mind map below for explanations):
and
The name maps to the name of the cache region of your entity. The attribute maxelementsInMemory needs to be set so that Hibernate does not have to swap in and out elements from the cache. A good choice for a read only cache would be as many entities there are in the database table the entity represents. The attribute eternal, if set to true means that any time outs specified will be ignored and entities put into the cache from Hibernate will live for ever.
Below is a mindmap for the second level cache and how it relates to the SessionFactory and the 1st level cache.
The Query cache of Hibernate is not on by default. It uses two cache regions called org.hibernate.cache.StandardQueryCache and org.hibernate.cache.UpdateTimestampsCache. The first one stores the query along with the parameters to the query as a key into the cache and the last one keeps track of stale query results. If an entity part of a cached query is updated the the query cache evicts the query and its cached result from the query cache. Of course to utilize the Query cache the returned and used entities must be set using a cache strategy as discussed previously. A simple load( id ) will not use the query cache but instead if you have a query like:
Hibernate will cache using as key the query and the parameters the value of the if of the entity.
{ query,{parameters}} ---> {id of cached entity}
{"from Router as r where r.id= :id and r.created = :creationDate", [ new Date() ] } ----> [ 4321 ] ]
Pragmatic approach to the 2nd level cache
How do you now if you are hitting the cache or not? One way is using Hibernates SessionFactory to get statistics for cache hits. In your SessionFactory configuration you can enable the cache statistics by:
The you might want to write a unit test to verify that you indeed are hitting the cache. Below is some sample code where the unit test is extending Springs excellent AbstractTransactionalDataSourceSpringContextTests
The output could looke something like:
Another way to spy on what Hibernate is doing is to proxy the jdbc driver used by a proxy driver. One excellent one I use is p6spy which will show you exactly what is issued over a JDBC connection to the actual backend database. For other tips have a look below in the mindmap.