目录:
一、iBatis简介
二、iBatis基础操作演示
三、如何搭建Spring+iBatis集成开发环境
四、Spring+iBatis的CRUD数据操作实现
五、iBatis高级应用
六、Spring+iBatis方案优点
我们的目标是:能够熟练运用当前流行的java开源框架:iBatis,掌握iBatis与Spring框架的集成方式。
DAO 模式就是在业务逻辑层和持久化存储层之间引入了新的抽象层。业务对象通过数据访问对象访问关系型数据库(数据源)。抽象层简化了应用程序代码增强了灵活性。试想一下哪天改变了数据源,比如更换为其他数据库厂商的产品,只需要修改数据访问对象,并且对业务对象的影响也是最小的。
iBatis简介(一)
采用JDBC实现DAO设计模式的缺点:
代码重复:正如 EmployeeDAOImpl 类列出的,代码重复是基于 JDBC 的传统数据库访问的主要问题。反复书写代码明显违反了基本的 OO 代码复用原则。对于项目开销、时间和消耗都有着明显的不利因素。
耦合:DAO 代码非常紧密的和 JDBC 接口以及核心集合类型耦合在一起。这点可以从每个 DAO 类导入语句的数目体现。
资源泄漏:进入 EmployeeDAOImpl 类的设计,所有 DAO 方法都必须释放已获取的数据库资源的控制权,比如 connection、statements 以及结果集。这样做是很危险的,因为一名没有经验的程序员可以很容易的绕开这些程序块。结果资源将流失,最终导致系统当机。
错误捕获:JDBC 驱动通过抛出 SQLException 报告所有的错误情况。SQLException 是 checked exception。因此开发者被迫处理它——即使无法从大部分异常中恢复,这样也就导致了混乱的代码。此外,从 SQLException 对象获取错误代码和消息是数据库供应商特定的,因此不可能编写灵活的 DAO 错误消息代码。
脆弱的代码:在基于 JDBC 的 DAO 中,为 statement 对象绑定变量的设置,以及获取数据使用的结果集 getter 方法是频繁用到的两个任务。如果 SQL 语句中的列数改变了,或者列的位置改变了,代码将不得不再经过严格的反复修改、测试然后部署。
package com.anduo.ssi.domain; public class UserVO { /** * This field was generated by Apache iBATIS ibator. * This field corresponds to the database column user.userid * * @ibatorgenerated Tue Mar 27 19:50:47 CST 2012 */ private Integer userid; /** * This field was generated by Apache iBATIS ibator. * This field corresponds to the database column user.username * * @ibatorgenerated Tue Mar 27 19:50:47 CST 2012 */ private String username; /** * <p>Discription:[构造器方法描述]</p> * @coustructor 方法. */ public UserVO() { } public UserVO(String username) { this.username = username; } /** * This method was generated by Apache iBATIS ibator. * This method returns the value of the database column user.userid * * @return the value of user.userid * * @ibatorgenerated Tue Mar 27 19:50:47 CST 2012 */ public Integer getUserid() { return userid; } /** * This method was generated by Apache iBATIS ibator. * This method sets the value of the database column user.userid * * @param userid the value for user.userid * * @ibatorgenerated Tue Mar 27 19:50:47 CST 2012 */ public void setUserid(Integer userid) { this.userid = userid; } /** * This method was generated by Apache iBATIS ibator. * This method returns the value of the database column user.username * * @return the value of user.username * * @ibatorgenerated Tue Mar 27 19:50:47 CST 2012 */ public String getUsername() { return username; } /** * This method was generated by Apache iBATIS ibator. * This method sets the value of the database column user.username * * @param username the value for user.username * * @ibatorgenerated Tue Mar 27 19:50:47 CST 2012 */ public void setUsername(String username) { this.username = username == null ? null : username.trim(); } }
<?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.anduo.ssi.domain.UserVO" /> <resultMap id="user" class="com.anduo.ssi.domain.UserVO"> <!-- WARNING - This element is automatically generated by Apache iBATIS ibator, do not modify. This element was generated on Tue Mar 27 19:50:47 CST 2012. --> <result column="userid" property="userid" jdbcType="INTEGER" /> <result column="username" property="username" jdbcType="VARCHAR" /> </resultMap> <!-- 新增 --> <insert id="insert" parameterClass="user"> INSERT INTO USER(USERNAME) VALUES(#username#) </insert> <!-- 删除 --> <delete id="delete" parameterClass="user"> DELETE FROM USER T WHERE T.USERID = #userid# </delete> <!-- 更新 --> <update id="update" parameterClass="user"> UPDATE USER <dynamic prepend="SET"> <isNotNull prepend="," property="username"> USERNAME=#USERNAME# </isNotNull> <isNotNull prepend="," property="password"> PASSWORD=#PASSWORD# </isNotNull> </dynamic> WHERE ID=#ID# </update> <!-- 查询全部 --> <select id="selectAllUserInfo" resultClass="user"> SELECT T.USERID,T.USERNAME FROM USER T </select> <!-- 根据ID查询 --> <select id="selectUserInfoById" resultClass="user"> SELECT T.USERID,T.USERNAME FROM USER T WHERE T.USERID=#userid# </select> <!-- 动态查询 --> <select id="dynamicSelectUserInfo" resultClass="user"> SELECT T.USERID,T.USERNAME FROM USER T <dynamic prepend="WHERE"> <isNotEmpty prepend="AND" property="userid"> T.USERID = #userid# </isNotEmpty> <isNotEmpty prepend="AND" property="username"> T.USERNAME LIKE '%$username$%' </isNotEmpty> </dynamic> </select> </sqlMap>
package com.anduo.ssi.dao; import java.sql.SQLException; import java.util.List; import java.util.Map; import org.springframework.dao.DataAccessException; import org.springframework.orm.ibatis.SqlMapClientCallback; import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport; import com.ibatis.sqlmap.client.SqlMapExecutor; import com.anduo.ssi.common.exception.BaseDataAccessException; public abstract class BaseDAO<E> extends SqlMapClientDaoSupport implements DAO<E>{ /** * <p>Discription:[方法功能中文描述]</p> * @param statement * @param parameter * @return * @throws BaseDataAccessException * @author:[安多] * @update:[日期YYYY-MM-DD] [更改人姓名][变更描述] */ @SuppressWarnings("unchecked") public List<E> getDataList(String statement, Object parameter) throws BaseDataAccessException { List<E> result = null; try{ result = getSqlMapClientTemplate().queryForList(statement, parameter); }catch(DataAccessException e){ throw new BaseDataAccessException(e); } return result; } /** * <p>Discription:[方法功能中文描述]</p> * @param statement * @param parameter * @return * @throws BaseDataAccessException * @author:[安多] * @update:[日期YYYY-MM-DD] [更改人姓名][变更描述] */ @SuppressWarnings("unchecked") public E getData(String statement, Object parameter) throws BaseDataAccessException { E result = null; try{ result = (E) getSqlMapClientTemplate().queryForObject(statement, parameter); }catch(DataAccessException e){ throw new BaseDataAccessException(e); } return result; } /** * <p>Discription:[方法功能中文描述]</p> * @param statement * @param parameter * @return * @throws BaseDataAccessException * @author:[安多] * @update:[日期YYYY-MM-DD] [更改人姓名][变更描述] */ public int getDataCount(String statement, Object parameter) throws BaseDataAccessException { Integer result= null; try{ result = (Integer) getSqlMapClientTemplate().queryForObject(statement, parameter); }catch(DataAccessException e){ throw new BaseDataAccessException(e); } return result; } /** * <p>Discription:[方法功能中文描述]</p> * @param statement * @param data * @return * @throws BaseDataAccessException * @author:[安多] * @update:[日期YYYY-MM-DD] [更改人姓名][变更描述] */ public int updateData(String statement, E data) throws BaseDataAccessException { Integer result= null; try{ result = getSqlMapClientTemplate().update(statement, data); }catch(DataAccessException e){ throw new BaseDataAccessException(e); } return result; } /** * <p>Discription:[方法功能中文描述]</p> * @param statement * @param map * @return * @throws BaseDataAccessException * @author:[安多] * @update:[日期YYYY-MM-DD] [更改人姓名][变更描述] */ public int updateData(String statement, Map<String, Object> map) throws BaseDataAccessException { Integer result= null; try{ result = getSqlMapClientTemplate().update(statement, map); }catch(DataAccessException e){ throw new BaseDataAccessException(e); } return result; } /** * <p>Discription:[方法功能中文描述]</p> * @param statement * @param data * @return * @throws BaseDataAccessException * @author:[安多] * @update:[日期YYYY-MM-DD] [更改人姓名][变更描述] */ public Object insertData(String statement, E data) throws BaseDataAccessException { Object result = null; try{ result = getSqlMapClientTemplate().insert(statement, data); }catch(DataAccessException e){ throw new BaseDataAccessException(e); } return result; } /** * <p>Discription:[方法功能中文描述]</p> * @param statement * @param map * @return * @throws BaseDataAccessException * @author:[安多] * @update:[日期YYYY-MM-DD] [更改人姓名][变更描述] */ public Object insertData(String statement, Map<String, Object> map) throws BaseDataAccessException { Object result = null; try{ result = getSqlMapClientTemplate().update(statement, map); }catch(DataAccessException e){ throw new BaseDataAccessException(e); } return result; } /** * <p>Discription:[方法功能中文描述]</p> * @param statement * @param data * @return * @throws BaseDataAccessException * @author:[安多] * @update:[日期YYYY-MM-DD] [更改人姓名][变更描述] */ public int deleteDate(String statement, String data) throws BaseDataAccessException{ Integer result = null; try{ result = getSqlMapClientTemplate().delete(statement, data); }catch(DataAccessException e){ throw new BaseDataAccessException(e); } return result; } /** * <p>Discription:[方法功能中文描述]</p> * @param statement * @param map * @return * @throws BaseDataAccessException * @author:[安多] * @update:[日期YYYY-MM-DD] [更改人姓名][变更描述] */ public int deleteDate(String statement, Map<String, Object> map) throws BaseDataAccessException{ Integer result = null; try{ result = getSqlMapClientTemplate().delete(statement, map); }catch(DataAccessException e){ throw new BaseDataAccessException(e); } return result; } /** * <p>Discription:[方法功能中文描述]</p> * @param statement * @param map * @throws BaseDataAccessException * @author:[安多] * @update:[日期YYYY-MM-DD] [更改人姓名][变更描述] */ public void executeBatch(final String statement, final Map<String, E> map) throws BaseDataAccessException { try{ getSqlMapClientTemplate().execute(new SqlMapClientCallback() { public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException { executor.startBatch(); for (Object o : map.keySet()) { executor.update(statement, map.get(o)); } executor.executeBatch(); return null; } }); }catch(DataAccessException e){ throw new BaseDataAccessException(e); } } /** * <p>Discription:[方法功能中文描述]</p> * @param statement * @param list * @throws BaseDataAccessException * @author:[安多] * @update:[日期YYYY-MM-DD] [更改人姓名][变更描述] */ public void executeBatch(final String statement, final List<?> list) throws BaseDataAccessException { try{ getSqlMapClientTemplate().execute(new SqlMapClientCallback() { public Object doInSqlMapClient(SqlMapExecutor executor) throws SQLException { executor.startBatch(); for (Object o : list) { executor.update(statement, o); } executor.executeBatch(); return null; } }); }catch(DataAccessException e){ throw new BaseDataAccessException(e); } } }
package com.anduo.ssi.dao.impl; import com.anduo.ssi.dao.BaseDAO; import com.anduo.ssi.dao.UserDAO; import com.anduo.ssi.domain.UserVO; /** * <p>Description: [描述该类概要功能介绍]</p> * @author * @version $Revision$ */ public class UserDAOImpl extends BaseDAO<UserVO> implements UserDAO { }