Aug/091
Java Middle-Tier Using Ibatis
This is going to be my first entry in a series on how to quickly and efficiently develop the middle-tier portion of an enterprise level flex application that will allow you to communicate with your application via the most efficient and simple means available, that being Remote Procedure Calls. By the time I finish the series, my hope is that you will be able to knock out the middle-tier portion of your application in no time at all, giving you a maximum amount of time to develop your front end Flex app.
The focus of this particular entry is ibatis, which is a framework which allows you to configure the population of java objects from the database using xml files. Ibatis has a ton of features which you can use, and detailing the full litany of them is a more laborious task than I’m up for. For the purposes of this entry, I’m going to show you how to map database fields to java fields, select, update, and insert data.
For the sake of these examples, I will have an embarassingly simple object model, reflected by the following VO:
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 | package com.softwarejesus.ibatis.domain; public class FirstObject { private String fieldOne; private String fieldTwo; private int fieldThree; public String getFieldOne() { return fieldOne; } public void setFieldOne(String fieldOne) { this.fieldOne = fieldOne; } public String getFieldTwo() { return fieldTwo; } public void setFieldTwo(String fieldTwo) { this.fieldTwo = fieldTwo; } public int getFieldThree() { return fieldThree; } public void setFieldThree(int fieldThree) { this.fieldThree = fieldThree; } } |
The first step in using ibatis, is to add the necessary jar files to your application’s buildpath. The jar files are available at the ibatis site here
Step two, is to determine what type of interactions you’ll need with your database. Here’s my Data Access Object
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 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | package com.softwarejesus.ibatis.dao; import java.io.IOException; import java.io.Reader; import java.sql.SQLException; import java.util.List; import com.ibatis.common.resources.Resources; import com.ibatis.sqlmap.client.SqlMapClient; import com.ibatis.sqlmap.client.SqlMapClientBuilder; import com.softwarejesus.ibatis.domain.FirstObject; public class FirstDao { private static SqlMapClient client; public FirstDao() { try { Reader reader = Resources.getResourceAsReader("sql-map-config.xml"); client = SqlMapClientBuilder.buildSqlMapClient(reader); reader.close(); } catch (IOException e) { System.out.println("There are better ways to do this, and I'll show you in a later post"); } } public List<FirstObject> getAllFirstObjects() { List<FirstObject> returnList = null; try { returnList = client.queryForList("getAllFirstObjects"); } catch (SQLException sqlE) { sqlE.printStackTrace(); } return returnList; } public List<FirstObject> getFirstObjects(String param) { List<FirstObject> returnList = null; try { returnList = client.queryForList("getFirstObjects"); } catch (SQLException sqlE) { sqlE.printStackTrace(); } return returnList; } public void updateFirstObject(FirstObject object) { try { client.update("updateFirstObject", object); } catch (SQLException sqlE) { sqlE.printStackTrace(); } } public void insertFirstObject(FirstObject newObject) { try { client.insert("insertFirstObject", newObject); } catch (SQLException sqlE) { sqlE.printStackTrace(); } } } |
As you can see, I have two ways I can retrieve data, one will return all the data, the other will select based on some input criteria. I also have an update and insert method. The constructor creates a SqlMapClient object, the SqlMapClient object is basically where all the magic happens with ibatis. I won’t focus on the constructor, because my next entry will show you how to use Spring to populate this, and many other necessary objects.
Now that we know what interactions we want to have with the database, we need to set up our SQL-Map XML. My SQL Map includes only 6 different node types: typeAlias, resultMap, result, select, update, and insert.
The typeAlias node creates a shorthand Alias for a specific java class.
The resultMap node create another Alias, indicating how a specific set of fields will populate a java object.
The result node matches a specific result set field to a java field.
The select, update, and insert nodes should all be relatively self-explanatory.
Here’s my SQL-Map
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 | <?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="Model"> <typeAlias alias="myFirstObject" type="com.softwarejesus.ibatis.domain.FirstObject" /> <resultMap id="firstObjectResult" class="myFirstObject"> <result property="fieldOne" column="oneField"/> <result property="fieldTwo" column="twoField"/> <result property="fieldThree" column="threeField"/> <resultMap> <select id="getAllFirstObjects" resultMap="firstObjectResult"> Select * from firstTable </select> <select id="getFirstObjects" resultMap="firstObjectResult" parameterClass="java.lang.String"> Select * from firstTable where oneField = #value# </select> <update id="updateFirstObject" parameterClass="myFirstObject"> UPDATE firstTable SET oneField = #fieldOne# ,twoField = #fieldTwo# ,threeField = #fieldThree# WHERE oneField = #fieldOne# </update> <insert id="insertFirstObject" parameterClass="myFirstObject"> INSERT INTO firstTable VALUES (#fieldOne#, #fieldTwo#, #fieldThree#) </insert> </sqlMap> |
Obviously this was a very simple example of what can be done using ibatis. I like how flexible ibatis is though, notice how the database calls (select, update, and insert nodes) have an attribute called parameterClass. What’s nice is that you can set the parameter class to either a typeAlias or the fully qualified Java class name. I almost always use the typeAlias, for the sake of readability, but, it’s not necessary to do so. The same goes for the result type, you can either use a resultMap defined in your SQL Map or set the resultClass attribute to a fully qualified Java class.
You may have noticed that sometimes in the select/insert/update portions of my SQLMap I use #value# to inject values into the SQL and sometime I use $value$ to inject values. The difference between the two is that using the #value# formats the value to ensure that it is SQL, for example handling apostrophes in Strings. Whereas, $value$ indicates that the value is already SQL formatted.
In the DAO all I had to provide ibatis with was the ID of the SQL statement I wanted to run, and any parameters necessary for the statement, that’s it! I love using ibatis because it makes my java piece so tiny and essentially maintenance free.
One thing to be careful of when using ibatis, is that it struggles with null values returned from the database, usually you’ll have to indicate in the resultMap what the java type is if there’s a null value returned.
Ibatis has tons of really great features, and I’ve only scratched the surface on them here. But one of the things I like the most is if the result set fields match the java fields, you don’t have to define a resultMap, because ibatis will handle it for you.
Sorry, the comment form is closed at this time.