ibatis学习之一二三 ibatis与spring的整合

http://www.blogjava.net/freeman1984/archive/2007/12/07/166112.html

介绍

iBATIS是以SQL为中心的持久化层框架。能支持懒加载、关联查询、继承等特性。

iBATIS不同于一般的OR映射框架(eg:hibernate)。OR映射框架,将数据库表、字段等映射到类、属性,那是一种元数据(meta-data)映射。iBATIS则是将SQL查询的参数和结果集映射到类。因此可以说,iBATIS做的是SQLMapping的工作。它把SQL语句看成输入以及输出,结果集就是输出,而where后面的条件参数则是输入。iBATIS能将输入的普通POJO对象、Map、XML等映射到SQL的条件参数上,同时也可以将查询结果映射到普通POJO对象(集合)、Map、XML等上面。

iBATIS使用xml文件来映射这些输入以及输出。能大大减少数据库存储部分的代码量,而且可以非常方便的利用SQL中的一些小技巧。

简单示例

基于ibatis-2.3.0.677版本。

1、创建新的项目,并引入jar包

a)ibatis-2.3.0.677.jar

b)mysql驱动

2、在类路径中(classes下)提供ibatis的配置文件:sqlMapConfig.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEsqlMapConfig

PUBLIC"-//ibatis.apache.org//DTDSQLMapConfig2.0//EN"

"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

<transactionManagertype="JDBC"commitRequired="false">

<dataSourcetype="SIMPLE">

<propertyname="JDBC.Driver"value="com.mysql.jdbc.Driver"/>

<propertyname="JDBC.ConnectionURL"value="jdbc:mysql://127.0.0.1/ibatis"/>

<propertyname="JDBC.Username"value="root"/>

<propertyname="JDBC.Password"value="mysql"/>

</dataSource>

</transactionManager>

<sqlMapresource="com/ibatis/model/User.xml"/>

</sqlMapConfig>

3、创建实体类:User.java

packagecom.ibatis.model;

publicclassUser{

privateintid;

privateStringusername;

privateStringpassword;

publicintgetId(){

returnid;

}

publicvoidsetId(intid){

this.id=id;

}

publicStringgetPassword(){

returnpassword;

}

publicvoidsetPassword(Stringpassword){

this.password=password;

}

publicStringgetUsername(){

returnusername;

}

publicvoidsetUsername(Stringusername){

this.username=username;

}

}

4、创建针对User对象的CRUD的xml映射配置:User.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEsqlMap

PUBLIC"-//ibatis.apache.org//DTDSQLMap2.0//EN"

"http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMapnamespace="User">

<!--Usetypealiasestoavoidtypingthefullclassnameeverytime.-->

<typeAliasalias="User"type="com.ibatis.model.User"/>

<!--SelectwithnoparametersusingtheresultmapforAccountclass.-->

<selectid="selectAllUsers"resultclass="User">

select*fromt_user

</select>

<selectid="selectUser"resultclass="User"parameterclass="int">

select*fromt_userwhereid=#id#

</select>

<insertid="insertUser"parameterclass="User">

insertintot_uservalues(

null,#username#,#password#

)

</insert>

<updateid="updateUser"parameterclass="User">

updatet_usersetusername=#username#,password=#password#

whereid=#id#

</update>

<deleteid="deleteUser"parameterclass="int">

deletefromt_userwhereid=#id#

</delete>

</sqlMap>

5、创建测试程序测试:

packagecom.crm.model;

importjava.io.Reader;

importjava.util.Iterator;

importjava.util.List;

importcom.ibatis.common.resources.Resources;

importcom.ibatis.sqlmap.client.SqlMapClient;

importcom.ibatis.sqlmap.client.SqlMapClientBuilder;

/**

*最简单的形式!

*@authorq

*

*/

publicclassUserTest{

/**

*@paramargs

*/

publicstaticvoidmain(String[]args)throwsException{

//从配置文件中得到SqlMapClient对象

Readerreader=Resources.getResourceAsReader("sqlMapConfig.xml");

SqlMapClientsqlMapper=SqlMapClientBuilder.buildSqlMapClient(reader);

reader.close();

//创建用户数据

for(inti=0;i<10;i++){

Useruser=newUser();

user.setUsername("用户"+i);

user.setPassword("密码"+i);

sqlMapper.insert("insertUser",user);

}

//查询用户数据

Listusers=sqlMapper.queryForList("selectAllUsers");

for(Iteratoriter=users.iterator();iter.hasNext();){

Useruser=(User)iter.next();

System.out.println(user.getUsername());

}

//查询特定用户的数据

Useruser=(User)sqlMapper.queryForObject("selectUser",1);

System.out.println("用户【id="+1+"】的名称是:"+user.getUsername());

//更新用户的信息

user=newUser();

user.setId(3);

user.setUsername("更改之后的用户名称");

user.setPassword("密码被更改");

sqlMapper.update("updateUser",user);

//删除用户的信息

sqlMapper.delete("deleteUser",6);

}

}

-----------------------------------之二--------------------------

SqlMapClient对象

这个对象是iBatis操作数据库的接口(执行CRUD等操作),它也可以执行事务管理等操作。这个类是我们使用iBATIS的最主要的类。它是线程安全的。通常,将它定义为单例。(与hibernate中sessionFactory的定义类似)。如:

importjava.io.Reader;

importcom.ibatis.common.resources.Resources;

importcom.ibatis.sqlmap.client.SqlMapClient;

importcom.ibatis.sqlmap.client.SqlMapClientBuilder;

publicclassIbatisSQLMapConfig{

privatestaticfinalSqlMapClientsqlMap;

//在静态区块中初试化返回

static{

try{

//声明配置文件的名称(映射文件被定义在其中)

Stringresource="sql_map_config.xml";

//利用工具类Resources来读取到配置文件

Readerreader=Resources.getResourceAsReader(resource);

//创建SqlMapClient接口的变量实例

sqlMap=SqlMapClientBuilder.buildSqlMapClient(reader);

}catch(Exceptione){

e.printStackTrace();

thrownewRuntimeException(

"ErrorinitializingMyAppSqlConfigclass.Cause:"+e);

}

}

publicstaticSqlMapClientgetSqlMapInstance(){

//提供静态方法返回静态区块中得到的SqlMapClient

returnsqlMap;

}

}

主要用法:

如何获得刚插入记录的自增长ID值?

以下所有虚线上面代表User.xml中的内容,虚线下方是测试类中的内容:User类沿用上一篇中的User类

<insertid="insertUser"parameterclass="User">

insertintot_uservalues(

null,#username#,#password#

)

<selectKeyresultclass="int"keyProperty="id">

SELECT@@IDENTITYASID

</selectKey>

</insert>

Useruser=newUser();

user.setUsername("张三");

user.setPassword("张三密码");

//如果主键是自动生成的,则其返回值可以通过<selectKey>标签来设置

//如果不通过<selectKey>标签来设置,则返回值为空!

//<selectKey>中的keyProperty,是指定User中的id属性,当调用结束之后,

//user对象的id值和insert方法的返回值都是这条记录的ID值!

Objectobj=sqlMapper.insert("insertUser",user);

parameterClass的使用

<insertid="insertUser"parameterclass="User">

insertintot_uservalues(

null,#username#,#password#

)

<selectKeyresultclass="int"keyProperty="id">

SELECT@@IDENTITYASID

</selectKey>

</insert>

<insertid="insertUser2">

insertintot_uservalues(

null,#username#,#password#

)

<selectKeyresultclass="int"keyProperty="id">

SELECT@@IDENTITYASID

</selectKey>

</insert>

insertUser使用了parameterClass,所以必需传入User类型的对象

Useruser=newUser();

user.setUsername("张三");

user.setPassword("张三密码");

//传递进去的对象,必须是User类型

Objectobj=sqlMapper.insert("insertUser",user);

insertUser2没有使用parameterClass,所以可以传入任意具有相应属性值的对象

JustAnObjectanobj=newJustAnObject();

anobj.setUsername("用户名");

anobj.setPassword("用户密码");

//如果没有指定parameterClass属性,则任何一个具有相应属性值

//的对象都可以被传递进去

Objectobj=sqlMapper.insert("insertUser2",anobj);

parameterMap的使用

<parameterMapclass="User"id="insertUser-param">

<parameterproperty="username"/>

<parameterproperty="password"/>

</parameterMap>

<insertid="insertUser"parameterMap="insertUser-param">

insertintot_uservalues(

null,?,?

)

<selectKeyresultclass="int"keyProperty="id">

SELECT@@IDENTITYASID

</selectKey>

</insert>

parameterMap用于传入参数,以便匹配SQL语句中的?号

Useruser=newUser();

user.setUsername("张三dd");

user.setPassword("张三密码dd");

Objectobj=sqlMapper.insert("insertUser",user);

利用parameterMap,可以定义参数对象的属性如何映射到SQL查询语句的动态参数上,注意parameterMap中<parameter/>标签的先后顺序不能颠倒!

如何将查询结果映射到不同的对象?(resultClass的使用)

packagecom.ibatis.model;

publicclassOtherObject{

privateintid;

privateStringprop1;

privateStringprop2;

publicintgetId(){

returnid;

}

publicvoidsetId(intid){

this.id=id;

}

publicStringgetProp1(){

returnProp1;

}

publicvoidsetProp1(StringProp1){

this.Prop1=Prop1;

}

publicStringgetProp2(){

returnusername;

}

publicvoidsetProp2(StringProp2){

this.Prop2=Prop2;

}

}

<selectid="selectUserForOtherObject"resultclass="com.ibatis.OtherObject"parameterclass="int">

select

usernameasprop1,

passwordasprop2

fromt_userwhereid=#value#

</select>

//查找t_user表,将其结果映射到一个属性名不同的对象中!

OtherObjectobj=(OtherObject)sqlMapper.queryForObject("selectUserForOtherObject",1);

System.out.println(obj.getProp1()+","+obj.getProp2());

如何将查询结果集映射到不同的对象?(resultMap的基本使用)

<resultMapclass="com.ibatis.model.OtherObject"id="ooResult">

<resultproperty="prop1"column="username"/>

<resultproperty="prop2"column="password"/>

</resultMap>

<!--

如果使用resultMap来定义如何映射,则如下语句不可写成:

selectusernameasprop1,passwordasprop2....

-->

<selectid="selectUserForOtherObject2"parameterclass="int"resultMap="ooResult">

select

username,

password

fromt_userwhereid=#value#

</select>

//查找t_user表,将其结果映射到一个属性名不同的对象中!

OtherObjectobj=(OtherObject)sqlMapper.queryForObject("selectUserForOtherObject2",17);

System.out.println(obj.getProp1()+","+obj.getProp2());

如何将查询结果集映射为xml格式的数据?

<selectid="selectXmlData"resultclass="xml"xmlResultname="User"parameterclass="int">

select*fromt_userwhereid=#value#

</select>

<selectid="selectXmlDatas"resultclass="xml"xmlResultname="User">

select*fromt_user

</select>

//查找t_user表,将其结果映射到xml!

//返回值是xml形式的字符串

Objectobj=(Object)sqlMapper.queryForObject("selectXmlData",1);

System.out.println(obj);

//查找t_user表,将其结果映射到xml!

Listlist=(List)sqlMapper.queryForList("selectXmlDatas");

System.out.println(list);

如何用Map类型的对象作为传入参数?

<!--

这里,可以使用全路径类名,如:

java.util.Map

java.util.HashMap

java.util.TreeMap

map

-->

<insertid="insertUser"parameterclass="map">

insertintot_uservalues(

null,#username#,#password#

)

</insert>

Mapuser=newTreeMap();

user.put("username","Map用户");

user.put("password","Map用户密码");

sqlMapper.insert("insertUser",user);

如何将查询结果集的元素转换为Map类型的对象?

<!--

resultClass可以定义为java.util.HashMap类型,

将能自动转换

-->

<selectid="selectMapUsers"resultclass="java.util.HashMap">

select*fromt_user

</select>

Listlist=(List)sqlMapper.queryForList("selectMapUsers");

System.out.println(list);

for(Iteratoriter=list.iterator();iter.hasNext();){

Mapmap=(Map)iter.next();

//可在此输出map的数据

}

事务处理

可以使用sqlMapClient的startTransaction/commitTransaction/endTransaction等方法来控制事务的边界。

如果与spring整合(这是iBatis推荐的方式),则我们需要在spring配置文件中指定其事务特性。

-----------------------------------之三--------------------------

Spring通过DAO模式,提供了对iBATIS的良好支持。SqlMapClient对象是iBATIS中的主要对象,我们可以通过配置让spring来管理SqlMapClient对象的创建。

与hibernate类似,Spring提供了SqlMapClientDaoSupport对象,我们的DAO可以继承这个类,通过它所提供的SqlMapClientTemplate对象来操纵数据库。看起来这些概念都与hibernate类似。

通过SqlMapClientTemplate来操纵数据库的CRUD是没有问题的,这里面关键的问题是事务处理。Spring提供了强大的声明式事务处理的功能,我们已经清楚hibernate中如何配置声明式的事务,那么在iBATIS中如何获得声明式事务的能力呢?

第一,我们需要了解的是spring通过AOP来拦截方法的调用,从而在这些方法上面添加声明式事务处理的能力。典型配置如下:applicationContext-common.xml

<!--配置事务特性-->

<tx:adviceid="txAdvice"transaction-manager="事务管理器名称">

<tx:attributes>

<tx:methodname="add*"propagation="REQUIRED"/>

<tx:methodname="del*"propagation="REQUIRED"/>

<tx:methodname="update*"propagation="REQUIRED"/>

<tx:methodname="*"read-only="true"/>

</tx:attributes>

</tx:advice>

<!--配置哪些类的方法需要进行事务管理-->

<aop:config>

<aop:pointcutid="allManagerMethod"expression="execution(*com.ibatis.manager.*.*(..))"/>

<aop:advisoradvice-ref="txAdvice"pointcut-ref="allManagerMethod"/>

</aop:config>

这些事务都是声明在业务逻辑层的对象上的。

第二,我们需要一个事务管理器,对事务进行管理。

<beanid="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<propertyname="dataSource"ref="dataSource"/>

</bean>

<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource">

<propertyname="driverClassName"value="com.mysql.jdbc.Driver"/>

<propertyname="url"value="jdbc:mysql://127.0.0.1/ibatis"/>

<propertyname="username"value="root"/>

<propertyname="password"value="mysql"/>

</bean>

此后,我们需要让spring来管理SqlMapClient对象:

<beanid="sqlMapClient"class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

<propertyname="configLocation"><value>classpath:sqlMapConfig.xml</value></property>

</bean>

我们的sqlMapConfig.xml就可以简写为:

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEsqlMapConfig

PUBLIC"-//ibatis.apache.org//DTDSQLMapConfig2.0//EN"

"http://ibatis.apache.org/dtd/sql-map-config-2.dtd">

<sqlMapConfig>

<settings

lazyLoadingEnabled="true"

useStatementNamespaces="true"/>

<!--使用spring之后,数据源的配置移植到了spring上,所以iBATIS本身的配置可以取消-->

<sqlMapresource="com/ibatis/dao/impl/ibatis/User.xml"/>

</sqlMapConfig>

User.xml:如下

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEsqlMap

PUBLIC"-//ibatis.apache.org//DTDSQLMap2.0//EN"

"http://ibatis.apache.org/dtd/sql-map-2.dtd">

<sqlMapnamespace="User">

<!--Usetypealiasestoavoidtypingthefullclassnameeverytime.-->

<typeAliasalias="User"type="com.ibatis.User"/>

<!--SelectwithnoparametersusingtheresultmapforAccountclass.-->

<selectid="selectAllUsers"resultclass="User">

select*fromt_user

</select>

<selectid="selectUser"resultclass="User"parameterclass="int">

select*fromt_userwhereid=#id#

</select>

<insertid="insertUser"parameterclass="User">

insertintot_uservalues(

null,#username#,#password#

)

</insert>

<updateid="updateUser"parameterclass="User">

updatet_usersetusername=#username#,password=#password#

whereid=#id#

</update>

<deleteid="deleteUser"parameterclass="int">

deletefromt_userwhereid=#id#

</delete>

</sqlMap>

我们的DAO的编写:

packagecom.iabtis.dao.impl.ibatis;

importjava.util.List;

importorg.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

importcom.ibatis.dao.UserDAO;

importcom.ibatis.crm.model.User;

publicclassUserDAOImplextendsSqlMapClientDaoSupportimplementsUserDAO{

publicvoidselect(Useruser){

getSqlMapClientTemplate().delete("selectUser",user.getId());

}

publicListfindAll(){

returngetSqlMapClientTemplate().queryForList("selectAllUsers");

}

publicvoiddelete(Useruser){

getSqlMapClientTemplate().delete("deleteUser",user.getId());

}

publicvoidsave(Useruser){

getSqlMapClientTemplate().insert("insertUser",user);

}

publicvoidupdate(Useruser){

getSqlMapClientTemplate().update("updateUser",user);

}

}

继承SqlMapClientDaoSupport,要求我们注入SqlMapClient对象,因此,需要有如下的DAO配置:

<beanid="userDAO"class="com.ibatils.dao.impl.ibatis.UserDAOImpl">

<propertyname=”sqlMapClient”ref=”sqlMapClient”/>

</bean>

这就是所有需要注意的问题了,此后就可以在业务逻辑层调用DAO对象了!

相关推荐