zoukankan      html  css  js  c++  java
  • ibatis学习三入门之sqlMap的OR映射配置

          先看一个sqlMap的示例

    User.java

    View Code
     1 package com.si.ibatis.model;
     2 
     3 import java.io.Serializable;
     4 
     5 public class User implements Serializable{
     6     private Integer id;
     7     private String username;
     8     private String password;
     9     private String address;
    10     
    11     public User() {
    12         super();
    13         // TODO Auto-generated constructor stub
    14     }
    15     public User(Integer id, String username, String password, String address) {
    16         super();
    17         this.id = id;
    18         this.username = username;
    19         this.password = password;
    20         this.address = address;
    21     }
    22     
    23     public String toString(){
    24         return "User id:" + id + ",  username" + username + ", password: " + password + ", address: " + address;
    25     }
    26 }

    User.xml

     1 <?xml version="1.0" encoding="UTF-8" ?>
     2 <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd">
     3 <sqlMap namespace="User">
     4 
     5     <typeAlias alias="User" type="com.si.ibatis.model.User"/>
     6     
     7     <parameterMap class="java.util.HashMap" id="paramteterMap">
     8        <parameter property="username"></parameter>
     9        <parameter property="password"></parameter>
    10     </parameterMap>
    11     
    12     <resultMap id="UserResult" class="User">
    13         <result property="id" column="id"/>
    14         <result property="username" column="username"/>
    15         <result property="address" column="address"/>
    16         <result property="password" column="password"/>
    17     </resultMap>
    18     <!-- 添加User -->
    19     <insert id="addUser">
    20         insert user(
    21         username,
    22         password,
    23         address
    24         )
    25         values(
    26         #username#,
    27         #password#,
    28         #address#
    29         )
    30     </insert>  
    31     
    32     <!-- 出错  parameterMap="parameterMap" -->
    33     <select id="findUser" resultMap="UserResult" parameterClass="java.util.HashMap">
    34         select * from user WHERE username=#username# and password=#password#
    35     </select>
    36     <select id="findUserById" resultMap="UserResult" parameterClass="int">
    37         select * from user WHERE id=#id#
    38     </select> 
    39     <select id="findAllUser" resultClass="User">
    40         select * from user
    41     </select>
    42     <!-- User表内记录总条数  -->
    43     <select id="getTotalCount" resultClass="int">
    44         select count(*) from user
    45     </select>
    46     
    47     <!-- 删除User -->
    48     <delete id="deleteUserById" parameterClass="java.lang.Integer">
    49       delete from user where id=#id#
    50     </delete>
    51     
    52     <!-- 修改User -->
    53     <update id="updateUser" parameterClass="User">
    54         update user set username=#username#, password=#password#, address=#address#
    55         where id=#id#
    56     </update>
    57 
    58 </sqlMap>

    SqlMapConfig.xml文件

    View Code
     1 <?xml version="1.0" encoding="UTF-8" ?>  
     2 <!DOCTYPE sqlMapConfig        
     3     PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN"        
     4     "http://ibatis.apache.org/dtd/sql-map-config-2.dtd">  
     5 <sqlMapConfig>  
     6     
     7     <!-- 各节点先后顺序不能颠倒  -->
     8     <properties resource="jdbc.properties" />
     9     
    10     <!-- cacheModelsEnabled: 是否启用SqlMapClient上的缓存机制。 建议设为"true" -->
    11     <!-- enhancementEnabled: 是否针对POJO启用字节码增强机制以提升getter/setter的调用效能,避免Reflect所带来的性能开销。同时,这也为Lazy Loading带来提升。 建议设为"true"  -->
    12     <!-- lazyLoadingEnabled: 是否使用延迟加载机制,建议设置true -->
    13     <!-- errorTracingEnabled: 是否启用错误日志,在开发时设置为"true"可方便调试 -->
    14     <!-- maxRequests: 最大并发请求数(Statement并发数) -->
    15     <!-- maxSessions: 最大Session数。即当前最大允许的并发SqlMapClient数  -->
    16     <!-- maxTransactions: 最大并发事物数,应满足  maxTransactions < maxSessions < maxRequests -->
    17     <!-- useStatementNamespaces: 是否使用Statement命名空间。 这里的命名空间指的是映射文件中,sqlMap节的namespace属性,如在上例中针对user表的映射文件sqlMap节点: <sqlMap namespace="User"> 
    18                               这里指定了此sqlMap节点下定义的操作均属于"User"命名空间。 在useStatementNamespaces="true"的情况下,Statement调用需追加命名空间,如:sqlMap.update("User.findUserById", 1); 
    19                             否则直接通过Statement名称调用即可,如: sqlMap.update("findUserById",1); 但请注意此时需要保证所有映射文件中,Statement定义无重名。 -->
    20     <!--  -->
    21     <settings
    22         cacheModelsEnabled="true"
    23         enhancementEnabled="true"
    24         lazyLoadingEnabled="true"
    25         errorTracingEnabled="true"
    26         maxRequests="30"
    27         maxSessions="10"
    28         maxTransactions="5"
    29         useStatementNamespaces="false"
    30     />  
    31     
    32     
    33     
    34     <!-- transactionManager 节点定义了ibatis 的事务管理器,目前提供了以下几种选择:JDBC、JTA、EXTERNAL -->
    35     <!-- JDBC: 通过传统JDBC Connection.commit/rollback实现事务支持 -->
    36     <!-- JTA: 使用容器提供的JTA服务实现全局事务管理 -->
    37     <!-- EXTERNAL: 外部事务管理,如在EJB中使用ibatis,通过EJB的部署配置即可实现自动的事务管理机制。此时ibatis 将把所有事务委托给外部容器进行管理。
    38                                此外,通过Spring 等轻量级容器实现事务的配置化管理也是一个不错的选择 -->
    39     
    40     <transactionManager type="JDBC">
    41         <!-- type: dataSouce的实现类型。可选值: SIMPLE、DBCP、JNDI -->
    42         <!-- SIMPLE:SIMPLE是ibatis内置的dataSource实现,其中实现了一个简单的数据库连接池机制, 对应ibatis 实现类为
    43               com.ibatis.sqlmap.engine.datasource.SimpleDataSourceFactory -->
    44         <!-- DBCP: 基于Apache DBCP 连接池组件实现的DataSource 封装,当无容器提供DataSource 服务时,建议使用该选项,对应ibatis 实现类为
    45               com.ibatis.sqlmap.engine.datasource.DbcpDataSourceFactory -->
    46         <!-- JNDI: 使用J2EE 容器提供的DataSource 实现,DataSource 将通过指定的JNDI Name 从容器中获取。对应ibatis 实现类为
    47               com.ibatis.sqlmap.engine.datasource.JndiDataSourceFactory -->
    48         <dataSource type="SIMPLE">  
    49             <property name="JDBC.Driver" value="${jdbc.driverClassName}" />
    50             <property name="JDBC.ConnectionURL" value="${jdbc.url}" />
    51             <property name="JDBC.Username" value="${jdbc.username}" />  
    52             <property name="JDBC.Password" value="${jdbc.password}" />  
    53             
    54             
    55             <!-- 数据库连接池可维持的最大容量 -->
    56             <property name="Pool.MaximumActiveConnections" value="10"/>
    57             <!-- 数据库连接池中允许的挂起(idle)连接数 -->
    58             <property name="Pool.MaximumIdelConnections" value="5"/>
    59             <!-- 数据库联接池中,连接被某个任务所允许占用的最大时间,如果超过这个时间限定,连接将被强制收回。(毫秒) -->
    60             <property name="Pool.MaximumCheckoutTime" value="12000"/>
    61             <!-- 当线程试图从连接池中获取连接时,连接池中无可用连接可供使用,此时线程将进入等待状态,直到池中出现空闲连接。此参数设定了线程所允许等待的最长时间。(毫秒) -->
    62             <property name="Pool.TimeToWait" value="600"/>
    63             <!-- 数据库连接状态检测语句。某些数据库在连接在某段时间持续处于空闲状态时会将其断开。而连接池管理器将通过此语句检测池中连接是否可用。
    64                                                            检测语句应该是一个最简化的无逻辑SQL。如“select 1 from t_user”,如果执行此语句成功,连接池管理器将认为此连接处于可用状态 -->
    65             <property name="Pool.PingQuery" value="select 1 from USER"/>
    66             <!-- 是否允许检测连接状态 -->
    67             <property name="Pool.PingEnabled" value="true"/>
    68             <!-- 对持续连接时间超过设定值(毫秒)的连接进行检测 -->
    69             <property name="Pool.PingConnectionsOlderThan" value="1"/>
    70             <!-- 对空闲超过设定值(毫秒)的连接进行检测 -->
    71             <property name="Pool.PingConnectionsNotUsedFor" value="1"/>
    72         </dataSource>
    73     </transactionManager>
    74     
    75     <!-- sqlMap 节点指定了映射文件的位置,配置中可出现多个sqlMap 节点,以指定项目内所包含的所有映射文件 -->
    76     <sqlMap resource="com/si/sqlMap/User.xml" />  
    77 </sqlMapConfig>  

    jdbc.properties文件

    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=utf8
    jdbc.username=root
    jdbc.password=root

    测试一下

     1 public class Test {
     2     public static void main(String[] args) throws IOException, SQLException{
     3         String config = "SqlMapConfig.xml";
     4         Reader reader = Resources.getResourceAsReader(config);
     5         SqlMapClient sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);
     6         User temp = new User();
     7         temp.setUsername("lisi");
     8         temp.setPassword("lisi");
     9         temp.setAddress("lsfjlesfjse");
    10         sqlMap.insert("addUser", temp);
    11         User user1 = (User)sqlMap.queryForObject("findUserById", 1);
    12         User user2 = (User)sqlMap.queryForObject("findUserById", 2);
    13         System.out.println(user1);
    14         System.out.println(user2);
    15         user2.setUsername("lisikkk");
    16         sqlMap.update("updateUser", user2);
    17         List<User> list = sqlMap.queryForList("findAllUser");
    18         for(User user : list){
    19             System.out.println(user);
    20         }
    21     }
    22 }

    运行结果:

    1 User id:1,  usernamezhangsan, password: zhangsan, address: lakdjfalkejfakle
    2 User id:2,  usernamelisi, password: lisi, address: lsfjlesfjse
    3 User id:1,  usernamezhangsan, password: zhangsan, address: lakdjfalkejfakle
    4 User id:2,  usernamelisikkk, password: lisi, address: lsfjlesfjse

          typeAlias节点:为类取一个别名,方便引用

          映射语句主要有:select、insert、update、delete、procedure(执行存储过程)、statement(可以包含任意类型的语句)

          insert插入操作中,对于自增主键的表,插入可以不配置插入的主键列。否则是必须的。 如要获取主键,需要在插入语句之前配置,主要是针对Sequence主键而言,插入前必须指定一个主键值给要插入的记录。Oracle、DB2亦如此,方法是在插入语句标签<insert....>之前配置上: 
        <insert id="insertAccount" parameterClass="Account"> 
            <selectKey resultClass="long" keyProperty="sctId"> 
                SELECT SEQ_TEST.NEXTVAL FROM DUAL 
            </selectKey>  
            insert into .... ........ 
        </insert>

          使用参数  在映射语句中使用参数要使用#paramName#的形式,如果where语句中要使用like,可写为where username like concat('%',#value#,'%'),或使用文本替换语法$, 如where username like ‘%$value$%’。使用$要进行严格参数验证处理,避免sql注入。

          参数类型  参数类型有parameterClass和parameterMap,其中Class既可以为ibatis支持的原生类型(比如string、int、long等)也可用为自定义的Class(一般为POJO,使用typeAlias引入)。map是最强大的入参方式,任何入参方式都可以转换为这种入参方式,因为ibatis仅接受一个入参,当几个参数分布在不同对象中的时候,将这些对象的属性(或者对象本身put)到map中,然后一次传递给sql语句是非常有效。另外,map的中的元素(比如product)是个复杂对象,则还可以在SQL中以#product.name#的格式来引用其中内嵌的属性。

          返回值类型  返回值参数也同样有两种类型,一种是对象类型resultClass="Account",一种是resultMap="AccountResult"。当结果集列名和类属性名完全对应的时候,则应该使用resultClass来指定查询结果类型。当然有些列明不对应,可以在sql中使用as重命名达到一致的效果。 当查询结果列名和类属性名对应不上的时候,应该选择 resultMap指定查询结果集类型。否则,则查询出来填充的对象属性为空(数字的为0,对象的为null)。实际上 resultMap是对一个Java Bean的映射,需要先定义xml的映射后,才可以引用,例如:

    <resultMap id="UserResult" class="User">
            <result property="id" column="id"/>
            <result property="username" column="username"/>
            <result property="address" column="address"/>
            <result property="password" column="password"/>
    </resultMap>

    resultMap映射的结果的目的就是要将查询的结果集绑定到映射对象的属性上。

          不管使用哪种返回值参数类型,其最终目的就是要把每条记录映射到一个类的对象或者对象集合上,如果有某个类属性映射不上,则在得到的这个对象或对象集合中这个属性为空。映射的属性可以是表与实体中的一部分。

          sql片段  可以通过<sql id="sql_xxx">...</sql>定义SQL片段,然后<include refid="sql_xxx"/>来在各种语句中引用,达到复用目的。

          动态sql  可以通过使用动态SQL来组织灵活性更大的更通用的SQL,这样极大减少了编码量。感觉mybatis的动态sql配置起来更简洁易懂。 比如:一个动态的where条件 
                    <dynamic prepend="where"> 
                            <isNotEmpty prepend="and" property="$$$$$"> 
                                    $name like '%'|| #$name# ||'%' 
                            </isNotEmpty> 
                            <isGreaterThan prepend="and" property="$$$$$" compareValue="$$$number"> 
                                    $code like '%'|| #$code# ||'%' 
                            </isGreaterThan> 
                    </dynamic> 
         当然,prepend表示链接关键字,可以为任何字符串,当为sql关键字时,iBatis自动判断是否应该添加该关键字。该语法也很简单,关键是要会用心思考组织动态SQL。这里面有一点要注意:区别<isNotEmpty>和<isNotNull>区别,当为空空串时<isNotEmpty>返回true,当为空串时<isNotNull>返回真。

        结果集映射继承  结果集映射的继承的目的是为了映射定义的复用,比如下面定义了两个映射,AccountResult继承了base: 
        <resultMap id="base" class="Account"> 
            <result property="id" column="ACC_ID"/> 
            <result property="firstName" column="ACC_FIRST_NAME"/> 
            <result property="lastName" column="ACC_LAST_NAME"/> 
        </resultMap> 
        <resultMap id="AccountResult" class="Account" extends="Account.base"> 
            <result property="emailAddress" column="ACC_EMAIL"/> 
        </resultMap> 
    这样,就很容易扩展了一个映射策略。

          分页查询  ibatis提供了两种分页方式。第一种方式:结果集筛选分页。先执行部分页的SQL查询语句,然后得到一个 ResultSet,然后根据分页范围选择有效的记录填充到对象中,最终以集合的形式返回。 第二种方式:SQL分页,通过组装分页类型的SQL来实现分页。这个关键在于分页参数的传递和分页SQL的构建。分页SQL构件每种数据库都不一样,分页参数的传递却可以通用。可以使用map传递参数,连同分页参数一块传递进来。

          该文章非原创,除了例子外,后面的总结说明基本是我从其他人的博客和相关pdf文件中整理过来的,后面有列出参考文章,更详细全面的内容可以查看这些文章。

          刚开始写技术博客真心不习惯,一是自己还没有养成做笔记写博客的好习惯,二是学习东西没有深入研究过,很少仔细阅读完官方文档、示例和源码,三是文笔太差,写东西没有结构和思路。希望以后能改正这些,写出属于自己的优秀的技术文章。

    参考文章:

    shmily2038(iteye):iBatis SqlMap的配置总结

    sarin(iteye):iBatis查询select详解

    Anders Cui(cnblogs):iBATIS In Action:使用映射语句(二)

    夏昕: iBATIS 2.0 开发指南

  • 相关阅读:
    Java 实现 蓝桥杯 生兔子问题
    Java实现 蓝桥杯 基因牛的繁殖
    Java实现 蓝桥杯 基因牛的繁殖
    Java实现 蓝桥杯 基因牛的繁殖
    Java实现 LeetCode 33 搜索旋转排序数组
    Java实现 LeetCode 33 搜索旋转排序数组
    Java实现 LeetCode 33 搜索旋转排序数组
    深入探究VC —— 资源编译器rc.exe(3)
    深入探究VC —— 编译器cl.exe(2)
    深入探究VC —— 编译器cl.exe(1)
  • 原文地址:https://www.cnblogs.com/waimai/p/2836006.html
Copyright © 2011-2022 走看看