Lazy loading is conceptually a tactic of delaying the creation of an object until required. It is also referred as design pattern also. When we talk about lazy loading while fetching information from database, lazy loading essentially means to delay the execution of certain select/ sub-select queries till the time their related data is asked for.
In this tutorial, I am showing an example of lazy loading when developing your application with iBatis. There are following sections in this tutorial.
1) Create a maven project 2) Update runtime dependencies 3) Configure sql-map and config files with lazy loading enabled 4) Write domain classes 5) Test the application
1) Create a maven project
Run following commands to make a simple java project which is supported by eclipse plugin.
mvn archetype:generate -DgroupId=com.howtodoinjava.ibatis.demo -DartifactId=ibatisHelloWorld -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
2) Update runtime dependencies
This will be done in pom.xml file. You can download the required jar files and put in lib folder as well.
pom.xml
<dependencies> <!-- iBatis support --> <dependency> <groupId>org.apache.ibatis</groupId> <artifactId>ibatis-sqlmap</artifactId> <version>2.3.4.726</version> </dependency> <!-- Database connectivity support --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.9</version> </dependency> <!-- Proxy support (Mandatory) --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency> <!-- Internal dependency (Required) --> <dependency> <groupId>asm</groupId> <artifactId>asm-util</artifactId> <version>3.3.1</version> </dependency> <!-- Internal dependency (Required) --> <dependency> <groupId>opensymphony</groupId> <artifactId>oscache</artifactId> <version>2.4</version> <scope>compile</scope> <!-- This excludes the transitive dependency on JMS --> <exclusions> <exclusion> <groupId>javax.jms</groupId> <artifactId>jms</artifactId> </exclusion> </exclusions> </dependency>
3) Write domain classes
Below the domain classes UserTEO.java and DepartmentTEO.java. UserTEO has reference of DepartmentTEO which we are targeting to lazy load.
UserTEO.java
package com.howtodoinjava.ibatis.demo.dto; import java.io.Serializable; public class UserTEO implements Serializable { private static final long serialVersionUID = 1L; private Integer id; private String name; private String email; private String password; private int status; private DepartmentTEO department; //Getters and Setters }
DepartmentTEO.java
package com.howtodoinjava.ibatis.demo.dto; import java.io.Serializable; public class DepartmentTEO implements Serializable { private static final long serialVersionUID = 1L; private int id; private String name; //Getters and Setters }
4) Configure sql-map and config files with lazy loading enabled
To configure iBatis in your application, you will need to configure sql-map-config.xml file and well as sql-map file also.
Below are two such files written for this tutorial.
sql-maps-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> <sqlMapConfig> <!-- Lazy loading is globally enabled here --> <settings useStatementNamespaces="true" cacheModelsEnabled="false" lazyLoadingEnabled="true"/> <transactionManager type="JDBC"> <dataSource type="SIMPLE"> <property name="JDBC.Driver" value="com.mysql.jdbc.Driver"/> <property name="JDBC.ConnectionURL" value="jdbc:mysql://localhost:3306/demoDB"/> <property name="JDBC.Username" value="root"/> <property name="JDBC.Password" value="lg225295"/> </dataSource> </transactionManager> <sqlMap resource="user.xml"/> </sqlMapConfig>
user.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd"> <sqlMap namespace="user"> <typeAlias alias="USER" type="com.howtodoinjava.ibatis.demo.dto.UserTEO" /> <typeAlias alias="DEPARTMENT" type="com.howtodoinjava.ibatis.demo.dto.DepartmentTEO" /> <resultMap id="userResultMap" class="USER"> <result property="id" column="ID" /> <result property="name" column="NAME" /> <result property="email" column="EMAIL" /> <result property="password" column="PASSWORD" /> <result property="status" column="STATUS" /> <result property="department" column="DEPT_ID" select="user.getDepartmentById" /> </resultMap> <resultMap id="departmentResultMap" class="DEPARTMENT"> <result property="id" column="ID" /> <result property="name" column="NAME" /> </resultMap> <select id="getDepartmentById" parameterClass="java.lang.Integer" resultMap="departmentResultMap"> SELECT * FROM DEPARTMENT WHERE ID = #value# </select> <select id="getUserById" parameterClass="java.lang.Integer" resultMap="userResultMap"> SELECT * FROM USERINFO WHERE ID = #value# </select> </sqlMap>
5) Test the application
I have written below code which loads the iBatis configuration, connects to DB and load user object. It first makes a call to user detail, the user object is loaded from database.
But Department data is selected only when I try to get it from user object. It means Department data is lazy loaded .
package com.howtodoinjava.ibatis.demo; import java.io.Reader; import com.howtodoinjava.ibatis.demo.dao.UserDao; import com.howtodoinjava.ibatis.demo.dao.UserDaoIbatis; import com.howtodoinjava.ibatis.demo.dto.UserTEO; import com.ibatis.common.resources.Resources; import com.ibatis.sqlmap.client.SqlMapClient; import com.ibatis.sqlmap.client.SqlMapClientBuilder; public class TestMain { public static void main(String[] args) throws Exception { UserDao manager = new UserDaoIbatis(); Reader reader = Resources.getResourceAsReader("sql-maps-config.xml"); SqlMapClient sqlmapClient = SqlMapClientBuilder.buildSqlMapClient (reader); UserTEO user = manager.getUserById(1, sqlmapClient); System.out.println(user.getEmail()); System.out.println("LAZY load the department"); System.out.println(user.getDepartment().getName()); } }
Below is the output of program.
DEBUG [main] - Created connection 27994366. DEBUG [main] - {conn-100000} Connection DEBUG [main] - {conn-100000} Preparing Statement: SELECT * FROM USERINFO WHERE ID = ? DEBUG [main] - {pstm-100001} Executing Statement: SELECT * FROM USERINFO WHERE ID = ? DEBUG [main] - {pstm-100001} Parameters: [1] DEBUG [main] - {pstm-100001} Types: [java.lang.Integer] DEBUG [main] - {rset-100002} ResultSet DEBUG [main] - {rset-100002} Header: [ID, NAME, EMAIL, PASSWORD, STATUS, DEPT_ID] DEBUG [main] - {rset-100002} Result: [1, Demo User, demo-user@howtodoinjava.com, password, 1, 1] DEBUG [main] - Returned connection 27994366 to pool. demo-user@howtodoinjava.com LAZY load the department DEBUG [main] - Checked out connection 27994366 from pool. DEBUG [main] - {conn-100003} Connection DEBUG [main] - {conn-100003} Preparing Statement: SELECT * FROM DEPARTMENT WHERE ID = ? DEBUG [main] - {pstm-100004} Executing Statement: SELECT * FROM DEPARTMENT WHERE ID = ? DEBUG [main] - {pstm-100004} Parameters: [1] DEBUG [main] - {pstm-100004} Types: [java.lang.Integer] DEBUG [main] - {rset-100005} ResultSet DEBUG [main] - {rset-100005} Header: [ID, NAME] DEBUG [main] - {rset-100005} Result: [1, Finance] DEBUG [main] - Returned connection 27994366 to pool. Finance
source download
Happy Learning !!
hello sir,
do you have lazy buddy system in java code???
Can you Please give the exapmple to call the Oracle stored procedure from the Ibatics that is returning the Cursor and mapped the result in the java Object
Thanks buddy…Its Simple and good one …