`

IBatis简单实现(附主键自动生成)

阅读更多
   有一段没有更新博客啦,还请各位原谅。
   这段时间一直在看Ibatis方面的东西,把IBatis的官方文档也都看完啦,觉得IBatis真就像官方说的那个门槛很低,但更加灵活。
   下面三段是引用《Ibatis开发指南》上的原话。
   相对 Hibernate和Apache OJB等“一站式”ORM解决方案而言,ibatis 是一种“半
自动化”的ORM实现。
   所谓“半自动” ,可能理解上有点生涩。纵观目前主流的 ORM,无论 Hibernate 还是
Apache OJB,都对数据库结构提供了较为完整的封装,提供了从 POJO 到数据库表的全
套映射机制。 程序员往往只需定义好了POJO 到数据库表的映射关系, 即可通过 Hibernate或者 OJB 提供的方法完成持久层操作。程序员甚至不需要对 SQL 的熟练掌握,
Hibernate/OJB 会根据制定的存储逻辑,自动生成对应的 SQL 并调用 JDBC 接口加以执
行。
   “半自动化” ,是相对Hibernate等提供了全面的数据库封装机制的 “全自动化”
ORM 实现而言, “全自动”ORM 实现了 POJO 和数据库表之间的映射,以及 SQL 的自动
生成和执行。 而ibatis 的着力点, 则在于POJO 与 SQL之间的映射关系。也就是说,ibatis并不会为程序员在运行期自动生成 SQL 执行。具体的 SQL 需要程序员编写,然后通过映射配置文件,将SQL所需的参数,以及返回的结果字段映射到指定 POJO。

   看了这种描述,对你有何感想呢。
   出于对技术的热情,花时间把Ibatis看了一下,觉得真的还不错,就写个简单的例子,供大家参考,有什么不足的地方还请各位指出来。
   本例子所用到的Jar文件为:
ibatis-2.3.jar
mysql-connecter.jar

   首先还是老一套,创建一张数据库表(使用Mysql数据库)。
CREATE DATABASE IBATISSTUDY;
CREATE TABLE PERSON(
  ID INT PRIMERY KEY AUTU_INCREMENT,
  U_NAME VARCHAR(20),
  U_PASSWORD VARCHAR(20)
)

   然后呢,创建POJO类:
package com.jack.ibatis.pojo;

public class Person {
	private int id;
	private String username;
	private String password;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}
}

   大家也看到啦,Person类里的属性与person表的字段并不一致,不过没有关系的,在SqlMap中可以使用ResultMap元素进行配置的。
   现在呢,就要配置Ibatis的两个关键配置SqlMapConfig映射文件和SqlMap映射文件。
首先要配置的当然是SqlMapConfig文件:
<?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>
	<!-- 唯一的Properties文件,加载数据库连接信息 -->
	<properties resource="mysql.properties"/>
<!--配置和优化SqlMapClient实例的各选项,是可选的
<settings 
    cacheModelsEnabled="true"    
    enhancementEnabled="true"    
    lazyLoadingEnabled="true"    
    errorTracingEnabled="true"    
    maxRequests="32"        
    maxSessions="10"        
    maxTransactions="5"        
    useStatementNamespaces="false" 
    /> 
-->
	<!-- 配置Ibatis事务管理,使用JDBC事务类型,数据源使用Simple类型 -->
	<transactionManager type="JDBC">
		<dataSource type="SIMPLE">
			<property name="JDBC.Driver" value="${mysql.driver}"/>
			<property name="JDBC.ConnectionURL" value="${mysql.url}"/>
			<property name="JDBC.Username" value="${mysql.username}"/>
			<property name="JDBC.Password" value="${mysql.password}"/>
		</dataSource>
	</transactionManager>	
	<!-- 配置Ibatis要使用的SqlMap文件信息 -->
	<sqlMap resource="com/jack/ibatis/pojo/map/person.xml"/>
</sqlMapConfig>

   setting元素可以配置和优化SqlMapClient对象的各选项,因为本例只是简单的使用,所有并没有必要去配置。
   现在配置SqlMap文件person.xml,此文件是专门针对您的POJO类进行配置的
<?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>
	<!-- 为Person类设置一个别名 -->
	<typeAlias alias="person" type="com.jack.ibatis.pojo.Person"/>
	<!-- 配置表和类之间的映射关系 -->
	<resultMap class="com.jack.ibatis.pojo.Person" id="personMap">
		<result property="id" column="ID"/>
		<result property="username" column="U_NAME"/>
		<result property="password" column="U_PASSWORD"/>
	</resultMap>
	<!-- 添加用户 -->
	<insert id="insertPerson" parameterClass="person">
		<!-- 配置Mysql主键自动增长 -->
		<selectKey keyProperty="id" resultClass="int">
			SELECT LAST_INSERT_ID() as value
		</selectKey>
                  <!-- 配置Oracle主键自动增长 
                  <selectKey resultClass="int" keyProperty="id" type="pre">    
                            <![CDATA[SELECT STOCKIDSEQUENCE.NEXTVAL AS ID FROM DUAL]]>    
                  </selectKey>-->
                  <!-- 配置MSServer主键自动增长 
                  <selectKey resultClass="int" keyProperty="id">    
                     <![CDATA[SELECT SCOPE_IDENTITY() AS ID ]]>  
                  </selectKey>-->
		<![CDATA[
			INSERT PERSON(U_NAME,U_PASSWORD) VALUES(#username#,#password#)
		]]>
	</insert>
	<!-- 查看特定用户 -->
	<select id="queryPersonById" parameterClass="int" resultMap="personMap">
		<![CDATA[
			SELECT * FROM PERSON WHERE ID=#id#
		]]>
	</select>
	<!-- 查看所有的用户 -->
	<select id="queryAllPerson" resultMap="personMap">
		<![CDATA[
			SELECT * FROM PERSON
		]]>
	</select>
</sqlMap>

  OK,现在所有的配置都已经完成啦,现在来做一个简单的测试:
package test.com.jack.ibatis;

import java.io.Reader;

import org.junit.Test;

import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
import com.jack.ibatis.pojo.Person;

public class TestPerson {
	@Test
	public  void testInsert(){
		String resource = "sqlMapConfig.xml";
		try {
			//读取配置文件
			Reader reader = Resources.getResourceAsReader(resource);
			//得到SqlMapClient
			SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
			Person person = new Person();
			person.setUsername("jack");
			person.setPassword("jack");
			//开始Ibatis事务
			sqlMap.startTransaction();
			sqlMap.insert("insertPerson", person);
			//结束IBatis事务
			sqlMap.commitTransaction();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	@Test
	public void testQuery(){
		String resource = "sqlMapConfig.xml";
		try {
			//读取配置文件
			Reader reader = Resources.getResourceAsReader(resource);
			//得到SqlMapClient
			SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
			//查看全部的用户
			sqlMap.queryForList("queryAllPerson");
			//查看特定的用户
			sqlMap.queryForObject("queryPersonById", 1);
		}catch(Exception e){}
	}
}

   好了,以上就是全部的实现,希望会对初学的朋友有所帮助。
  • ibatisStudy.rar (796.7 KB)
  • 描述: IBatis简单实例全部信息。
  • 下载次数: 725
分享到:
评论
16 楼 xnxqs 2009-07-14  
楼主你的例子有错误。
com.ibatis.common.beans.ProbeException: Could not set property 'id' to value 'null' for com.jack.ibatis.pojo.Person.  Cause: java.lang.IllegalArgumentException
at com.ibatis.common.beans.ComplexBeanProbe.setProperty(ComplexBeanProbe.java:368)
at com.ibatis.common.beans.ComplexBeanProbe.setObject(ComplexBeanProbe.java:234)
at com.ibatis.common.beans.GenericProbe.setObject(GenericProbe.java:90)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.executeSelectKey(SqlMapExecutorDelegate.java:427)
at com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate.insert(SqlMapExecutorDelegate.java:387)
at com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl.insert(SqlMapSessionImpl.java:82)
at com.ibatis.sqlmap.engine.impl.SqlMapClientImpl.insert(SqlMapClientImpl.java:58)
at test.com.jack.ibatis.TestPerson.testInsert(TestPerson.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99)
at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75)
at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45)
at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:66)
at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35)
at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)
at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34)
at org.junit.internal.runners.TestClassRunner.run(TestClassRunner.java:52)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:45)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: java.lang.IllegalArgumentException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.ibatis.common.beans.MethodInvoker.invoke(MethodInvoker.java:17)
at com.ibatis.common.beans.ComplexBeanProbe.setProperty(ComplexBeanProbe.java:356)
... 27 more


还有,你在帖子上的person.xml的配置中。
<!-- 添加用户 -->  
    <insert id="insertPerson" parameterClass="person">  
        <!-- 配置Mysql主键自动增长 -->  
        <selectKey keyProperty="id" resultClass="int">  
            SELECT LAST_INSERT_ID() as value   @1

---------------------------------------
上面的value是不是应该改为ID??
----------------------------------------


        </selectKey>   
                  <!-- 配置Oracle主键自动增长   
                  <selectKey resultClass="int" keyProperty="id" type="pre">      
                            <![CDATA[SELECT STOCKIDSEQUENCE.NEXTVAL AS ID FROM DUAL]]>      
                  </selectKey>-->  
                  <!-- 配置MSServer主键自动增长   
                  <selectKey resultClass="int" keyProperty="id">      
                     <![CDATA[SELECT SCOPE_IDENTITY() AS ID ]]>    
                  </selectKey>-->  
        <![CDATA[  
            INSERT PERSON(U_NAME,U_PASSWORD) VALUES(#username#,#password#)  
        ]]>  
    </insert>  

----------------------------
另外。对于自增长主键来说,mysql和sql的自增长ID应该属于后发型,即 type="post"但你没有配置,并且把selectKey 写到前面去了,这样的话应该会报错吧?我猜报ID无法SET的原因就在于此吧??
--------------------------

本人其实也写过类似的例子,但始终无法搞定的就是插入后获得自增长ID值 的问题。网上的方法基本都试过,但获得依旧为NULL,不知道 为什么。。。哭。。。。
15 楼 tinyhot 2009-04-02  
谢谢楼主,分享。
14 楼 merman 2008-12-03  
孤风浪客 写道
这些主键生成机制都是用数据本身机制生成的,有没有办法自定义主键生成机制呢。比如说用UUID来写主键?
PS:不是用Pojo中的setId(String str)这样子将生成的UUID赋值给主键字段。

我用oracle
<insert id="insertUser"	parameterClass="user">
		INSERT INTO USER_INFO (
			id,
			name,
			sex)
		VALUES (
			sys_guid(),
			#name#,
			#sex#
		)
	</insert>

预生成(如Oracle)和后生成两种类型(如MS-SQL Server)。下面是两个例子:
<
!—Oracle SEQUENCE Example -->
<insert id="insertProduct-ORACLE" parameterClass="com.domain.Product">
<selectKey resultClass="int" keyProperty="id" >
SELECT STOCKIDSEQUENCE.NEXTVAL AS ID FROM DUAL
</selectKey>
insert into PRODUCT (PRD_ID,PRD_DESCRIPTION)
values (#id#,#description#)
</insert>
<!— Microsoft SQL Server IDENTITY Column Example -->
<insert id="insertProduct-MS-SQL" parameterClass="com.domain.Product">
insert into PRODUCT (PRD_DESCRIPTION)
values (#description#)
<selectKey resultClass="int" keyProperty="id" >
SELECT @@IDENTITY AS ID
</selectKey>
</insert>
13 楼 jishan2008 2008-12-03  
我第一次接触ibatis这个框架,感觉好可以啊,我以后会常来的。
12 楼 孤风浪客 2008-11-28  
这些主键生成机制都是用数据本身机制生成的,有没有办法自定义主键生成机制呢。比如说用UUID来写主键?
PS:不是用Pojo中的setId(String str)这样子将生成的UUID赋值给主键字段。
11 楼 Jun_OuYang 2008-11-28  
zhi chi!
10 楼 mmwy 2008-11-03  
pejaming 写道
请问,ibatis涉及到1:n等关系是否就不能把单独的映射类拆分成多个映射文件

因为在resultMap中需要把外键字段映射到类中的对象字段


<settings useStatementNamespaces="true" />

然后在你的resultMap配置中,定义result ... select="namespace.xxx"
9 楼 流浪者A 2008-11-03  
还可以啊~
8 楼 InnocentBoy 2008-10-31  
mvmouse 写道
同楼上,标题有歧义……
楼主有个简单的例子,地址是:http://www.iteye.com/topic/247467,这是其中的一个方面吧!
7 楼 pejaming 2008-10-13  
请问,ibatis涉及到1:n等关系是否就不能把单独的映射类拆分成多个映射文件

因为在resultMap中需要把外键字段映射到类中的对象字段
6 楼 yanghaofeilong 2008-10-12  
支持顶啊!
5 楼 mvmouse 2008-10-10  
同楼上,标题有歧义……
4 楼 caipanjin 2008-10-09  
我以为楼主自己实现了一个简单的“iBatis”呢
3 楼 coolstar648 2008-10-08  
挺好的。
有时间自己搭建一个demo玩玩.
2 楼 rockxx 2008-10-07  
今天刚好要学这个,非常感谢LZ!
1 楼 jy02411368 2008-09-29  
放心吧 像这样的好东西 我会定期不间断的来回复了!!!支持支持 大大的支持

相关推荐

    ibatis框架实现的增删改查

    实现ibatis框架对student表的增删改查(包括模糊查询和用序列自动生成主键)

    iBatis SQL Maps开发指南.pdf

    自动生成的主键 存储过程 parameterClass parameterMap Inline Parameter简介 resultClass resultMap cacheModel xmlResultName Parameter Map 和 Inline Parameter 元素 Inline Parameter Map 基本类型输入参数 Map...

    Ibatis框架的核心知识点

    1 简单的sqlmap 2 SQl语句 3 自动生成的主键 4 存储过程 5 parameterMap与inline parameter 6 二元条件元素和一元条件元素 7 隐式的Result Map

    JAVA代码生成工具

    unique="是否唯一性约束" nullable="是否可以为空" pk="是否主键,在表没有主键的情况下,可以指定一个代理主键" updatable="是否可以更新" insertable="是否插入" enumString="枚举值,以分号分隔,示例值:M(1,...

    好用的代码生成源码

    示例如下: UserInfoBaseDao : 自动生成的代码, 不能手工修改,用于重复生成 UserInfoDao extends UserInfoBaseDao : 存放手工的代码,不能重复生成 页面的重复生成还没有啥好办法。 语法参考: ...

    iBATIS 帮助文档

    自动生成的主键.............................................................................................................20 存储过程.....................................................................

    AppFramework数据库访问组件_代码生成插件_V1.1.rar

    &lt;br&gt;6、 提供代码生成工具,生成的类代码的同时可以类之间的继承关系和接口实现关系,所有DAO类方法均以接口作为参数,使得代码更加具有可扩展性和灵活性。 &lt;br&gt;7、 Sql模板和ORMap直接生成.cs原代码,编译为...

    AppFramework_V1.0

    除了实现数据的增删改查,数据访问层还要提供一些与业务无关功能,例如面向对象的持久化与访问机制、本地事务与分布式事务支持、多数据库支持,这些机制或功能形成相对独立的逻辑领域,其主要目的有: &lt;br&gt;1、 ...

    Spring中文帮助文档

    11.5.2. 使用SimpleJdbcInsert来获取自动生成的主键 11.5.3. 指定SimpleJdbcInsert所使用的字段 11.5.4. 使用SqlParameterSource提供参数值 11.5.5. 使用SimpleJdbcCall调用存储过程 11.5.6. 声明SimpleJdbcCall...

    Spring API

    11.5.2. 使用SimpleJdbcInsert来获取自动生成的主键 11.5.3. 指定SimpleJdbcInsert所使用的字段 11.5.4. 使用SqlParameterSource提供参数值 11.5.5. 使用SimpleJdbcCall调用存储过程 11.5.6. 声明SimpleJdbcCall...

    springmybatis

    前面一章,已经搭建好了eclipse,mybatis,mysql的环境,并且实现了一个简单的查询。请注意,这种方式是用SqlSession实例来直接执行已映射的SQL语句: session.selectOne(...

    AppFramework_V1.0_New

    &lt;br&gt;6、 提供代码生成工具,生成的类代码的同时可以类之间的继承关系和接口实现关系,所有DAO类方法均以接口作为参数,使得代码更加具有可扩展性和灵活性。 &lt;br&gt;7、 Sql模板和ORMap直接生成.cs原代码,编译为...

    阿里巴巴编码规范 基础技能认证 考题分析(考题+答案).docx

    B .iBATIS自带的queryForList(String statementName,int start,int size)分页接口有性能隐患,不允许使用。 C .定义明确的sql查询语句,通过传入参数start和size来实现分页逻辑。 D .可使用存储过程写分页逻辑...

Global site tag (gtag.js) - Google Analytics