很久没做ibaist的系列的东西了,昨天正好在组里分享了一下,所以就顺手把内容再重新整理一下
首先附一下ibatis的源码包,由于ibaits改成了mybatis,所以官网都很难下到了源码,感谢这个博主的分享
http://yizhilong28.iteye.com/blog/850084
首先看下ibatis的代码结构
主要有comomon和sqlmap两个包,另外还有一个sqldao的包是可选的。其中common是公用的工具类,sqlmap是sqlmaps框架
这里我是用maven组织项目的,我们在来看下maven的pom文件,使用ibatis的一个主要特点就是降低jar包的依赖性,所以一个ibatis的测试包只需要3个jar包即可
上一次我么是用autoDao这个插件来生成一个ibatis项目的,其中生成了两个配置文件,一个config文件,一个sqlmap文件。
其中config文件主要用来定义数据源的,这里有一点要注意下,2.0之后每一个config文件只允许一个数据源了,如果一个项目下有多个数据源,要配置多个config文件,其中config文件主要有以下几个节点:
properties(主要定义属性文件) settings(用来做一些自定义的配置) typealias(用来设别名,默认的有JDBC,JTA,EXTERNAL,SIMPLE,DBCP,JNDI) transcationManager(用来定义事务管理) datasource(用来配置数据源,2.0以后只允许一个数据源) sqlMap(用来做其他sqlmp文件的引用)sqlxml文件主要用来定义各个SQLstatement。以及定义输入参数和输出结果的映射,另外还可以用来配置缓存模型。其主要有以下几个节点
mapstatement(用来定义各个sql语句,包括sql,select,update,delete,insert及procedure) parameterMap(用来定义入参的映射) resultMap(用来定义输出结果的映射) cachemodel(用来定义模型)提到mapstatment,dynamic的节点就要提一下了,这个是ibatis优于传统的SQL的地方之一。ibaits通过各种不同的节点把一个mapstatement动态映射成各种SQL,提高了代码的重用。这里列出ibatis中所有的动态节点:
二元条件 isEqual isgreaterThan isLessThan 一元条件 isPropertyAvailale isnull isEmpty collection的size(),String的valueof() 其他 isparameterpresent iterate 简单的动态SQL $$说完了配置文件,我们就要看下ibatis即sqlmapclient的主要的api了
1 配置sqlmap,主要的代码如下:
String resource = "sqlmap-config.xml"; Reader reader = Resources.getResourceAsReader(resource); sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader);2执行SQL的update(包括insert,update和delete)
3获取一个对象
queryforobject4获取一个对象的list
queryforlist queryformap quqyerforpaginatedlist这里还要提一个queryWithRowHandler()这个api,可以用来处理大数据的操作,其和statement中额fetchsize有关,用来约定每次取多少数据。
接下来,我这里粘一下一个完整的测试代码。其中staement的配置已经在注释中了
public class UserDaoTest { private static SqlMapClient sqlMapClient = null; static { try { String resource = "sqlmap-config.xml"; Reader reader = Resources.getResourceAsReader(resource); sqlMapClient = SqlMapClientBuilder.buildSqlMapClient(reader); } catch (Exception e) { e.printStackTrace(); } } // 注:当parameterClass="string"的时侯,sql语句中的参数没有限制, 如:SELECT * FROM t_user WHERE NAME=#name#, // 其中#name#中name可以是任何名称,不过通常情况下,我们习惯于只有一个参数的时候用#value#或者是#熟悉名# // <!-- example 1: 无映射 --> // <select id="getUserByName1" resultClass="user" parameterClass="string"> // <![CDATA[ // SELECT * FROM t_user WHERE NAME=#name# // ]]> // </select>. public static void example1() throws Exception { try { List<User> list = sqlMapClient.queryForList("getUserByName1", "zxx"); for (User user : list) { System.out.println(user.getId() + "-" + user.getName() + "-" + user.getPass()); } } catch (Exception e) { e.printStackTrace(); } } // 注:当使用内联映射 ->实体类的时侯,sql语句中的映射名可以没有限制, 如:SELECT ID as id, NAME as name, PASS as pass FROM t_user WHERE NAME=#name#, // 通常情况下映射名就是bean的属性的名字,如果改成这样 // SELECT ID as iid, NAME as name, PASS as pass FROM t_user WHERE NAME=#name#,其中iid不是bean的属性,那么我们就无法获取id的值, // 其实这样写也是没意义的,所以通常情况下映射的名字就是bean的属性的名字。 // <!-- example 2: 内联映射 -> 实体类 --> // <select id="getUserByName2" resultClass="user" parameterClass="string"> // <![CDATA[ // SELECT ID as id, NAME as name, PASS as pass FROM t_user WHERE NAME=#name# // ]]> // </select> public static void example2() throws Exception { try { List<User> list = sqlMapClient.queryForList("getUserByName2", "zxx"); for (User user : list) { System.out.println(user.getId() + "-" + user.getName() + "-" + user.getPass()); } } catch (Exception e) { e.printStackTrace(); } } // 注:当使用内联映射 ->MAP类的时侯,即resultClass="hashmap"或者resultClass="java.util.Map"; 它会返回一个Map的集合, // Map中的键对应的数据库中的字段名,非bean中的属性名,所以获取的时候get()中的应该是字段名。 // <!-- example 3: 内联映射 -> MAP类 --> // <select id="getUserByName3" resultClass="hashmap" parameterClass="string"> // <![CDATA[ // SELECT * FROM t_user WHERE NAME=#name# // ]]> // </select> public static void example3() throws Exception { try { List<User> list = sqlMapClient.queryForList("getUserByName3", "zxx"); Iterator iterator = list.iterator(); while (iterator.hasNext()) { Map map = (Map) iterator.next(); System.out.println(map.get("ID") + ":" + map.get("NAME") + ":" + map.get("PASS")); } } catch (Exception e) { e.printStackTrace(); } } // 注:当使用显示映射 ->实体类的时侯,即返回的结果在resultMap中,而非resultClass中,类如上面一个最简单的resultMap, // column对应的是字段名,此时字段名不区分大小写, property对应的是bean中的属性名,与example2的内联映射 ->实体类不同的是, // 该属性必须在bean中存在,否则就会报错,它的检查更严格.. // <!-- example 4: 显示映射 -> 实体类 --> // <resultMap id="userResult" class="user"> // <result property="id" column="Id" /> // <result property="name" column="NAME" /> // <result property="pass" column="PASS" /> // </resultMap> // <select id="getUserByName4" resultMap="userResult" parameterClass="string"> // <![CDATA[ // SELECT * FROM t_user WHERE NAME=#name# // ]]> // </select> public static void example4() throws Exception { try { List<User> list = sqlMapClient.queryForList("getUserByName4", "zxx"); for (User user : list) { System.out.println(user.getId() + "-" + user.getName() + "-" + user.getPass()); } } catch (Exception e) { e.printStackTrace(); } } // 注:当使用显示映射 ->MAP类的时侯,即resultMap的class不是我们定义的bean而是hashmap或者java.util.Map的时候,类如上面一个最简单的MAP类, // column对应的是字段名,此时字段名不区分大小写, property对应的是bean中的属性名,与example3的内联映射 ->MAP类不同的是,它的键值是属性名而非字段名. // <!-- example 5: 显示映射 -> MAP类 --> // <resultMap id="userMapResult" class="hashmap"> // <result property="id" column="ID" /> // <result property="name" column="NAME" /> // <result property="pass" column="PASS" /> // </resultMap> // <select id="getUserByName5" resultMap="userMapResult" parameterClass="string"> // <![CDATA[ // SELECT * FROM t_user WHERE NAME=#name# // ]]> // </select> public static void example5() throws Exception { try { List<User> list = sqlMapClient.queryForList("getUserByName5", "zxx"); Iterator iterator = list.iterator(); while (iterator.hasNext()) { Map map = (Map) iterator.next(); System.out.println(map.get("id") + ":" + map.get("name") + ":" + map.get("pass")); } } catch (Exception e) { e.printStackTrace(); } } // 注:xmlResultName="info",xmlResultName定义返回的结果信息保存在xml的那个元素中,如果返回有多个xml对象那么就会产生多个<?Xml ,而不是整合在一个<?xml中。 // <!-- example 6: XML --> // <select id="getUserByName6" parameterClass="string" resultClass="xml" xmlResultName="info"> // <![CDATA[ // SELECT * FROM t_user WHERE name=#name# // ]]> // </select> public static void example6() throws Exception { try { List list = sqlMapClient.queryForList("getUserByName6", "zxx"); System.out.println(list.get(0)); // 输出: <?xml version="1.0" encoding="UTF-8"?><info><ID>7</ID><NAME>zxx</NAME><PASS>xfmn123456</PASS></info> } catch (Exception e) { e.printStackTrace(); } } // 注: 自动参数映射 插入操作 // <!-- example 7: 自动参数映射 --> // <insert id="insertUser7" parameterClass="user"> // <![CDATA[ // INSERT INTO t_user ( ID, NAME, PASS )VALUES( #id#,#name#,#pass# ) // ]]> // </insert> public static void example7() throws Exception { try { User user = new User(); user.setName("example7"); sqlMapClient.insert("insertUser7", user); } catch (Exception e) { e.printStackTrace(); } } // 注:内联参数映射 插入操作 // <!-- example 8: 内联参数映射 --> // <insert id="insertUser8" parameterClass="user"> // <![CDATA[ // INSERT INTO t_user ( ID, NAME, PASS ) VALUES( #id:INT#, #name:VARCHAR#, #pass:VARCHAR# ) // ]]> // </insert> public static void example8() throws Exception { try { User user = new User(); user.setName("example8"); sqlMapClient.insert("insertUser8", user); } catch (Exception e) { e.printStackTrace(); } } // 注:外联参数映射 插入操作,如上述所示:SQL语句中有多少个参数,那么在parameterMap中必须定义多少个,而且要一一对应,参数定义顺序也不要错。 // <!-- example 9: 外联参数映射 --> // <parameterMap id="parameterMap" class="user"> // <parameter property="id" jdbcType="INTEGER" /> // <parameter property="name" jdbcType="VARCHAR" /> // <parameter property="pass" jdbcType="VARCHAR" /> // </parameterMap> // <insert id="insertUser9" parameterMap="parameterMap"> // <![CDATA[ // INSERT INTO t_user ( ID, NAME, PASS )VALUES( ?,?,? ) // ]]> // </insert> public static void example9() throws Exception { try { User user = new User(); user.setName("example9"); user.setPass("123456"); sqlMapClient.insert("insertUser9", user); } catch (Exception e) { e.printStackTrace(); } } // 注:该方法插入数据,并返回id的值 // <!-- example 10: 自动生成的键 --> // <insert id="insertUser10" parameterClass="user"> // <![CDATA[ // INSERT INTO t_user ( ID,NAME,PASS )VALUES( #id#, #name#, #pass# ) // ]]> // <selectKey resultClass="int" keyProperty="id"> // <![CDATA[ // SELECT LAST_INSERT_ID() // ]]> // </selectKey> // </insert> public static void example10() throws Exception { try { User user = new User(); user.setName("example10"); user.setPass("123456"); Integer returnValue = (Integer) sqlMapClient.insert("insertUser10", user); System.out.println(returnValue); } catch (Exception e) { e.printStackTrace(); } } //注:调用存储过程的参数个数必须和写存储过程的时候参数(输入和输出)个数相同. // <!-- example 11: 存储过程 --> // <resultMap id="returnResultMap" class="user"> // <result property="id" column="ID" /> // </resultMap> // <parameterMap id="paramUser" class="java.util.Map"> // <parameter property="name" jdbcType="VARCHAR" javaType="string" mode="IN" /> // <parameter property="pass" jdbcType="VARCHAR" javaType="string" mode="IN" /> // <parameter property="id" jdbcType="INT" javaType="Integer" mode="INOUT" resultMap="returnResultMap" /> // </parameterMap> // <procedure id="pro_insertUser11" parameterMap="paramUser" resultClass="int"> // <![CDATA[ // {call proc_userinsert(?,?,?)} // ]]> // </procedure> public static void example11() throws Exception { try { Map map = new HashMap(); map.put("name", "procedure"); map.put("pass", "123456"); Integer returnValue = (Integer)sqlMapClient.insert("pro_insertUser11", map); System.out.println(returnValue); } catch (Exception e) { e.printStackTrace(); } } //分页写法 public static void example12() throws Exception { try { List<User> list = sqlMapClient.queryForPaginatedList("getUserByName1", "zxx",1); for (User user : list) { System.out.println(user.getId() + "-" + user.getName() + "-" + user.getPass()); } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) throws Exception { Logger logger = Logger.getLogger(UserDaoTest.class); logger.debug("开始"); example1(); logger.debug("结束"); } }
总结一下,这里接着前两个博客,继续深入了一下ibatis的代码结构及主要的两个配置文件,另外熟悉了一下sqlmapclient的常用api