• mybatis3温故


    MyBatis可以利用SQL映射文件来配置,也可以利用Annotation来设置。MyBatis提供的一些基本注解如下表所示。

    注解

    目标

    相应的XML

    描述

    @CacheNamespace

    <cache>  

    为给定的命名空间(比如类)配置缓存。属性:

    implemetation,eviction,

    flushInterval , size 和 readWrite 。

    @CacheNamespaceRef

    <cacheRef>

    参照另外一个命名空间的缓存来使用。

    属性:value,也就是类的完全限定名。

    @ConstructorArgs

    方法

    <constructor>

    收集一组结果传递给对象构造方法。

    属性:value,是形式参数的数组

    @Arg

    方法

    <arg>

    <idArg>

    单独的构造方法参数,是ConstructorArgs  集合的一部分。属性:id,column,javaType,typeHandler。

    id属性是布尔值,来标识用于比较的属性,和<idArg>XML 元素相似

    @TypeDiscriminator

    方法

    <discriminator>

    一组实例值被用来决定结果映射的表

    现。属性:Column, javaType ,  jdbcType typeHandler,cases。

    cases属性就是实例的数组。

    @Case

    方法

    <case>

    单独实例的值和它对应的映射。属性:value  ,type ,results 。

    Results 属性是结果数组,因此这个注解和实际的ResultMap 很相似,由下面的  Results注解指定

    @Results

    方法

    <resultMap>

    结果映射的列表,包含了一个特别结果

    列如何被映射到属性或字段的详情。

    属性:value ,是Result注解的数组

    @Result

    方法

    <result>

    <id>

    在列和属性或字段之间的单独结果映

    射。属性:id ,column , property ,

    javaType ,jdbcType ,type Handler ,

    one,many。id 属性是一个布尔值,表

    示了应该被用于比较的属性。one 属性是单独的联系,和 <association> 相似,而many 属性是对集合而言的,和

    <collection>相似。

    @One

    方法

    <association>  

    复杂类型的单独属性值映射。属性:

    select,已映射语句(也就是映射器方

    法)的完全限定名,它可以加载合适类

    型的实例。注意:联合映射在注解 API

    中是不支持的。

    @Many

    方法

    <collection>

    复杂类型的集合属性映射。属性:

    select,是映射器方法的完全限定名,它可加载合适类型的一组实例。注意:联合映射在Java注解中是不支持的。

    @Options

    方法

    映射语句的属性

    这个注解提供访问交换和配置选项的宽广范围,它们通常在映射语句上作为属性出现。而不是将每条语句注解变复杂,Options 注解提供连贯清晰的方式来访问它们。属性:useCache=true,

    flushCache=false,

    resultSetType=FORWARD_ONLY,

    statementType=PREPARED,

    fetchSize= -1,timeout=-1 ,

    useGeneratedKeys=false ,

    keyProperty=”id“。

    理解Java 注解是很重要的,因为没有办法来指定“null ”作为值。因此,一旦你使用了Options注解,语句就受所有默认值的支配。要注意什么样的默认值来避免不期望的行为

    @Insert

    @Update

    @Delete

    方法

    <insert>

    <update>

    <delete>

    这些注解中的每一个代表了执行的真实 SQL。它们每一个都使用字符串数组(或单独的字符串)。如果传递的是字符串数组,它们由每个分隔它们的单独空间串联起来。属性:value,这是字符串数组用来组成单独的SQL语句

    @InsertProvider

    @UpdateProvider

    @DeleteProvider

    @SelectProvider

    方法

    <insert>

    <update>

    <delete>

    <select>

    允许创建动态

    SQL。

    这些可选的SQL注解允许你指定一个

    类名和一个方法在执行时来返回运行

    的SQL。基于执行的映射语句, MyBatis

    会实例化这个类,然后执行由 provider

    指定的方法. 这个方法可以选择性的接

    受参数对象作为它的唯一参数,但是必

    须只指定该参数或者没有参数。属性:

    type,method。type 属性是类的完全限定名。method  是该类中的那个方法名。

    @Param

    参数

    N/A

    当映射器方法需多个参数,这个注解可以被应用于映射器方法参数来给每个参数一个名字。否则,多参数将会以它们的顺序位置来被命名。比如

    #{1},#{2} 等,这是默认的。

    使用@Param(“person”),SQL中参数应该被命名为#{person}。

    这些注解都是运用到传统意义上映射器接口中的方法、类或者方法参数中的。

    今天主要介绍两种使用注解的方式。

    一种是直接在映射器接口中写SQL语句,一种是利用SqlBuilder来创建SQL再由映射器接口来调用

    准备前提:

    1,配置常规的MyBatis主配置文件,即各种数据源,别名等设置。在利用注解配置SQL的时候,一般不需要在主配置文件中配置Mapper,个别情况下需要配置。

    2,数据库表Blog:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    DROP TABLE IF EXISTS `blog`;
    CREATE TABLE `blog` (
      `id` int(10) NOT NULL auto_increment,
      `title` varchar(200) NOT NULL,
      `datevarchar(50) NOT NULL,
      `authername` varchar(15) NOT NULL,
      `content` varchar(500) NOT NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

     数据库表User:

    1
    2
    3
    4
    5
    6
    7
    8
    DROP TABLE IF EXISTS `user`;
    CREATE TABLE `user` (
      `id` int(11) NOT NULL auto_increment,
      `userName` varchar(50) default NULL,
      `userAge` int(11) default NULL,
      `userAddress` varchar(200) default NULL,
      PRIMARY KEY  (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    3,分别写User和Blog对应的JavaBean即setter和getter实体类。

    第一种 映射器接口中写SQL语句

    映射器接口注解

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    package com.whut.inter;
    import java.util.List;
    import org.apache.ibatis.annotations.Delete;
    import org.apache.ibatis.annotations.Insert;
    import org.apache.ibatis.annotations.Param;
    import org.apache.ibatis.annotations.Select;
    import org.apache.ibatis.annotations.Update;
    import com.whut.model.User;
    //最基本的注解CRUD
    public interface IUserDAO {
        @Select("select *from User")
        public List<User> retrieveAllUsers();
                                                                                                                                                                                                                                       
        //注意这里只有一个参数,则#{}中的标识符可以任意取
        @Select("select *from User where id=#{idss}")
        public User retrieveUserById(int id);
                                                                                                                                                                                                                                       
        @Select("select *from User where id=#{id} and userName like #{name}")
        public User retrieveUserByIdAndName(@Param("id")int id,@Param("name")String names);
                                                                                                                                                                                                                                       
        @Insert("INSERT INTO user(userName,userAge,userAddress) VALUES(#{userName},"
                "#{userAge},#{userAddress})")
        public void addNewUser(User user);
                                                                                                                                                                                                                                       
        @Delete("delete from user where id=#{id}")
        public void deleteUser(int id);
                                                                                                                                                                                                                                       
        @Update("update user set userName=#{userName},userAddress=#{userAddress}"
                " where id=#{id}")
        public void updateUser(User user);
    }

    测试代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    package com.whut.test;
    import java.io.IOException;
    import java.io.Reader;
    import java.util.List;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import com.whut.inter.IUserDAO;
    import com.whut.model.User;
    public class TestUser {
        private static SqlSessionFactory sqlSessionFactory;
        private static Reader reader;
        static {
            try {
                Reader reader = Resources.getResourceAsReader("mybatic-config.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
                // 由于使用了注解,所以在主配置文件没有mapper,需要在代码里显示注册该mapper接口
                sqlSessionFactory.getConfiguration().addMapper(IUserDAO.class);
            catch (IOException e) {
                e.printStackTrace();
            }
        }
        public static void main(String[] args) {
            // testSelectAll();
            // testSelectByConditions();
            //testAddUser();
            //testDeleteUser();
                                                                                                                                                                                                                    
            testUpateUser();
        }
        public static void testSelectAll() {
            // sqlSessionFactory.getConfiguration().addMapper(IUserDAO.class);
            SqlSession session = sqlSessionFactory.openSession();
            try {
                IUserDAO userDAO = session.getMapper(IUserDAO.class);
                List<User> users = userDAO.retrieveAllUsers();
                System.out.println("用户编号 " "姓名 " "年龄 住址");
                for (User u : users) {
                    System.out.println(u.getId() + " " + u.getUserName() + " "
                            + u.getUserAge() + " " + u.getUserAddress());
                }
            finally {
                session.close();
            }
        }
        public static void testSelectByConditions() {
            SqlSession session = sqlSessionFactory.openSession();
            try {
                IUserDAO userDAO = session.getMapper(IUserDAO.class);
                User u = userDAO.retrieveUserByIdAndName(4"%spring%");
                if (u != null) {
                    System.out.println("用户编号 " "姓名 " "年龄 住址");
                    System.out.println(u.getId() + " " + u.getUserName() + " "
                            + u.getUserAge() + " " + u.getUserAddress());
                }
            finally {
                session.close();
            }
        }
        public static void testAddUser() {
            User u = new User();
            u.setUserName("dongtian");
            u.setUserAge(51);
            u.setUserAddress("hubeisheng");
            SqlSession session = sqlSessionFactory.openSession();
            try {
                IUserDAO userDAO = session.getMapper(IUserDAO.class);
                userDAO.addNewUser(u);
                session.commit();
            finally {
                session.close();
            }
        }
        public static void testDeleteUser() {
            SqlSession session = sqlSessionFactory.openSession();
            try {
                IUserDAO userDAO = session.getMapper(IUserDAO.class);
                userDAO.deleteUser(7);
                session.commit();
            finally {
                session.close();
            }
        }
                                                                                                                                                                                                                
        public static void testUpateUser() {
            User u = new User();
            u.setId(4);
            u.setUserName("dongtian");
            u.setUserAge(51);
            u.setUserAddress("hubeisheng");
            SqlSession session = sqlSessionFactory.openSession();
            try {
                IUserDAO userDAO = session.getMapper(IUserDAO.class);
                userDAO.updateUser(u);
                session.commit();
            finally {
                session.close();
            }
        }
    }

    第二种 映射器接口调用SqlBuilder生成的SQL进行执行

    映射器接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    package com.whut.inter;
    import java.util.List;
    import org.apache.ibatis.annotations.CacheNamespace;
    import org.apache.ibatis.annotations.DeleteProvider;
    import org.apache.ibatis.annotations.InsertProvider;
    import org.apache.ibatis.annotations.Options;
    import org.apache.ibatis.annotations.Param;
    import org.apache.ibatis.annotations.Result;
    import org.apache.ibatis.annotations.ResultMap;
    import org.apache.ibatis.annotations.Results;
    import org.apache.ibatis.annotations.SelectProvider;
    import org.apache.ibatis.annotations.UpdateProvider;
    import org.apache.ibatis.type.JdbcType;
    import com.whut.model.Blog;
    import com.whut.sqlTool.BlogSqlProvider;
    @CacheNamespace(size=100)
    public interface IBlogDAO {
        @SelectProvider(type = BlogSqlProvider.class, method = "getSql")
        @Results(value ={
                @Result(id=true, property="id",column="id",javaType=Integer.class,jdbcType=JdbcType.INTEGER),
                @Result(property="title",column="title",javaType=String.class,jdbcType=JdbcType.VARCHAR),
                @Result(property="date",column="date",javaType=String.class,jdbcType=JdbcType.VARCHAR),
                @Result(property="authername",column="authername",javaType=String.class,jdbcType=JdbcType.VARCHAR),
                @Result(property="content",column="content",javaType=String.class,jdbcType=JdbcType.VARCHAR),
                })
        public Blog getBlog(@Param("id"int id);
                                                                                                                                                                                           
        @SelectProvider(type = BlogSqlProvider.class, method = "getAllSql")
        @Results(value ={
                @Result(id=true, property="id",column="id",javaType=Integer.class,jdbcType=JdbcType.INTEGER),
                @Result(property="title",column="title",javaType=String.class,jdbcType=JdbcType.VARCHAR),
                @Result(property="date",column="date",javaType=String.class,jdbcType=JdbcType.VARCHAR),
                @Result(property="authername",column="authername",javaType=String.class,jdbcType=JdbcType.VARCHAR),
                @Result(property="content",column="content",javaType=String.class,jdbcType=JdbcType.VARCHAR),
                })
        public List<Blog> getAllBlog();
                                                                                                                                                                                           
        @SelectProvider(type = BlogSqlProvider.class, method = "getSqlByTitle")
        @ResultMap(value = "sqlBlogsMap")
        //这里调用resultMap,这个是SQL配置文件中的,必须该SQL配置文件与本接口有相同的全限定名
        //注意文件中的namespace路径必须是使用@resultMap的类路径
        public List<Blog> getBlogByTitle(@Param("title")String title);
                                                                                                                                                                                           
        @InsertProvider(type = BlogSqlProvider.class, method = "insertSql")
        public void insertBlog(Blog blog);
                                                                                                                                                                                           
        @UpdateProvider(type = BlogSqlProvider.class, method = "updateSql")
        public void updateBlog(Blog blog);
                                                                                                                                                                                           
        @DeleteProvider(type = BlogSqlProvider.class, method = "deleteSql")
        @Options(useCache = true, flushCache = false, timeout = 10000)
        public void deleteBlog(int ids);
                                                                                                                                                                                           
    }

    SQL生成器(利用SqlBuilder生成)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    package com.whut.sqlTool;
    import java.util.Map;
    import static org.apache.ibatis.jdbc.SqlBuilder.*;
    public class BlogSqlProvider {
        private final static String TABLE_NAME = "blog";
        public String getSql(Map<Integer, Object> parameter) {
            BEGIN();
            //SELECT("id,title,authername,date,content");
            SELECT("*");
            FROM(TABLE_NAME);
            //注意这里这种传递参数方式,#{}与map中的key对应,而map中的key又是注解param设置的
            WHERE("id = #{id}");
            return SQL();
        }
        public String getAllSql() {
            BEGIN();
            SELECT("*");
            FROM(TABLE_NAME);
            return SQL();
        }
        public String getSqlByTitle(Map<String, Object> parameter) {
            String title = (String) parameter.get("title");
            BEGIN();
            SELECT("*");
            FROM(TABLE_NAME);
            if (title != null)
                WHERE(" title like #{title}");
            return SQL();
        }
        public String insertSql() {
            BEGIN();
            INSERT_INTO(TABLE_NAME);
            VALUES("title""#{title}");
            //  VALUES("title", "#{tt.title}");
            //这里是传递一个Blog对象的,如果是利用上面tt.方式,则必须利用Param来设置别名
            VALUES("date""#{date}");
            VALUES("authername""#{authername}");
            VALUES("content""#{content}");
            return SQL();
        }
        public String deleteSql() {
            BEGIN();
            DELETE_FROM(TABLE_NAME);
            WHERE("id = #{id}");
            return SQL();
        }
        public String updateSql() {
            BEGIN();
            UPDATE(TABLE_NAME);
            SET("content = #{content}");
            WHERE("id = #{id}");
            return SQL();
        }
    }

    注意由于在映射器接口中调用了@ResultMap,该注解内容是SQL配置文件ResultMap的ID,它是允许访问SQL配置文件中的ResultMap,则需要在相应的SQL配置相应ResultMap,然后再在主配置文件加上该SQL配置的Mapper路径。并且该SQL配置文件的namespace必须与使用@ResultMap的映射器接口的全限定相同。Blog.xml如下。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
    <mapper namespace="com.whut.inter.IBlogDAO">
       <resultMap type="Blog" id="sqlBlogsMap">
          <id property="id" column="id"/>
          <result property="title" column="title"/>
          <result property="authername" column="authername"/>
          <result property="date" column="date"/>
          <result property="content" column="content"/>
       </resultMap>
    </mapper>

    再在主配置文件mybatis-config.xml加入一句mapper。

    1
    2
    3
    <mappers>
            <mapper resource="com/whut/model/Blog.xml"/>
    </mappers>

    测试类

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    package com.whut.test;
    import java.io.IOException;
    import java.io.Reader;
    import java.util.List;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import com.whut.inter.IBlogDAO;
    import com.whut.model.Blog;
    /**
     * 注意这里是一种利用SqlBuilder以及多种设置来注解使用
     * @author zxl
     *
     */
    public class TestBlog {
        private static SqlSessionFactory sqlSessionFactory;
        private static Reader reader;
        static {
            try {
                Reader reader = Resources.getResourceAsReader("mybatic-config.xml");
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
                // 由于使用了注解,所以在主配置文件没有mapper,需要在代码里显示注册该mapper接口
                //sqlSessionFactory.getConfiguration().addMapper(IBlogDAO.class);
            catch (IOException e) {
                e.printStackTrace();
            }
        }
                                                                                                                               
        public static void main(String[] args) {
            //testOneBlog();
            //testAllBlog();
            //testBlogByTitle();
            //testAddBlog();
            //testDeleteBlog();
                                                                                                                                   
            testUpdateBlog();
        }
                                                                                                                               
        public static void testOneBlog()
        {
            SqlSession session=sqlSessionFactory.openSession();
            try{
                IBlogDAO dao=session.getMapper(IBlogDAO.class);
                Blog  blog=dao.getBlog(2);
                System.out.println(blog.getId()+" "+blog.getAuthername()+" "+blog.getTitle());
            }finally{
                session.close();
            }
                                                                                                                                   
        }
        public static void testAllBlog()
        {
            SqlSession session=sqlSessionFactory.openSession();
            try{
                IBlogDAO dao=session.getMapper(IBlogDAO.class);
                List<Blog>  blogs=dao.getAllBlog();
                System.out.println("编号 作者 标题");
                for(Blog blog:blogs)
                System.out.println(blog.getId()+" "+blog.getAuthername()+" "+blog.getTitle());
            }finally{
                session.close();
            }
        }
        public static void testBlogByTitle()
        {
            SqlSession session=sqlSessionFactory.openSession();
            try{
                IBlogDAO dao=session.getMapper(IBlogDAO.class);
                List<Blog>  blogs=dao.getBlogByTitle("%word%");
                System.out.println("编号 作者 标题");
                for(Blog blog:blogs)
                System.out.println(blog.getId()+" "+blog.getAuthername()+" "+blog.getTitle());
            }finally{
                session.close();
            }
        }
                                                                                                                               
        public static void testAddBlog()
        {
            SqlSession session=sqlSessionFactory.openSession();
            Blog blog=new Blog();
            blog.setTitle("chuntian");
            blog.setAuthername("xiaohua");
            blog.setDate("2013/12/25");
            blog.setContent("bushuangyayya");
            try{
                IBlogDAO dao=session.getMapper(IBlogDAO.class);
                dao.insertBlog(blog);
                session.commit();
            }finally{
                session.close();
            }
        }
                                                                                                                               
        public static void testDeleteBlog()
        {
            SqlSession session=sqlSessionFactory.openSession();
            try{
                IBlogDAO dao=session.getMapper(IBlogDAO.class);
                dao.deleteBlog(5);
                session.commit();
            }finally{
                session.close();
            }
        }
                                                                                                                               
        public static void testUpdateBlog()
        {
            SqlSession session=sqlSessionFactory.openSession();
            Blog blog=new Blog();
            blog.setId(6);
            blog.setTitle("daxuexiaoyuan");
            blog.setAuthername("xiaohua");
            blog.setDate("2013/2/25");
            blog.setContent("冷死了");
            try{
                IBlogDAO dao=session.getMapper(IBlogDAO.class);
                dao.updateBlog(blog);
                session.commit();
            }finally{
                session.close();
            }
        }
    }

    注意事项:

    1) 在利用注解配置映射器接口的时候,必须要通过

    sqlSessionFactory.getConfiguration().addMapper(IBlogDAO.class);来对给映射器接口注册,如果映射器接口中使用了@ResultMap注解,则由于已经在mybatis-config.xml配置了Mapper,则就不需要再次在代码中添加mapper。

    2)当方法有多个参数的时候,为了与SQL语句中的#{}对应,一般可以使用@Param("")来为每个参数命别名,使得该别名与#{}对应。当参数只有一个的时候,不需要别名。

    3 在进行更新删除添加的时候,如果传递的是一个实体对象,则SQL可以直接使用实体的属性。

    4)映射器接口调用SqlBuilder中的方法,都是将参数转换为Map中的key,可以在SqlBuilder的方法中利用Map来获取传递的参数值,进而进行逻辑操作判断。

    5)注解中对于返回多条记录的查询可以直接利用@Results和@Result来配置映射,或者利用@ResultMap来调用SQL配置文件中的ResultMap。

    --------------------------------------------------------------------------------------------------------------------

    (1)官方开发文档:http://ibatis.apache.org/docs/dotnet/datamapper/ch03s09.html

    <isGreaterThan prepend="AND" property="bo.lastUpdatedBy" compareValue="0">

    <![CDATA[(

    LAST_UPDATED_BY=#bo.lastUpdatedBy:NUMERIC#

    )]]>

    </isGreaterThan>

    在ibatis中,该属性用于判断传入的值是否大于0

    <isNotNull prepend="AND" property="bo.lastUpdateDate" >

    <![CDATA[(

    LAST_UPDATE_DATE=#bo.lastUpdateDate:TIMESTAMP#

    )]]>

    </isNotNull>

    在ibatis中,该属性用于判断传入的值是否为空

    IBATIS动态查询语句

    <!-- 在ibatis中使用安全的拼接语句,动态查询 ibatis比JDBC的优势之一,安全高效说明文字在注释中 --> <select id="selectA

    <!--

    在ibatis中使用安全的拼接语句,动态查询

    ibatis比JDBC的优势之一,安全高效

    说明文字在注释中

    -->

    <select id="selectAllProducts" parameterClass="Product" resultMap="ProductResult">

    select id,note from Product

    <dynamic prepend="WHERE">

    <!-- isNotNull判断参数是否存在,Integer类型 -->

    <isNotNull property="id">

    <!-- isGreaterThan判断参数是否大于compareValue,isGreaterEquals是大于等于 -->

    <isGreaterThan prepend=" and " property="id" compareValue="0">

    id = #id#

    </isGreaterThan>

    </isNotNull>

    <!-- isNotEmpty判断字串不为空,isEmpty可以判断字串为空 -->

    <isNotEmpty prepend=" and " property="note">

    <!-- 模糊查询不能用#,#在是用prepareStatement的?插入参数,$是文本替换 -->

    note like '%$note$%'

    </isNotEmpty>

    </dynamic>

    </select>

    用Map传参数

    <select id="selectAllProducts" parameterClass="java.util.HashMap" resultMap="ProductResult">

    select id,note from Product

    <dynamic prepend="WHERE">

    <!-- isPropertyAvailable判断属性是否有效 -->

    <isPropertyAvailable property="id">

    <isNotNull property="id">

    <!-- isLessThan判断参数是否小于compareValue,isLessEquals是小于等于 -->

    <isLessThan prepend=" and " property="id" compareValue="10">

    id = #id#

    </isLessThan>

    </isNotNull>

    </isPropertyAvailable>

    </dynamic>

    </select>

    <!--------------------------------------------------------------------几个常用属性-->

    <isPropertyAvailable> 属性是存在

    <isNotPropertyAvailable> 属性不存在

    <isNull> 属性值是null

    <isEmpty> 判断Collection.size<1或String.length()<1

    <isEqual> 等于

    <isNotEqual> 不等于

    <isGreaterThan> 大于

    <isGreaterEqual> 大于等于

    <isLessThan> 小于

    <isLessEqual> 小于等于


    ibatis中使用安全的拼接语句,动态查询,大于、小于、等于

    2012-11-26 17:38:13| 分类: 默认分类 |举报|字号 订阅
    在ibatis中使用安全的拼接语句,动态查询
    ibatis比JDBC的优势之一,安全高效
    说明文字在注释中

    <select id="selectAllProducts" parameterClass="Product" resultMap="ProductResult">
    select id,note from Product
    <dynamic prepend="WHERE">
    <!-- isNotNull判断参数是否存在,Integer类型 -->
    <isNotNull property="id">
    <!-- isGreaterThan判断参数是否大于compareValue,isGreaterEquals是大于等于 -->
    <isGreaterThan prepend=" and " property="id" compareValue="0">
    id = #id#
    </isGreaterThan>
    </isNotNull>
    <!-- isNotEmpty判断字串不为空,isEmpty可以判断字串为空 -->
    <isNotEmpty prepend=" and " property="note">
    <!-- 模糊查询不能用#,#在是用prepareStatement的?插入参数,$是文本替换 -->
    note like '%$note$%'
    </isNotEmpty>
    </dynamic>
    </select>

    用Map传参数

    <select id="selectAllProducts" parameterClass="java.util.HashMap" resultMap="ProductResult">
    select id,note from Product
    <dynamic prepend="WHERE">
    <!-- isPropertyAvailable判断属性是否有效 -->
    <isPropertyAvailable property="id">
    <isNotNull property="id">
    <!-- isLessThan判断参数是否小于compareValue,isLessEquals是小于等于 -->
    <isLessThan prepend=" and " property="id" compareValue="10">
    id = #id#
    </isLessThan>
    </isNotNull>
    </isPropertyAvailable>
    </dynamic>
    </select>
    /*动态SQL的参数有

    属性关键字
    含义

    <isEqual>
    如果参数相等于值则查询条件有效。

    <isNotEqual>
    如果参数不等于值则查询条件有效。

    <isGreaterThan>
    如果参数大于值则查询条件有效。

    <isGreaterEqual>
    如果参数等于值则查询条件有效。

    <isLessEqual>
    如果参数小于值则查询条件有效。如下所示:

    <isLessEqual prepend = ”AND” property = ”age” compareValue = ”18” >

    ADOLESCENT = ‘TRUE’

    </isLessEqual>

    <isPropertyAvailable>
    如果参数有使用则查询条件有效。

    <isNotPropertyAvailable>
    如果参数没有使用则查询条件有效。

    <isNull>
    如果参数为NULL则查询条件有效。

    <isNotNull>
    如果参数不为NULL则查询条件有效。

    <isEmpty>
    如果参数为空则查询条件有效。

    <isNotEmpty>
    如果参数不为空则查询条件有效。参数的数据类型为Collection、String 时参数不为NULL或“”。如下所示:

    <isNotEmpty prepend=”AND” property=”firstName” >

    FIRST_NAME=#firstName#

    </isNotEmpty>

    <isParameterPresent>
    如果参数类不为NULL则查询条件有效。

    <isNotParameterPresent>
    Checks to see if the parameter object is not present (null). Example Usage:

    <isNotParameterPresent prepend=”AND”>

    EMPLOYEE_TYPE = ‘DEFAULT’

    </isNotParameterPresent>


    在复杂查询过程中,我们常常需要根据用户的选择决定查询条件,这里发生变化的并不只是SQL 中的参数,包括Select 语句中所包括的字段和限定条件,都可能发生变化。典型情况,如在一个复杂的组合查询页面,我们必须根据用户的选择和输入决定查询的条件组合。

    一个典型的页面如下:

    对于这个组合查询页面,根据用户选择填写的内容,我们应为其生成不同的查询语句。如用户没有填写任何信息即提交查询请求,我们应该返回所有记录:
    Select * from t_user;
    如用户只在页面上填写了姓名“Erica”,我们应该生成类似:
    Select * from t_user where name like ‘%Erica%’ ;的SQL查询语句。
    如用户只在页面上填写了地址“Beijing”,我们应该生成类似:
    Select * from t_user where address like ‘%Beijing%”;的SQL。
    而如果用户同时填写了姓名和地址(”Erica”&’Beijing’),则我们应生成类似:
    Select * from t_user where name like ‘%Erica%’ and address like ‘%Beijing%”的SQL查询语句。

    对于ibatis 这样需要预先指定SQL 语句的ORM 实现而言,传统的做法无非通过if-else 语句对输入参数加以判定,然后针对用户选择调用不同的statement 定义。对于上面这种简单的情况(两种查询条件的排列组合,共4 种情况)而言,statement 的重复定义工作已经让人不厌其烦,而对于动辄拥有七八个查询条件,乃至十几个查询条件
    的排列组合而言,琐碎反复的statement定义实在让人不堪承受。

    考虑到这个问题,ibatis引入了动态映射机制,即在statement定义中,根据不同的
    查询参数,设定对应的SQL语句。
    还是以上面的示例为例:
    <select id="getUsers"
    parameterClass="user"
    resultMap="get-user-result">
    select
    id,
    name,
    sex
    from t_user
    <dynamic prepend="WHERE">
    <isNotEmpty prepend="AND" property="name">
    (name like #name#)
    </isNotEmpty>
    <isNotEmpty prepend="AND" property="address">
    (address like #address#)
    </isNotEmpty>
    </dynamic>
    </select>
    通过dynamic 节点,我们定义了一个动态的WHERE 子句。此WHERE 子句中将
    可能包含两个针对name 和address 字段的判断条件。而这两个字段是否加入检索取决于用户所提供的查询条件(字段是否为空[isNotEmpty])。
    对于一个典型的Web程序而言,我们通过HttpServletRequest获得表单中的字段名并将其设入查询参数,如:
    user.setName(request.getParameter("name"));
    user.setAddress(request.getParameter("address"));
    sqlMap.queryForList("User.getUsers", user);
    在执行queryForList("User.getUsers", user)时,ibatis 即根据配置文
    件中设定的SQL动态生成规则,创建相应的SQL语句。
    上面的示例中,我们通过判定节点isNotEmpty,指定了关于name 和address 属
    性的动态规则:
    <isNotEmpty prepend="AND" property="name">
    (name like #name#)
    </isNotEmpty>
    这个节点对应的语义是,如果参数类的"name"属性非空(isNotEmpty,即非空
    字符串””),则在生成的SQL Where字句中包括判定条件(name like #name#),其
    中#name#将以参数类的name属性值填充。
    Address属性的判定生成与name属性完全相同,这里就不再赘述。
    这样,我们通过在statement 定义中引入dynamic 节点,很简单的实现了SQL 判定子句的动态生成,对于复杂的组合查询而言,这将带来极大的便利。判定节点的定义可以非常灵活,我们甚至可以使用嵌套的判定节点来实现复杂的动态映射,如:
    <isNotEmpty prepend="AND" property="name">
    ( name=#name#
    <isNotEmpty prepend="AND" property="address">
    address=#address#
    </isNotEmpty>
    )
    </isNotEmpty>
    这段定义规定,只有用户提供了姓名信息时,才能结合地址数据进行查询(如果只提供地址数据,而将姓名信息忽略,将依然被视为全检索)。Dynamic节点和判定节点中的prepend属性,指明了本节点中定义的SQL子句在
    主体SQL中出现时的前缀。如:

    <dynamic prepend="WHERE">
    <isNotEmpty prepend="AND" property="name">
    (name like #name#)
    </isNotEmpty>
    <isNotEmpty prepend="AND" property="address">
    (address like #address#)
    </isNotEmpty>
    </dynamic>

    假设"name"属性的值为“Erica”, "address"属性的值为“Beijing”,则会生成类似下面的SQL子句(实际运行期将生成带占位符的PreparedStatement,之后再为其填充数据):

    WHERE (name like ‘Beijing’) AND (address like ‘Beijing’)

    其中WHERE 之后的语句是在dynamic 节点中所定义,因此以dynamic 节点的prepend设置("WHERE")作为前缀,而其中的”AND”,实际上是address属性所对应的isNotEmpty节点的prepend设定,它引领了对应节点中定义的SQL子句。至于name属性对应的isNotEmpty节点,由于ibatis会自动判定是否需要追加prepend前缀,这里(name like #name#)是WHERE 子句中的第一个条件子句,无需AND 前缀,所以自动省略。

    判定节点并非仅限于isNotEmpty,ibatis中提供了丰富的判定定义功能。判定节点分两类:

    ? 一元判定
    一元判定是针对属性值本身的判定,如属性是否为NULL,是否为空值等。
    上面示例中isNotEmpty就是典型的一元判定。

    一元判定节点有:

    节点名 描述
    <isPropertyAvailable> 参数类中是否提供了此属性
    <isNotPropertyAvailable> 与<isPropertyAvailable>相反
    <isNull> 属性值是否为NULL
    <isNotNull> 与<isNull>相反
    <isEmpty> 如果属性为Collection或者String,其size是否<1,如果非以上两种类型,则通过String.valueOf(属性值)
    获得其String类型的值后,判断其size是否<1<isNotEmpty> 与<isEmpty>相反。

    ? 二元判定
    二元判定有两个判定参数,一是属性名,而是判定值,如
    <isGreaterThan prepend="AND" property="age"
    compareValue="18">
    (age=#age#)
    </isGreaterThan>
    其中,property="age"指定了属性名”age”,compareValue=”18”指明了判定值为”18”。上面判定节点isGreaterThan 对应的语义是:如果age 属性大于18(compareValue),则在SQL中加入(age=#age#)条件。
    二元判定节点有:
    节点名 属性值与compareValues的关系
    <isEqual> 相等。
    <isNotEqual> 不等。
    <isGreaterThan> 大于
    <isGreaterEqual> 大于等于
    <isLessThan> 小于
    <isLessEqual> 小于等于


    为了防止SQL注入,iBatis模糊查询时也要避免使用$$来进行传值。下面是三个不同数据库的ibatis的模糊查询传值。
    mysql: select * from stu where name like concat('%',#name #,'%')

    oracle: select * from stu where name like '%'||#name #||'%'

    SQL Server:select * from stu where name like '%'+#name #+'%
    如:
    <!-- 用途:小二后台查询活动的数目 -->
    <!-- 频率:1000/天 -->
    <!-- 维护:刘飞 -->
    <select id="countActivitySearch" resultClass="java.lang.Long" parameterClass="actDO">
    <![CDATA[
    select count(id) from activity
    ]]>

    <dynamic prepend="WHERE">
    <isNotNull prepend=" AND " property="name">
    name LIKE CONCAT('%', #name#, '%')
    </isNotNull>
    <isNotNull prepend=" AND " property="itemId">
    itemId = #itemId#
    </isNotNull>
    <isNotNull prepend=" AND " property="itemName">
    itemName LIKE CONCAT('%', #itemName#, '%')
    </isNotNull>
    <isNotNull prepend=" AND " property="status">
    status = #status#
    </isNotNull>
    <isNotNull prepend=" AND " property="actStatus">
    actStatus = #actStatus#
    </isNotNull>
    <isNotNull prepend=" AND " property="domain">
    domain LIKE CONCAT('%', #domain#, '%')
    </isNotNull>
    </dynamic>

    </select>

    <!-- 用途:小二后台查询活动的列表 -->
    <!-- 频率:1000/天 -->
    <!-- 维护:刘飞 -->
    <select id="searchActivityForList" resultMap="actResult" parameterClass="actDO">
    <![CDATA[
    select * from activity
    ]]>

    <dynamic prepend="WHERE">
    <isNotNull prepend=" AND " property="name">
    name LIKE CONCAT('%', #name#, '%')
    </isNotNull>
    <isNotNull prepend=" AND " property="itemId">
    itemId = #itemId#
    </isNotNull>
    <isNotNull prepend=" AND " property="itemName">
    itemName LIKE CONCAT('%', #itemName#, '%')
    </isNotNull>
    <isNotNull prepend=" AND " property="status">
    status = #status#
    </isNotNull>
    <isNotNull prepend=" AND " property="actStatus">
    actStatus = #actStatus#
    </isNotNull>
    <isNotNull prepend=" AND " property="domain">
    domain LIKE CONCAT('%', #domain#, '%')
    </isNotNull>
    </dynamic>

    <![CDATA[
    order by starttime desc, createtime desc
    limit
    #startRow#, #perPageSize#
    ]]>
    </select>


    IBatis模糊查詢

    <!--
    在ibatis中使用安全的拼接语句,动态查询
    ibatis比JDBC的优势之一,安全高效
    说明文字在注释中
    -->


    <select id="selectAllProducts" parameterClass="Product" resultMap="ProductResult">
    select id,note from Product
    <dynamic prepend="WHERE">
    <!-- isNotNull判断参数是否存在,Integer类型 -->
    <isNotNull property="id">
    <!-- isGreaterThan判断参数是否大于compareValue,isGreaterEquals是大于等于 -->
    <isGreaterThan prepend=" and " property="id" compareValue="0">
    id = #id#
    </isGreaterThan>
    </isNotNull>
    <!-- isNotEmpty判断字串不为空,isEmpty可以判断字串为空 -->
    <isNotEmpty prepend=" and " property="note">
    <!-- 模糊查询不能用#,#在是用prepareStatement的?插入参数,$是文本替换 -->
    note like '%$note$%'
    </isNotEmpty>
    </dynamic>
    </select>

    用Map传参数

    <select id="selectAllProducts" parameterClass="java.util.HashMap" resultMap="ProductResult">
    select id,note from Product
    <dynamic prepend="WHERE">
    <!-- isPropertyAvailable判断属性是否有效 -->
    <isPropertyAvailable property="id">
    <isNotNull property="id">
    <!-- isLessThan判断参数是否小于compareValue,isLessEquals是小于等于 -->
    <isLessThan prepend=" and " property="id" compareValue="10">
    id = #id#
    </isLessThan>
    </isNotNull>
    </isPropertyAvailable>
    </dynamic>
    </select>
    <!--------------------------------------------------------------------几个常用属性-->

    <isPropertyAvailable> 属性是存在
    <isNotPropertyAvailable> 属性不存在
    <isNull> 属性值是null
    <isEmpty> 判断Collection.size<1或String.length()<1
    <isEqual> 等于
    <isNotEqual> 不等于
    <isGreaterThan> 大于
    <isGreaterEqual> 大于等于
    <isLessThan> 小于
    <isLessEqual>

    ---------------------

    Ibatis的动态查询使得数据操作变得非常的灵活,下次举出了常用的动态查询的属性信息: 
    Ibatis配置信息 

    Xml代码  收藏代码
    1. <!-- Dynamic Sql -->  
    2.   <typeAlias alias="Student" type="com.ibatis.Student" />  
    3.     <typeAlias alias="StudentDTO" type="com.ibatis.StudentDTO" />  
    4.     <select id="dynamicGetStudent" parameterClass="StudentDTO"  
    5.         resultClass="Student">  
    6.         select *  
    7.         from student  
    8.         <dynamic prepend="WHERE">  
    9.             <isNotEqual prepend="AND" property="sid" compareValue="0">  
    10.                 sid = #sid#  
    11.             </isNotEqual>  
    12.               
    13.             <isNotNull prepend="AND" property="sname">  
    14.                 sname = #sname#  
    15.             </isNotNull>  
    16.         </dynamic>  
    17.         <dynamic prepend="order by">  
    18.             <isParameterPresent>  
    19.                 <isEqual prepend="order by" property="sort" compareValue="1">  
    20.                     sname desc,socre  
    21.                 </isEqual>  
    22.                   
    23.                 <isEqual prepend="order by" property="sort" compareValue="2">  
    24.                     sname asc,socre  
    25.                 </isEqual>  
    26.             </isParameterPresent>  
    27.         </dynamic>  
    28.     </select>  


    Student的信息 

    Java代码  收藏代码
    1. package com.ibatis;  
    2.   
    3. import java.util.Date;  
    4.   
    5. public class Student {  
    6.     private int sid;  
    7.     private String sname;  
    8.     private String major;  
    9.     private Date birth;  
    10.     private int socre;  
    11.     public int getSid() {  
    12.         return sid;  
    13.     }  
    14.     public void setSid(int sid) {  
    15.         this.sid = sid;  
    16.     }  
    17.     public String getSname() {  
    18.         return sname;  
    19.     }  
    20.     public void setSname(String sname) {  
    21.         this.sname = sname;  
    22.     }  
    23.     public String getMajor() {  
    24.         return major;  
    25.     }  
    26.     public void setMajor(String major) {  
    27.         this.major = major;  
    28.     }  
    29.     public Date getBirth() {  
    30.         return birth;  
    31.     }  
    32.     public void setBirth(Date birth) {  
    33.         this.birth = birth;  
    34.     }  
    35.     public int getSocre() {  
    36.         return socre;  
    37.     }  
    38.     public void setSocre(int socre) {  
    39.         this.socre = socre;  
    40.     }  
    41.       
    42.     @Override  
    43.     public String toString() {  
    44.         String content = "Sid="+this.sid+" "+"Sname="+this.sname+" "+this.birth.toLocaleString();  
    45.         return content;  
    46.     }  
    47.       
    48. }  


    StudentDTO的信息 

    Java代码  收藏代码
    1. package com.ibatis;  
    2.   
    3. import java.util.Date;  
    4.   
    5. public class StudentDTO {  
    6.     private int sid;  
    7.     private String sname;  
    8.     private String major;  
    9.     private Date birth;  
    10.     private int socre;  
    11.     private int sort;  
    12.     public int getSort() {  
    13.         return sort;  
    14.     }  
    15.     public void setSort(int sort) {  
    16.         this.sort = sort;  
    17.     }  
    18.     public int getSid() {  
    19.         return sid;  
    20.     }  
    21.     public void setSid(int sid) {  
    22.         this.sid = sid;  
    23.     }  
    24.     public String getSname() {  
    25.         return sname;  
    26.     }  
    27.     public void setSname(String sname) {  
    28.         this.sname = sname;  
    29.     }  
    30.     public String getMajor() {  
    31.         return major;  
    32.     }  
    33.     public void setMajor(String major) {  
    34.         this.major = major;  
    35.     }  
    36.     public Date getBirth() {  
    37.         return birth;  
    38.     }  
    39.     public void setBirth(Date birth) {  
    40.         this.birth = birth;  
    41.     }  
    42.     public int getSocre() {  
    43.         return socre;  
    44.     }  
    45.     public void setSocre(int socre) {  
    46.         this.socre = socre;  
    47.     }  
    48.       
    49.     @Override  
    50.     public String toString() {  
    51.         String content = "Sid="+this.sid+" "+"Sname="+this.sname+" "+this.birth.toLocaleString();  
    52.         return content;  
    53.     }  
    54.       
    55. }  


    Java中的调用信息 

    Java代码  收藏代码
    1. @SuppressWarnings("unchecked")  
    2.     public static void main(String[] args) {  
    3.         List<Student> list = dao.dynamicGetStudent(studentDTO);  
    4.         for(Student student : list){  
    5.             System.out.println("name:"+student.getSname());  
    6.         }  
    7.         System.out.println("size:"+list.size());  
    8.     }  
    9. @Override  
    10.     public List dynamicGetStudent(StudentDTO studentDTO) {  
    11.         List result = null;  
    12.         try {  
    13.             result = sqlMapClient.queryForList("dynamicGetStudent",studentDTO);  
    14.         } catch (SQLException e) {  
    15.             // TODO Auto-generated catch block  
    16.             e.printStackTrace();  
    17.         }  
    18.         return result;  
    19.     }  


    动态查询中的常用属性: 

    属性关键字 含义
    <isEqual> 如果参数相等于值则查询条件有效
    <isNotEqual> 如果参数不等于值则查询条件有效
    <isGreaterThan> 如果参数大于值则查询条件有效
    <isGreaterEqual> 如果参数等于值则查询条件有效
    <isLessEqual> 如果参数小于值则查询条件有效。如下所示:<isLessEqual prepend = ”AND” property = ”age” compareValue = ”18” >ADOLESCENT = ‘TRUE’</isLessEqual>
    <isPropertyAvailable> 如果参数有使用则查询条件有效。
    <isNotPropertyAvailable> 如果参数没有使用则查询条件有效
    <isNull> 如果参数为NULL则查询条件有效
    <isNotNull> 如果参数不为NULL则查询条件有效
    <isEmpty> 如果参数为空则查询条件有效
    <isNotEmpty> 如果参数不为空则查询条件有效
    <isParameterPresent> 如果参数类不为NULL则查询条件有效
    <isNotParameterPresent> Checks to see if the parameter object is not present (null). Example Usage
  • 相关阅读:
    Castle实践1-Castle IOC容器剖析
    Castle实践-开篇
    界面逻辑和业务逻辑分离的重要性
    Castle实践4-Automatic Transaction Management Facility
    Castle实践2-Startable Facility
    世事无常....
    手动配置oracle客户端的方法
    Excel.Application 和 打印机 :)
    流水如斯...
    SourceControl
  • 原文地址:https://www.cnblogs.com/fx2008/p/4039653.html
Copyright © 2020-2023  润新知