个人博客
http://www.milovetingting.cn
简介 MyBatis
是一款优秀的持久层框架
,它支持自定义 SQL
、存储过程
以及高级映射
。MyBatis
免除了几乎所有的 JDBC
代码以及设置参数
和获取结果集
的工作。MyBatis
可以通过简单的 XML
或注解
来配置
和映射原始类型
、接口
和 Java POJO
(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
中文文档
https://mybatis.org/mybatis-3/zh/index.html
maven仓库 1 2 3 4 5 6 7 <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.11</version > </dependency >
环境搭建 安装MySQL 安装MySQL
,这里不再赘述,网上很多相关资料
安装SQLyog 参考链接 https://www.jb51.net/article/263345.htm
密钥:
名称:any
证书秘钥:dd987f34-f358-4894-bd0f-21f3f04be9c1
创建数据库 1 2 3 4 # 创建数据库 create database `mybatis`; # 使用数据库 use `mybatis`;
创建表 1 CREATE TABLE `user`(`id` INT(20) NOT NULL PRIMARY KEY,`name` VARCHAR(50) DEFAULT NULL,`pwd` VARCHAR(50) DEFAULT NULL)ENGINE=INNODB DEFAULT CHARSET=utf8;
插入数据 1 2 3 INSERT INTO `user`(`id`,`name`,`pwd`) VALUES (1,'张三','123456'); INSERT INTO `user`(`id`,`name`,`pwd`) VALUES (2,'李四','123456'); INSERT INTO `user`(`id`,`name`,`pwd`) VALUES (3,'王五','123456');
引入MyBatis 1、打开IDEA
,新建Maven
项目
2、导入依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <dependencies > <dependency > <groupId > mysql</groupId > <artifactId > mysql-connector-java</artifactId > <version > 8.0.30</version > </dependency > <dependency > <groupId > org.mybatis</groupId > <artifactId > mybatis</artifactId > <version > 3.5.11</version > </dependency > <dependency > <groupId > junit</groupId > <artifactId > junit</artifactId > <version > 4.13.2</version > <scope > test</scope > </dependency > </dependencies >
为了方便测试,这里也导入了junit
3、创建一个模块
4、在新建的模块的resources目录下创建mybatis
的配置文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd" > <configuration > <environments default ="development" > <environment id ="development" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="com.mysql.cj.jdbc.Driver" /> <property name ="url" value ="jdbc:mysql://localhost:3306/mybatis?useSSL=true& useUnicode=true& characterEncoding=UTF-8" /> <property name ="username" value ="root" /> <property name ="password" value ="root" /> </dataSource > </environment > </environments > <mappers > <mapper resource ="com/wangyz/mapper/UserMapper.xml" /> </mappers > </configuration >
5、编写MyBatisUtil
工具类
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 package com.wangyz.dao.util;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 java.io.IOException;import java.io.InputStream;public class MyBatisUtil { private static SqlSessionFactory sqlSessionFactory; static { try { String resource = "mybatis-config.xml" ; InputStream inputStream = Resources.getResourceAsStream(resource); sqlSessionFactory = new SqlSessionFactoryBuilder ().build(inputStream); } catch (IOException e) { e.printStackTrace(); } } public static SqlSession getSqlSession () { return sqlSessionFactory.openSession(); } }
6、编写实体类
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 package com.wangyz.pojo;public class User { private int id; private String name; private String pwd; public int getId () { return id; } public void setId (int id) { this .id = id; } public String getName () { return name; } public void setName (String name) { this .name = name; } public String getPwd () { return pwd; } public void setPwd (String pwd) { this .pwd = pwd; } @Override public String toString () { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + pwd + '\'' + '}' ; } }
7、创建UserMapper
1 2 3 4 5 6 7 8 9 10 11 12 13 package com.wangyz.mapper;import com.wangyz.pojo.User;import java.util.List;public interface UserMapper { int insert (User user) ; int delete (User user) ; int update (User user) ; List<User> getUserList () ; }
8、创建UserMapper.xml
1 2 3 4 5 6 7 8 9 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.wangyz.mapper.UserMapper" > <select id ="getUserList" resultType ="com.wangyz.pojo.User" > select * from User; </select > </mapper >
9、在根目录的POM
文件中配置build
信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <build > <resources > <resource > <directory > src/main/resources</directory > <includes > <include > **/*.properties</include > <include > **/*.xml</include > </includes > <filtering > true</filtering > </resource > <resource > <directory > src/main/java</directory > <includes > <include > **/*.properties</include > <include > **/*.xml</include > </includes > <filtering > true</filtering > </resource > </resources > </build >
10、测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import com.wangyz.mapper.UserMapper;import com.wangyz.util.MyBatisUtil;import org.apache.ibatis.session.SqlSession;import org.junit.Test;public class UserMapperTest { @Test public void test () { SqlSession sqlSession = null ; try { sqlSession = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); System.out.println(mapper.getUserList()); } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } } }
输出结果:
[User{id=1, name=’张三’, pwd=’123456’}, User{id=2, name=’李四’, pwd=’123456’}, User{id=3, name=’王五’, pwd=’123456’}]
CRUD 1、根据id查询用户
Mapper
1 2 3 public interface UserMapper { User getUserById (int id) ; }
xml
1 2 3 <select id ="getUserById" parameterType ="int" resultType ="com.wangyz.pojo.User" > select * from user where id=#{id} </select >
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test public void getUserById () { SqlSession sqlSession = null ; try { sqlSession = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); System.out.println(mapper.getUserById(1 )); } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } }
2、增加用户
Mapper
xml
1 2 3 <insert id ="insert" parameterType ="com.wangyz.pojo.User" > insert into mybatis.user(id,name,pwd) values(#{id},#{name},#{pwd}) </insert >
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Test public void insert () { SqlSession sqlSession = null ; try { sqlSession = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = new User (4 ,"haha" ,"123456" ); int result = mapper.insert(user); if (result>0 ){ sqlSession.commit(); } } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } }
3、修改用户
Mapper
xml
1 2 3 <update id ="update" parameterType ="com.wangyz.pojo.User" > update mybatis.user set name=#{name},pwd=#{pwd} where id = #{id} </update >
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 @Test public void update () { SqlSession sqlSession = null ; try { sqlSession = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); User user = new User (4 ,"hi" ,"000000" ); int result = mapper.update(user); if (result>0 ){ sqlSession.commit(); } } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } }
4、删除用户
Mapper
xml
1 2 3 <delete id ="delete" parameterType ="int" > delete from mybatis.user where id = #{id} </delete >
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 @Test public void delete () { SqlSession sqlSession = null ; try { sqlSession = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); int result = mapper.delete(4 ); if (result>0 ){ sqlSession.commit(); } } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } }
5、通过Map类型参数
Mapper
1 int insertByMap (Map<String,Object> map) ;
xml
1 2 3 <insert id ="insertByMap" parameterType ="map" > insert into mybatis.user(id,name,pwd) values(#{userId},#{userName},#{userPwd}) </insert >
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @Test public void insertByMap () { SqlSession sqlSession = null ; try { sqlSession = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); Map<String,Object> map = new HashMap <>(); map.put("userId" ,4 ); map.put("userName" ,"hello" ); map.put("userPwd" ,"123456" ); int result = mapper.insertByMap(map); if (result>0 ){ sqlSession.commit(); } } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } }
6、模糊查询
Mapper
1 List<User> getUserListByLike (String kw) ;
xml
1 2 3 <select id ="getUserListByLike" resultType ="com.wangyz.pojo.User" > select * from mybatis.user where name like "%"#{value}"%" </select >
测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Test public void getUserListByLike () { SqlSession sqlSession = null ; try { sqlSession = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); System.out.println(mapper.getUserListByLike("王" )); } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } }
配置解析 环境配置 1 2 3 4 5 6 7 8 9 10 <environments default ="development" > <environment id ="development" > ... </environment > </environments > <environments default ="development" > <environment id ="test" > ... </environment > </environments >
可以通过default选项来设置环境
属性 1、编写配置文件 db.properties
1 2 3 4 driver =com.mysql.cj.jdbc.Driver url =jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8 username =root password =root
2、引入配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <properties resource ="db.properties" /> <environments default ="development" > <environment id ="development" > <transactionManager type ="JDBC" /> <dataSource type ="POOLED" > <property name ="driver" value ="${driver}" /> <property name ="url" value ="${url}" /> <property name ="username" value ="${username}" /> <property name ="password" value ="${password}" /> </dataSource > </environment > </environments >
3、如果外部配置文件和mybatis.config存在同一字段,优先使用外部配置
1 2 3 4 <properties resource ="db.properties" > <property name ="username" value ="root" /> <property name ="password" value ="123" /> </properties >
上面的配置中,会优先使用db.properties中的username
和password
类型别名 指定单个类的别名 1、在mybatis-config.xml中配置
1 2 3 <typeAliases > <typeAlias type ="com.wangyz.pojo.User" alias ="User" /> </typeAliases >
2、修改UserMapper.xml
1 2 3 <select id ="getUserList" resultType ="User" > select * from User; </select >
使用包名 1、在mybatis-config.xml中配置
1 2 3 <typeAliases > <package name ="com.wangyz.pojo" /> </typeAliases >
2、修改UserMapper.xml,默认别名为这个类的类名
1 2 3 <select id ="getUserList" resultType ="User" > select * from User; </select >
使用建议 当类比较少时,可以用第一种,如果类较多,可以指定包名。也可以在类上加注解
1 2 3 @Alias("user") public class User {}
Mapper 方式一【推荐】
1 2 3 4 <mappers > <mapper resource ="com/wangyz/mapper/UserMapper.xml" /> </mappers >
方式二
1 2 3 4 <mappers > <mapper class ="com.wangyz.mapper.UserMapper" /> </mappers >
接口和Mapper必须同名,而且需要在同一个包下
方式三
1 2 3 <mappers > <package name ="com.wangyz.mapper" /> </mappers >
接口和Mapper必须同名,而且需要在同一个包下
ResultMap映射 1、修改字段pwd
为password
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 package com.wangyz.pojo;public class User { private int id; private String name; private String password; public User () { } public User (int id, String name, String pwd) { this .id = id; this .name = name; this .password = pwd; } @Override public String toString () { return "User{" + "id=" + id + ", name='" + name + '\'' + ", pwd='" + password + '\'' + '}' ; } }
2、修改mapper.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.wangyz.mapper.UserMapper" > <resultMap id ="UserMap" type ="User" > <result column ="id" property ="id" /> <result column ="name" property ="name" /> <result column ="pwd" property ="password" /> </resultMap > <select id ="getUserList" resultMap ="UserMap" > select * from User; </select > </mapper >
日志 标准日志 1 2 3 <settings > <setting name ="logImpl" value ="STDOUT_LOGGING" /> </settings >
Log4J 1、引入Log4J
1 2 3 4 5 6 <dependency > <groupId > log4j</groupId > <artifactId > log4j</artifactId > <version > 1.2.17</version > </dependency >
2、在Resource目录下新建log4j.properties
1 2 3 4 log4j.rootLogger=DEBUG,stdout log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n
分页 Limit分页 1、接口
1 List<User> getUserListByLimit (Map<String,Integer> map) ;
2、Mapper.xml
1 2 3 <select id ="getUserListByLimit" parameterType ="map" resultMap ="UserMap" > select * from user limit #{startIndex},#{endIndex} </select >
3、测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 @Test public void getUserListByLimit () { SqlSession sqlSession = null ; try { sqlSession = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); Map<String, Integer> map = new HashMap <>(); map.put("startIndex" , 0 ); map.put("endIndex" , 2 ); System.out.println(mapper.getUserListByLimit(map)); } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } }
分页插件 https://pagehelper.github.io/
@Insert("insert into user(id,name,pwd) values (#{id},#{name},#{pwd})")
int addUser(User user);
@Update("update user set name=#{name},pwd=#{pwd} where id=#{id}")
int updateUser(User user);
@Delete("delete from user where id=#{id}")
int deleteUser(@Param("id") int id);
}
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 2、配置mapper ```xml <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="db.properties"/> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${driver}"/> <property name="url" value="${url}"/> <property name="username" value="${username}"/> <property name="password" value="${password}"/> </dataSource> </environment> </environments> <mappers> <mapper class="com.wangyz.mapper.UserMapper"/> </mappers> </configuration>
3、测试
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 import com.wangyz.mapper.UserMapper;import com.wangyz.pojo.User;import com.wangyz.util.MyBatisUtil;import org.apache.ibatis.session.SqlSession;import org.junit.Test;public class UserMapperTest { @Test public void getUserList () { SqlSession sqlSession = null ; try { sqlSession = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); System.out.println(mapper.getUserList()); } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } } @Test public void getUserListById () { SqlSession sqlSession = null ; try { sqlSession = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); System.out.println(mapper.getUserById(1 )); } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } } @Test public void addUser () { SqlSession sqlSession = null ; try { sqlSession = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.addUser(new User (5 ,"hi" ,"123456" )); } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } } @Test public void updateUser () { SqlSession sqlSession = null ; try { sqlSession = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.updateUser(new User (5 ,"hey" ,"12345678" )); } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } } @Test public void deleteUser () { SqlSession sqlSession = null ; try { sqlSession = MyBatisUtil.getSqlSession(); UserMapper mapper = sqlSession.getMapper(UserMapper.class); mapper.deleteUser(5 ); } catch (Exception e) { e.printStackTrace(); } finally { if (sqlSession != null ) { sqlSession.close(); } } } }
Lombok 1、安装Lombok
插件
在IDEA
的插件中搜索Lombok
,然后点击安装
2、引入依赖
1 2 3 4 5 6 7 <dependency > <groupId > org.projectlombok</groupId > <artifactId > lombok</artifactId > <version > 1.18.24</version > <scope > provided</scope > </dependency >
3、使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 package com.wangyz.pojo;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String name; private String pwd; }
查询嵌套 多对一 1、pojo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 package com.wangyz.mapper;import com.wangyz.pojo.Student;import java.util.List;public interface StudentMapper { List<Student> getStudentList () ; } package com.wangyz.mapper;import org.apache.ibatis.annotations.Param;import org.apache.ibatis.annotations.Select;import com.wangyz.pojo.Teacher;public interface TeacherMapper { @Select("select * from teacher where id = #{id}") Teacher getTeacher (@Param("id") int id) ; List<Student> getStudentList2 () ; }
2、mapper
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 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.wangyz.mapper.StudentMapper" > <select id ="getStudentList" resultMap ="StudentTeacher" > select * from student </select > <resultMap id ="StudentTeacher" type ="Student" > <result property ="id" column ="id" /> <result property ="name" column ="name" /> <association property ="teacher" column ="tid" javaType ="Teacher" select ="getTeacher" /> </resultMap > <select id ="getTeacher" resultType ="Teacher" > select * from teacher where id=#{id} </select > <select id ="getStudentList2" resultMap ="StudentTeacher2" > select s.id sid,s.name sname,t.id tid,t.name tname from student as s,teacher as t where s.tid=t.id </select > <resultMap id ="StudentTeacher2" type ="Student" > <result property ="id" column ="sid" /> <result property ="name" column ="sname" /> <association property ="teacher" javaType ="Teacher" > <result property ="id" column ="tid" /> <result property ="name" column ="tname" /> </association > </resultMap > </mapper > <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.wangyz.mapper.TeacherMapper" > </mapper >
一对多 1、pojo
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 package com.wangyz.pojo;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data @AllArgsConstructor @NoArgsConstructor public class Student { private int id; private String name; private int tid; } package com.wangyz.pojo;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;import java.util.List;@Data @AllArgsConstructor @NoArgsConstructor public class Teacher { private int id; private String name; private List<Student> students; }
2、mapper
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd" > <mapper namespace ="com.wangyz.mapper.TeacherMapper" > <select id ="getTeacherList" resultType ="Teacher" > select * from teacher </select > <select id ="getTeacherList2" resultMap ="TeacherStudent" > select s.id sid,s.name sname,t.name tname,t.id tid from student s,teacher t where s.tid=t.id </select > <resultMap id ="TeacherStudent" type ="Teacher" > <result property ="id" column ="tid" /> <result property ="name" column ="tname" /> <collection property ="students" ofType ="Student" > <result property ="id" column ="sid" /> <result property ="name" column ="sname" /> <result property ="tid" column ="tid" /> </collection > </resultMap > </mapper >
动态SQL https://mybatis.org/mybatis-3/zh/dynamic-sql.html