Hibernate Session provides two methods to retrieve object e.g. get() and load() both looked quite similar to each other but there are subtle difference between load and get method.
The major difference between two methods is:
- get method will involve a database query if the record is not in the cache, and obtain a fully initialized object. However, load method can return a proxy object and only initialize the object or query the database when it is required. Since load method supports lazy loading, it may result in better performance.
- load method throws exception if the data is not found while get method return a null object. Therefore, it is better to use load method when you know the data record is in the database
Let’s take a looks at some examples:
Case 1: database records are available
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
package net.tecbar.hibernate; import net.tecbar.domain.Category; public class HibernateSessionGetVsLoadExample1 { public static void main(String[] args) { System.out.println("session get()"); // assume those records cannot be found in the database Category cat1 = (Category) HibernateUtil.getSession().get(Category.class, 3); System.out.println("get method has been called"); System.out.println("show data now"); System.out.println(cat1); HibernateUtil.closeSession(); System.out.println("\nsession load()"); Category cat2 = (Category) HibernateUtil.getSession().load(Category.class, 4); System.out.println("load method has been called"); System.out.println("show data now"); System.out.println(cat2); HibernateUtil.closeSession(); } } |
Output
1 2 3 4 5 6 7 8 9 10 11 12 13 |
session get() Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_, category0_.description as descript3_0_0_ from category category0_ where category0_.id=? get method has been called show data now PIAccount [id=3, name=car, description=2015 models] session load() load method has been called show data now Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_, category0_.description as descript3_0_0_ from category category0_ where category0_.id=? PIAccount [id=4, name=magazine, description=2000 options] |
Hibernate log
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
17:04:24,471 DEBUG [SessionFactoryRegistry]:67 - Initializing SessionFactoryRegistry : org.hibernate.internal.SessionFactoryRegistry@1f709902 17:04:24,472 DEBUG [SessionFactoryRegistry]:89 - Registering SessionFactory: d9746326-f672-4593-97c7-e661ae9ca0bd (<unnamed>) 17:04:24,472 DEBUG [SessionFactoryRegistry]:96 - Not binding SessionFactory to JNDI, no JNDI name configured 17:04:24,472 DEBUG [SessionFactoryImpl]:505 - Instantiated session factory 17:04:24,473 DEBUG [NamedQueryRepository]:155 - Checking 0 named HQL queries 17:04:24,473 DEBUG [NamedQueryRepository]:171 - Checking 0 named SQL queries 17:04:24,477 DEBUG [StatisticsInitiator]:110 - Statistics initialized [enabled=false] // get method 17:04:24,540 DEBUG [SQL]:109 - select category0_.id as id1_0_0_, category0_.name as name2_0_0_, category0_.description as descript3_0_0_ from category category0_ where category0_.id=? 17:04:24,540 DEBUG [LogicalConnectionImpl]:226 - Obtaining JDBC connection 17:04:24,540 DEBUG [LogicalConnectionImpl]:232 - Obtained JDBC connection 17:04:24,555 DEBUG [ResultSetProcessorImpl]:127 - Starting ResultSet row #0 17:04:24,555 DEBUG [EntityReferenceInitializerImpl]:142 - On call to EntityIdentifierReaderImpl#resolve, EntityKey was already known; should only happen on root returns with an optional identifier specified 17:04:24,561 DEBUG [TwoPhaseLoad]:160 - Resolving associations for [net.tecbar.domain.Category#3] 17:04:24,562 DEBUG [TwoPhaseLoad]:194 - Adding entity to second-level cache: [net.tecbar.domain.Category#3] 17:04:24,567 DEBUG [TwoPhaseLoad]:286 - Done materializing entity [net.tecbar.domain.Category#3] 17:04:24,568 DEBUG [AbstractLoadPlanBasedEntityLoader]:208 - Done entity load : net.tecbar.domain.Category#3 17:04:24,568 DEBUG [LogicalConnectionImpl]:246 - Releasing JDBC connection 17:04:24,568 DEBUG [LogicalConnectionImpl]:264 - Released JDBC connection // load method 17:04:24,570 DEBUG [SessionImpl]:972 - Initializing proxy: [net.tecbar.domain.Category#4] 17:04:24,570 DEBUG [SQL]:109 - select category0_.id as id1_0_0_, category0_.name as name2_0_0_, category0_.description as descript3_0_0_ from category category0_ where category0_.id=? 17:04:24,570 DEBUG [LogicalConnectionImpl]:226 - Obtaining JDBC connection 17:04:24,570 DEBUG [LogicalConnectionImpl]:232 - Obtained JDBC connection 17:04:24,571 DEBUG [ResultSetProcessorImpl]:127 - Starting ResultSet row #0 17:04:24,571 DEBUG [EntityReferenceInitializerImpl]:142 - On call to EntityIdentifierReaderImpl#resolve, EntityKey was already known; should only happen on root returns with an optional identifier specified 17:04:24,571 DEBUG [TwoPhaseLoad]:160 - Resolving associations for [net.tecbar.domain.Category#4] 17:04:24,571 DEBUG [TwoPhaseLoad]:194 - Adding entity to second-level cache: [net.tecbar.domain.Category#4] 17:04:24,572 DEBUG [TwoPhaseLoad]:286 - Done materializing entity [net.tecbar.domain.Category#4] 17:04:24,572 DEBUG [AbstractLoadPlanBasedEntityLoader]:208 - Done entity load : net.tecbar.domain.Category#4 17:04:24,572 DEBUG [LogicalConnectionImpl]:246 - Releasing JDBC connection 17:04:24,572 DEBUG [LogicalConnectionImpl]:264 - Released JDBC connection |
From the output and Hibernate log, we can see that get method will query database if the record is not in the cache, and obtain the object while load method can return a proxy object and only initialize the object or query the database when it is required.
Case 2: database records cannot be found
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
package net.tecbar.hibernate; import net.tecbar.domain.Category; public class HibernateSessionGetVsLoadExample1 { public static void main(String[] args) { System.out.println("session get()"); // assume those records are not in the database Category cat1 = (Category) HibernateUtil.getSession().get(Category.class, 30); System.out.println("get method has been called"); System.out.println("show data now"); System.out.println(cat1); HibernateUtil.closeSession(); System.out.println("\nsession load()"); Category cat2 = (Category) HibernateUtil.getSession().load(Category.class, 40); System.out.println("load method has been called"); System.out.println("show data now"); System.out.println(cat2); HibernateUtil.closeSession(); } } |
output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
session get() Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_, category0_.description as descript3_0_0_ from category category0_ where category0_.id=? get method has been called show data now null session load() load method has been called show data now Hibernate: select category0_.id as id1_0_0_, category0_.name as name2_0_0_, category0_.description as descript3_0_0_ from category category0_ where category0_.id=? Exception in thread "main" org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [net.tecbar.domain.Category#40] at org.hibernate.internal.SessionFactoryImpl$1$1.handleEntityNotFound(SessionFactoryImpl.java:253) at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:262) at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:176) at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:286) at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185) at net.tecbar.domain.Category_$$_jvst7d3_1.toString(Category_$$_jvst7d3_1.java) at java.lang.String.valueOf(Unknown Source) at java.io.PrintStream.println(Unknown Source) at net.tecbar.hibernate.HibernateSessionGetVsLoadExample1.main(HibernateSessionGetVsLoadExample1.java:22) |
Conclusion
Hibernate Session get() method and load() method look similar, but there are difference between two methods. Load method uses lazy loading, and has better performance. However, if no record can be found it will throw exception when using load() method. As there is no best solution, you should choose which method based on your application.