Ibatis

来源:互联网 发布:linux内核编译教程 编辑:程序博客网 时间:2024/06/03 05:33

  数据访问层框架,ORM,Object Relation Mapping,将对象映射到关系,通过操作对象来达到操作关系的目的。
  通过hibernate访问数据层不需要自己编写sql,简单智能,调用方法就可完成。ibatis需要自己编写sql语句,更加灵活,可对sql进行优化。ibatis的最后版本为2.3.4,从3.x开始,转投到Google Code门下,并改名为MyBatis。

===========================================

  ibatis的核心类是SqlMapClient,通过其可完成对数据库的访问操作。
  spring提供的SqlMapClientFactoryBean对SqlMapClient进行了封装,类内提供对SqlMapClient实例进行初始化的方法,并提供返回SqlMapClient实例的方法getObject。SqlMapClientFactoryBean实现FactoryBean接口,spring规定实现该接口的Bean,由框架实例化时,返回的是getObject返回的实例,这也体现了SqlMapClientFactoryBean是SqlMapClient的实例工厂的意义——配置SqlMapClientFactoryBean,要注入configLocation属性,对应ibatis的配置文件;datasource属性,对应数据源bean。
  spring提供的SqlMapClientTemplate对SqlMapClient进行了封装,类内实际是对SqlMapClient的增删改查方法做了一个外包层,类内SqlMapClient实例的初始化需要外部的注入,本身不提供初始化方法。SqlMapClientTemplate继承JdbcAccessor,JdbcAccessor内部封装了DataSource数据源Bean——配置SqlMapClientTemplate,要注入sqlMapClient属性,对应注入SqlMapClientFactoryBean的实例,因为其返回的就是SqlMapClient的实例;datasource属性,对应数据源bean。
  spring提供的SqlMapClientDaoSupport对SqlMapClientTemplate进行了封装,是一个抽象类,必须继承才能使用,类内以new的方式生成一个SqlMapClientTemplate的实例。
  
  DataSource可在SqlMapClientFactoryBean内注入,也可在SqlMapClientTemplate内注入,放在SqlMapClientTemplate内更合适。
  实际项目中肯能会有多个数据源,如mysql、sqlserver、oracle等。
  SqlMapClientFactoryBean旨在生成SqlMapClient的实例,与属性configLocation有关,需要指明映射关系,而SqlMapClient实例的生成与属性datasource无关,仅在连接数据库时会用到。
  SqlMapClientTemplate内部使用SqlMapClient的实例进行数据库操作,需要连接数据库,必须注入属性datasource。
  针对不同的数据源,需要对每个数据源配置一个SqlMapClientFactoryBean用于注入对应数据源的映射文件,需要对每个数据源配置一个SqlMapClientTemplate用于注入数据源bean来连接不同的数据库。

  dao的三种实现方式,根据设计模式能用对象组合不用继承的原则,不建议使用后两种方式。
  对象组合方式,dao内部定义SqlMapClientTemplate的实例,SqlMapClientTemplate的实例由spring注册并注入,SqlMapClientTemplate要注入SqlMapClientFactoryBean与DataSource。
  继承方式,dao继承SqlMapClientTemplate,dao的配置也就包括了SqlMapClientTemplate的配置,dao内部可以直接使用继承的方法操作数据库,dao配置要注入SqlMapClientFactoryBean与DataSource——类内属性不加注解,配置文件内也不给类注入,配置文件头部<beans default-autowire="byName"> 给出default-autowire,spring也能完成注入。
  继承方式,dao继承SqlMapClientDaoSupport,同样dao的配置也包括了SqlMapClientTemplate的配置,dao内部可以直接使用继承的SqlMapClientTemplate实例操作数据库,dao配置要注入SqlMapClientFactoryBean与DataSource——类内只给出set方法,不给出属性定义,spring也能完成注入。

===========================================

  ibatis中一个pojo对应一个dao,一个dao对应一个映射文件,由此项目中通常会有多个映射文件。由于ibatis最终会将所有的映射文件合并到一起,为防止id冲突,需要命名空间namespace来唯一标识该映射文件。
  以下两个配置文件在dao层,属于ibatis的内容。

// Computer.xml// namespace,通常用pojo名<sqlMap namespace="Computer">    // alias,类型别名,通常为首字母小写的pojo名    <typeAlias alias="computer" type="xx.Computer" />    // 对应一类查询结果集    // class,指明查询结果要映射的pojo类    <resultMap id="all" class="computer">        // 指明pojo类的属性与关系表中字段的对应关系        // jdbcType与javaType的对应关系用时去网上查一下,不要背        <result property="id" column="id" jdbcType="INT" javaType="java.lang.Integer" />        <result property="name" column="name" jdbcType="VARCHAR" javaType="java.lang.String" />        <result property="price" column="price" jdbcType="VARCHAR" javaType="java.lang.String"/>    </resultMap>    <resultMap id="part" class="computer">        <result property="name" column="name" jdbcType="VARCHAR" javaType="java.lang.String" />        <result property="price" column="price" jdbcType="VARCHAR" javaType="java.lang.String"/>    </resultMap>    // id,指出该sql语句的名字,代码中会用到,用时必须加命名空间    // parameterClass,指出参数类型    <insert id="insert" parameterClass="computer">        // CDATA中的内容被定义为纯文本,以防与xml标签混淆        // 在#之间的为变量        <![CDATA[            insert into computer(name, price) values(#name#, #price#)        ]]>        // selectKey,用于在插入时自动生成主键        // keyProperty,定义主键名字        // resultClass,定义返回类型        <selectKey resultClass="java.lang.Long" keyProperty="id">            // 返回上次插入自动生成的id            select @@IDENTITY as id        </selectKey>    </insert>    // 项目中不要用基本类型,要用类包装    // 也有将删除操作放在update标签内的,没多大区别    <delete id="delete" parameterClass="java.lang.Long">        delete from computer where id = #id#    </delete>    <update id="update" parameterClass="computer">        update computer set name = #name#, price = #price# where id = #id#        // 或        // dynamic的prepend值会覆盖条件标签中第一个条件为真的prepend的值        // 前提是条件标签prepend的值被设置且长度 > 0        update computer        <dynamic prepend="set">            <isNotEmpty property="name" prepend=','>                name = #name#            </isNotEmpty>            <isNotEmpty property="price" prepend=','>                price  = #price #            </isNotEmpty>        </dynamic>        where id = #id#    </update>    // select查询出的字段必须和resultMap配置的字段对应,多了、少了或不对应都会抛出异常    // ibatis内部会将查询结果依次赋值到resultMap配置的pojo实例内对应的属性上    // resultMap,为前面定义的resultMap的id    <select id="list" resultMap="all">        select id, name, price from computer    </select>    // 或    // resultMap是显示映射,pojo属性与关系字段映射明确,性能更好,推荐使用    // resultClass,指出查询结果要映射的类,为隐式映射,若pojo的属性名与关系的字段名不同,查询结果就不会映射到类    <select id="list" resultClass="computer">        select id, name, price from computer    </select>    // 查询结果仅一个字段    <select id="getName" parameterClass="java.lang.Long" resultClass="java.lang.String">        select name from computer where id = #id#    </select>    // sql标签用来定义sql语句片段    // id,为sql片段标识,后面可根据此id拼接sql语句    <sql id="list_where">        // isNotNull,指当property设置的变量name不为空时,执行标签里内容        // prepend,表示将其内容and追加在isNotNull标签的内容之前        <isNotNull property="name" prepend="and">            name = #name#        </isNotNull>        <isNotNull property="price" prepend="and">            price = #price#        </isNotNull>        // 上述打印内容为 and name = xx and price = xx        // 通过设置dynamic标签的prepend来覆盖第一个条件为真的and        // 打印内容为where name = xx and price = xx        <dynamic prepend="where">            <isNotNull property="name" prepend="and">                name = #name#            </isNotNull>            <isNotNull property="price" prepend="and">                price = #price#            </isNotNull>        </dynamic>    </sql>    // parameterClass,参数为map类型    <select id="list_2" parameterClass="map" resultMap="part">        // where 1 = 1,用于巧妙的连接name之前的and,若用dynamic可以不用此        // include,用于包含sql片段        // start,属性值来自map类型的参数        // limit start, rows 返回查询结果的第start行,偏移从0开始,共返回rows行        // limit start, -1 返回查询结果的第start,及其之后的所有行        // limit end 等价于 limit 0, end 返回查询结果第end行,及其之前的所有行        // #与$的区别,#之间放变量,$用于字符串之间的拼接,$间不要放字符或字符串变量,否则出错        select name, price from computer        where 1 = 1        <include refid="list_where" />        order by id asc        <isNotNull property="start" prepend=" ">            limit $start$, $rows$        </isNotNull>    </select></sqlMap>// sqlmap-config-mysql.xml// 用于配置数据源信息,以及整合全部的映射文件// 若有其它异构数据库,应单独建立另一个文件,如sqlmap-config-sqlserver.xml<sqlMapConfig>    // useStatementNamespaces,设为true表示开启映射文件的命名空间    <settings useStatementNamespaces="true"/>    // 配置数据源,与spring整合后,该部分移植到spring配置文件    ....    // 以当前目录为相对路径,加载映射文件    <sqlMap resource="xx/mysql/xx.xml" /></sqlMapConfig>

===========================================

  以下配置文件在web层,属于spring与ibatis的整合内容。

// spring-config-datasource-dbcp.xml// 所有的数据源在此配置<beans>    // 将数据源注册为bean    <bean id="mysqlDataSource" class="..BasicDataSource">        // 属性的名字都是在BasicDataSource里定义好的,不要自定义        <property name="driverClassName" value="com.mysql.jdbc.Driver" />        <property name="url" value="jdbc:mysql://localhost:3306/xxdb" />        <property name="username" value="root" />        <property name="password" value="123" />    </bean>    // 其它的数据源,如sqlserver、oracle、分库的</beans>// spring-dao.xml// 注册项目所有的dao<beans>    // 注册SqlMapClientFactoryBean    <bean id="sqlMapClient" class="..SqlMapClientFactoryBean">        // SqlMapClientFactoryBean源码内定义了属性dataSource和configLocation        // dataSource放在SqlMapClientTemplate内注入        // configLocation在此注入,看为与ibatis整合的入口        <property name="configLocation" value="classpath:sqlmap-config-mysql.xml" />    </bean>    // 针对不同的数据源,要再次配置新的SqlMapClientFactoryBean    ....    // 配置SqlMapClientTemplate    <bean id="mysqlSqlMapClientTemplate" class="..SqlMapClientTemplate">        <property name="dataSource" ref="mysqlDataSource">        // SqlMapClientTemplate源码内定义了ibatis的SqlMapClient类型的属性sqlMapClient        <property name="sqlMapClient" ref="sqlMapClient">    </property>    // 针对不同的数据源,要再次配置新的SqlMapClientTemplate    ....    // 放到项目用注解完成    <bean id="xxDaoImpl" class="xx.xxDaoImpl">          <property name="myClientTemplate" ref="mysqlSqlMapClientTemplate" />    </bean></beans>// spring-config.xml// 将上述xml文件整合到一起@Repository("computerDao ")public class ComputerDaoImpl implements ComputerDao {    @Resource(name = "mysqlSqlMapClientTemplate")    private SqlMapClientTemplate mysqlTool;    ..    public Integer insertComputer(Computer computer) {        // 加命名空间        return (Integer)mysqlTool.insert("Computer.insert", computer);    }}
0 0