MyBatis详解 一篇就够啦

第1章MyBatis框架配置文件详解

1.1 typeHandlers类型转换器

  每当MyBatis 设置参数到PreparedStatement 或者从ResultSet 结果集中取得值时,就会使用TypeHandler 来处理数据库类型与java 类型之间转换。下表描述了默认

TypeHandlers

1.1.1 自定义类型转换器

假设表中字段是int类型,而实体类与之对应的属性是boolean类型,此时可以采用自定义类型转换器进行对应

(1)实体类

 1 package com.chenyanbin.beans;
 2
 3 public class Dept {
 4     private Integer deptNo;
 5     private String dname;
 6     private String loc;
 7     private boolean flag;
 8     public Integer getDeptNo() {
 9         return deptNo;
10     }
11     public boolean isFlag() {
12         return flag;
13     }
14     public void setFlag(boolean flag) {
15         this.flag = flag;
16     }
17     public void setDeptNo(Integer deptNo) {
18         this.deptNo = deptNo;
19     }
20     public String getDname() {
21         return dname;
22     }
23     public void setDname(String dname) {
24         this.dname = dname;
25     }
26     public String getLoc() {
27         return loc;
28     }
29     public void setLoc(String loc) {
30         this.loc = loc;
31     }
32 }

(2) 表中字段

(3) 开发自定义类型转换器:MyTypeHandler.java

继承并实现接口:TypeHandler.java

 1 package com.chenyanbin.util;
 2
 3 import java.sql.CallableStatement;
 4 import java.sql.PreparedStatement;
 5 import java.sql.ResultSet;
 6 import java.sql.SQLException;
 7
 8 import org.apache.ibatis.jdbc.Null;
 9 import org.apache.ibatis.type.JdbcType;
10 import org.apache.ibatis.type.TypeHandler;
11 /*
12  * setParameter:这个方法在生成SQL语句时才被调用
13  *
14  * getResult:查询结束之后,在将ResultSet数据行转换为实体类对象时,通知TypeHandler将当前数据行某个字段转换为何种类型
15  *
16  *
17  */
18 public class MyTypeHandler implements TypeHandler {
19
20     public void setParameter(PreparedStatement ps, int i, Object parameter, JdbcType jdbcType) throws SQLException {
21         if (parameter==null) { //dept.flag=null insertsql flag设置0
22             ps.setInt(i, 0);
23             return;
24         }
25         Boolean flag=(Boolean)parameter;
26         if (flag==true) {
27             ps.setInt(i, 1);
28         }
29         else {
30             ps.setInt(i, 0);
31         }
32     }
33
34     public Object getResult(ResultSet rs, String columnName) throws SQLException {
35         int flag = rs.getInt(columnName); //1 or 0
36         Boolean myFlag=Boolean.FALSE;
37         if (flag==1) {
38             myFlag=Boolean.TRUE;
39         }
40         return myFlag;
41     }
42
43     public Object getResult(ResultSet rs, int columnIndex) throws SQLException {
44         // TODO Auto-generated method stub
45         return null;
46     }
47
48     public Object getResult(CallableStatement cs, int columnIndex) throws SQLException {
49         // TODO Auto-generated method stub
50         return null;
51     }
52
53 }

(4) 在MyBatis核心配置文件注册自定义类型转换器:

myBatis-config.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE configuration
 3   PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4   "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <configuration>
 6     <!-- 属性配置 -->
 7     <properties resource="config.properties"></properties>
 8     <!-- 别名配置 -->
 9     <typeAliases>
10         <package name="com.chenyanbin.beans" />
11         <package name="com.chenyanbin.dao" />
12     </typeAliases>
13     <!-- 类型处理器 -->
14     <typeHandlers>
15         <!-- 从java中的Boolean转jdbc中的NUMERIC -->
16         <typeHandler handler="com.chenyanbin.util.MyTypeHandler"
17             javaType="Boolean" jdbcType="NUMERIC" />
18     </typeHandlers>
19     <!-- 环境配置 -->
20     <environments default="development">
21         <!-- 环境配置 -->
22         <environment id="development">
23             <!-- 事务管理器 -->
24             <transactionManager type="JDBC"></transactionManager>
25             <!-- 数据源 -->
26             <dataSource type="pooled">
27                 <property name="driver" value="${jdbc.driver}" />
28                 <property name="url" value="${jdbc.url}" />
29                 <property name="username" value="${jdbc.username}" />
30                 <property name="password" value="${jdbc.password}" />
31             </dataSource>
32         </environment>
33     </environments>
34     <!-- 映射器 -->
35     <mappers>
36         <package name="com.chenyanbin.dao" />
37     </mappers>
38 </configuration>

config.properties

1 jdbc.driver=com.mysql.jdbc.Driver
2 jdbc.url=jdbc:mysql://localhost:3306/sam
3 jdbc.username=root
4 jdbc.password=root

(5) 创建接口:DeptMapper.java

 1 package com.chenyanbin.dao;
 2
 3 import java.util.List;
 4 import com.chenyanbin.beans.Dept;
 5
 6 public interface DeptMapper {
 7     public void deptSave(Dept dept);
 8
 9     public List<Dept> deptFind();
10 }

(6)  DeptMapper.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE mapper
 3   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 4   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 <mapper namespace="com.chenyanbin.dao.DeptMapper">
 6     <insert id="deptSave">
 7         insert into dept (DEPTNO,DNAME,LOC,flag)
 8         values(#{deptNo},#{dname},#{loc},#{flag})
 9     </insert>
10     <select id="deptFind" resultType="Dept">
11         select deptNo,dname,loc,flag from dept
12     </select>
13 </mapper>

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE configuration
 3   PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4   "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <configuration>
 6     <!-- 属性配置 -->
 7     <properties resource="config.properties"></properties>
 8     <!-- 别名配置 -->
 9     <typeAliases>
10         <package name="com.chenyanbin.beans" />
11         <package name="com.chenyanbin.dao" />
12     </typeAliases>
13     <!-- 环境配置 -->
14     <environments default="development">
15         <!-- 环境配置 -->
16         <environment id="development">
17             <!-- 事务管理器 -->
18             <transactionManager type="JDBC"></transactionManager>
19             <!-- 数据源 -->
20             <dataSource type="pooled">
21                 <property name="driver" value="${jdbc.driver}" />
22                 <property name="url" value="${jdbc.url}" />
23                 <property name="username" value="${jdbc.username}" />
24                 <property name="password" value="${jdbc.password}" />
25             </dataSource>
26         </environment>
27     </environments>
28     <!-- 映射器 -->
29     <mappers>
30         <package name="com.chenyanbin.dao" />
31     </mappers>
32 </configuration>

方式二:myBatis-config.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE mapper
 3   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 4   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 <mapper namespace="com.chenyanbin.dao.DeptMapper">
 6     <insert id="deptSave">
 7         insert into dept (DEPTNO,DNAME,LOC,flag)
 8         values(#{deptNo},#{dname},#{loc},#{flag})
 9     </insert>
10     <resultMap type="dept" id="deptMap">
11     <result column="flag" property="flag" typeHandler="com.chenyanbin.util.MyTypeHandler"/>
12     </resultMap>
13     <select id="deptFind" resultType="Dept">
14         select deptNo,dname,loc,flag from dept
15     </select>
16 </mapper>

方式二:DeptMapper.xml

(7) 执行单元测试:TestMain_01.java

 1 package com.chenyanbin.test;
 2
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.util.List;
 6 import org.apache.ibatis.io.Resources;
 7 import org.apache.ibatis.session.SqlSession;
 8 import org.apache.ibatis.session.SqlSessionFactory;
 9 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
10 import org.junit.After;
11 import org.junit.Before;
12 import org.junit.Test;
13 import com.chenyanbin.beans.Dept;
14 import com.chenyanbin.dao.DeptMapper;
15
16 public class TestMain_01 {
17     private SqlSession session;
18
19     @Before
20     public void Start() {
21         try {
22             InputStream inputStream = Resources.getResourceAsStream("myBatis-config.xml");
23             SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
24             session = factory.openSession();
25         } catch (Exception e) {
26             e.printStackTrace();
27         }
28     }
29
30     @After
31     public void end() {
32         if (session == null) {
33             session.close();
34         }
35     }
36
37     @Test
38     public void test01() throws IOException {
39         Dept d2 = new Dept();
40         d2.setDname("上海事业部");
41         d2.setLoc("上海");
42         d2.setFlag(false);
43         session.insert("deptSave", d2);
44         session.commit();
45         session.close();
46     }
47
48     @Test
49     public void test02() {
50           DeptMapper dao=session.getMapper(DeptMapper.class);
51           List<Dept> deptList=dao.deptFind();
52           System.out.println("ok");
53     }
54
55 }

(8) 项目目录结构

1.2 objectFactory 对象工厂

  MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。 默认的对象工厂需要做的仅仅是实例化目标类,要么通过默认构造方法,要么在参数映射存在的时候通过参数构造方法来实例化。 如果想覆盖对象工厂的默认行为,则可以通过创建自己的对象工厂来实现。

1.2.1 自定义对象工厂

表结构:dept

实体类:Dept.java

 1 package com.chenyanbin.beans;
 2
 3 public class Dept {
 4     private Integer deptNo;
 5     private String dname;
 6     private String loc;
 7     private Boolean flag;
 8     private String country;
 9     public String getCountry() {
10         return country;
11     }
12     public void setCountry(String country) {
13         this.country = country;
14     }
15     public Integer getDeptNo() {
16         return deptNo;
17     }
18     public Boolean getFlag() {
19         return flag;
20     }
21     public void setFlag(Boolean flag) {
22         this.flag = flag;
23     }
24     public void setDeptNo(Integer deptNo) {
25         this.deptNo = deptNo;
26     }
27     public String getDname() {
28         return dname;
29     }
30     public void setDname(String dname) {
31         this.dname = dname;
32     }
33     public String getLoc() {
34         return loc;
35     }
36     public void setLoc(String loc) {
37         this.loc = loc;
38     }
39 }

(1) 继承与DefaultObjectFactory:MyObjectFactory.java

 1 package com.chenyanbin.util;
 2
 3 import org.apache.ibatis.reflection.factory.DefaultObjectFactory;
 4
 5 import com.chenyanbin.beans.Dept;
 6
 7 public class MyObjectFactory extends DefaultObjectFactory {
 8
 9     @Override
10     public Object create(Class type) {// 重新定义Dept类实例对象创建规则,其他类实例对象创建规则不想改变
11         if (Dept.class == type) {
12             // 依靠父类提供create方法创建Dept对象
13             Dept dept = (Dept) super.create(type);
14             // 设置自定义规则
15             dept.setCountry("China");
16             return dept;
17         }
18         return super.create(type);
19     }
20
21 }

(2) 在MyBatis核心文件中注册自定义工厂

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE configuration
 3   PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4   "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <configuration>
 6     <!-- 属性配置 -->
 7     <properties resource="config.properties"></properties>
 8     <!-- 别名配置 -->
 9     <typeAliases>
10         <package name="com.chenyanbin.beans" />
11         <package name="com.chenyanbin.dao" />
12     </typeAliases>
13     <!-- ObjectFactory对象工厂 -->
14     <objectFactory type="com.chenyanbin.util.MyObjectFactory"></objectFactory>
15     <!-- 类型处理器 -->
16 <!--     <typeHandlers>
17         从java中的Boolean转jdbc中的NUMERIC
18         <typeHandler handler="com.chenyanbin.util.MyTypeHandler"
19             javaType="Boolean" jdbcType="NUMERIC" />
20     </typeHandlers> -->
21     <!-- 环境配置 -->
22     <environments default="development">
23         <!-- 环境配置 -->
24         <environment id="development">
25             <!-- 事务管理器 -->
26             <transactionManager type="JDBC"></transactionManager>
27             <!-- 数据源 -->
28             <dataSource type="pooled">
29                 <property name="driver" value="${jdbc.driver}" />
30                 <property name="url" value="${jdbc.url}" />
31                 <property name="username" value="${jdbc.username}" />
32                 <property name="password" value="${jdbc.password}" />
33             </dataSource>
34         </environment>
35     </environments>
36     <!-- 映射器 -->
37     <mappers>
38         <package name="com.chenyanbin.dao" />
39     </mappers>
40 </configuration>

1.3 Plugins 拦截器

  拦截器的一个作用就是我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法。Mybatis拦截器设计的一个初衷就是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑。打个比方,对于Executor,Mybatis中有几种实现:BatchExecutor、ReuseExecutor、SimpleExecutor和CachingExecutor。这个时候如果你觉得这几种实现对于Executor接口的query方法都不能满足你的要求,那怎么办呢?是要去改源码吗?当然不。我们可以建立一个Mybatis拦截器用于拦截Executor接口的query方法,在拦截之后实现自己的query方法逻辑,之后可以选择是否继续执行原来的query方法。

  对于拦截器Mybatis为我们提供了一个Interceptor接口,通过实现该接口就可以定义我们自己的拦截器。我们先来看一下这个接口的定义:

  我们可以看到在该接口中一共定义有三个方法,intercept、plugin和setProperties。plugin方法是拦截器用于封装目标对象的,通过该方法我们可以返回目标对象本身,也可以返回一个它的代理。当返回的是代理的时候我们可以对其中的方法进行拦截来调用intercept方法,当然也可以调用其他方法,这点将在后文讲解。setProperties方法是用于在Mybatis配置文件中指定一些属性的。

定义自己的Interceptor最重要的是要实现plugin方法和intercept方法,在plugin方法中我们可以决定是否要进行拦截进而决定要返回一个什么样的目标对象。而intercept方法就是要进行拦截的时候要执行的方法。

对于plugin方法而言,其实Mybatis已经为我们提供了一个实现。Mybatis中有一个叫做Plugin的类,里面有一个静态方法wrap(Object target,Interceptor interceptor),通过该方法可以决定要返回的对象是目标对象还是对应的代理。

对于实现自己的Interceptor而言有两个很重要的注解,一个是@Intercepts,其值是一个@Signature数组。@Intercepts用于表明当前的对象是一个Interceptor,而@Signature则表明要拦截的接口、方法以及对应的参数类型。

创建自己的拦截器:MySimpleInterceptor.java

 1 package com.chenyanbin.util;
 2
 3 import java.util.Properties;
 4
 5 import org.apache.ibatis.executor.Executor;
 6 import org.apache.ibatis.mapping.MappedStatement;
 7 import org.apache.ibatis.plugin.Interceptor;
 8 import org.apache.ibatis.plugin.Intercepts;
 9 import org.apache.ibatis.plugin.Invocation;
10 import org.apache.ibatis.plugin.Plugin;
11 import org.apache.ibatis.plugin.Signature;
12 import org.apache.ibatis.session.ResultHandler;
13 import org.apache.ibatis.session.RowBounds;
14
15 @Intercepts({ @Signature(method = "query", type = Executor.class, args = { MappedStatement.class, Object.class,
16         RowBounds.class, ResultHandler.class }) })
17 public class MySimpleInterceptor implements Interceptor {
18     /*
19      * 参数:Invocation {代理对象,被监控的方法对象,当前被监控方法运行时需要实参}
20      */
21     public Object intercept(Invocation invocation) throws Throwable {
22         // TODO Auto-generated method stub
23         System.out.println("被拦截方法执行之前,做的辅助服务。。。。。");
24         Object object = invocation.proceed(); // 执行被拦截方法
25         System.out.println("被拦截方法执行之后,做的辅助服务。。。。。");
26         return object;
27     }
28
29     /*
30      * 参数:target 表示被拦截的对象,应该是Executor接口实例对象 作用: 如果 被拦截的对象所在的类是有实现接口就为当前拦截对象生成一个代理对象
31      * 如果被拦截的对象所在的类没有指定接口,这个对象之后的行为不会被代理操作
32      */
33     public Object plugin(Object target) {
34         // TODO Auto-generated method stub
35         return Plugin.wrap(target, this);
36     }
37
38     public void setProperties(Properties properties) {
39         // TODO Auto-generated method stub
40
41     }
42
43 }

MyBatis核心配置文件:myBatis-config.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE configuration
 3   PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
 4   "http://mybatis.org/dtd/mybatis-3-config.dtd">
 5 <configuration>
 6     <!-- 属性配置 -->
 7     <properties resource="config.properties"></properties>
 8     <!-- 别名配置 -->
 9     <typeAliases>
10         <package name="com.chenyanbin.beans" />
11         <package name="com.chenyanbin.dao" />
12     </typeAliases>
13     <!-- ObjectFactory对象工厂 -->
14     <objectFactory type="com.chenyanbin.util.MyObjectFactory"></objectFactory>
15     <!-- Plugins拦截器 -->
16     <plugins>
17         <plugin interceptor="com.chenyanbin.util.MySimpleInterceptor"></plugin>
18     </plugins>
19     <!-- 类型处理器 -->
20     <!-- <typeHandlers> 从java中的Boolean转jdbc中的NUMERIC <typeHandler handler="com.chenyanbin.util.MyTypeHandler"
21         javaType="Boolean" jdbcType="NUMERIC" /> </typeHandlers> -->
22     <!-- 环境配置 -->
23     <environments default="development">
24         <!-- 环境配置 -->
25         <environment id="development">
26             <!-- 事务管理器 -->
27             <transactionManager type="JDBC"></transactionManager>
28             <!-- 数据源 -->
29             <dataSource type="pooled">
30                 <property name="driver" value="${jdbc.driver}" />
31                 <property name="url" value="${jdbc.url}" />
32                 <property name="username" value="${jdbc.username}" />
33                 <property name="password" value="${jdbc.password}" />
34             </dataSource>
35         </environment>
36     </environments>
37     <!-- 映射器 -->
38     <mappers>
39         <package name="com.chenyanbin.dao" />
40     </mappers>
41 </configuration>

单元测试

 1 package com.chenyanbin.test;
 2
 3 import java.io.IOException;
 4 import java.io.InputStream;
 5 import java.util.List;
 6 import org.apache.ibatis.io.Resources;
 7 import org.apache.ibatis.plugin.Interceptor;
 8 import org.apache.ibatis.session.SqlSession;
 9 import org.apache.ibatis.session.SqlSessionFactory;
10 import org.apache.ibatis.session.SqlSessionFactoryBuilder;
11 import org.junit.After;
12 import org.junit.Before;
13 import org.junit.Test;
14 import com.chenyanbin.beans.Dept;
15 import com.chenyanbin.dao.DeptMapper;
16
17 public class TestMain_01 {
18     private SqlSession session;
19
20     @Before
21     public void Start() {
22         try {
23             InputStream inputStream = Resources.getResourceAsStream("myBatis-config.xml");
24             SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
25             session = factory.openSession();
26         } catch (Exception e) {
27             e.printStackTrace();
28         }
29     }
30
31     @After
32     public void end() {
33         if (session == null) {
34             session.close();
35         }
36     }
37
38     @Test
39     public void test01() throws IOException {
40         Dept d2 = new Dept();
41         d2.setDname("上海事业部");
42         d2.setLoc("上海");
43         d2.setFlag(false);
44         session.insert("deptSave", d2);
45         session.commit();
46         session.close();
47     }
48
49     @Test
50     public void test02() {
51         Interceptor ccInterceptor;
52           DeptMapper dao=session.getMapper(DeptMapper.class);
53           List<Dept> deptList=dao.deptFind();
54           System.out.println("ok");
55     }
56
57 }

 1 ##define an appender named console
 2 log4j.appender.console=org.apache.log4j.ConsoleAppender
 3 #The Target value is System.out or System.err
 4 log4j.appender.console.Target=System.out
 5 #set the layout type of the apperder
 6 log4j.appender.console.layout=org.apache.log4j.PatternLayout
 7 #set the layout format pattern
 8 log4j.appender.console.layout.ConversionPattern=[%-5p] %m%n
 9
10 ##define a logger
11 log4j.rootLogger=debug,console

log4j.properties

MyBatis自定义拦截器,可以拦截接口只有四种.

  • Executor.class
  • StatementHandler.class
  • ParameterHandler.class
  • ResultSetHandler.class

第二章 MyBatis框架Mapper配置文件详解

2.1 参数(#{参数名})

#{}实现的是向prepareStatement中的预处理语句中设置参数值,sql语句中#{}表示一个占位符即?

使用#{参数名},将参数的内容添加到sql语句中指定位置.

如果当前sql语句中只有一个参数,此时参数名称可以随意定义

但是,如果当前sql语句有多个参数,此时参数名称应该是与当前表关联[实体类的属性名]或则[Map集合关键字]

上述SQL语句在调用时,我们可以分别采用如下两种方式输入参数

使用#{}读取实体类对象属性内容

使用#{}读取map集合中关键字的值

2.2 #{}和${}区别

在MyBatis中提供了两种方式读取参数的内容到SQL语句中,分别是

#{参数名} :实体类对象或则Map集合读取内容

${参数名} :实体类对象或则Map集合读取内容

为了能够看到两种方式的区别,需要看到MyBatis执行时输送的SQL情况.因此

需要借助Log4J日志进行观察

第一步: 加载Log4j日志工具包到项目

第二步:将Log4j配置文件添加到src/main/resources下

接下来,我们可以查看

输出结果

从这里我们可以看出两者的区别:

#{} : 采用预编译方式,可以防止SQL注入

${}:  采用直接赋值方式,无法阻止SQL注入攻击

在大多数情况下,我们都是采用#{}读取参数内容.但是在一些特殊的情况下,我们还是需要使用${}读取参数的.

比如 有两张表,分别是emp_2017 和 emp_2018 .如果需要在查询语句中动态指定表名,就只能使用${}

<select>

select *  from emp_${year}

<select>

再比如.需要动态的指定查询中的排序字段,此时也只能使用${}

<select>

select  *  from dept order by ${name}

</select>

简单来说,在JDBC不支持使用占位符的地方,都可以使用${}

2.3 resultMap

  MyBatis框架中是根据表中字段名到实体类定位同名属性的.如果出现了实体类属性名与表中字段名不一致的情况,则无法自动进行对应.此时可以使用resultMap来重新建立实体类与字段名之间对应关系.

2.4 Sql标签

首先,我们如下两条SQL映射

这两条查询映射中要查询的表以及查询的字段是完全一致的.因此可以<sql>标签

将[select  *  from dept]进行抽取.

在需要使用到这个查询的地方,通过<include>标签进行引用

第三章 MyBatis动态SQL

3.1 什么是MyBatis动态SQL

根据用户提供的参数,动态决定查询语句依赖的查询条件或则SQL语句的内容

3.2 动态SQL依赖标签

  • if
  • choose、when、otherwise
  • trim、where、set
  • foreach

if使用

choose、when、otherwise

  类似于Java中的switch case default. 只有一个条件生效,也就是只执行满足的条件when,没有满足的条件就执行otherwise,表示默认条件

when的使用

set使用

会在成功拼接的条件前加上SET单词且最后一个”,”号会被无视掉

trim使用

foreach的使用

foreach标签用于对集合内容进行遍历,将得到内容作为SQL语句的一部分.

在实际开发过程中主要用于in语句的构建和批量添加操作

foreach元素的属性主要有 item,index,collection,open,separator,close。

案例1.使用foreach实现批处理添加

案例2.使用foreach遍历list集合作为查询条件

案例3.使用foreach遍历数组作为查询条件

案例4.使用foreach遍历Map作为查询条件

原文地址:https://www.cnblogs.com/chenyanbin/p/11656461.html

时间: 2024-08-04 19:47:08

MyBatis详解 一篇就够啦的相关文章

[转帖]前端-chromeF12 谷歌开发者工具详解 Sources篇

前端-chromeF12 谷歌开发者工具详解 Sources篇 原贴地址:https://blog.csdn.net/qq_39892932/article/details/82498748 console 里面的东西 前端的不懂啊.. 这次分享的是Chrome开发工具中最有用的面板Sources. Sources面板几乎是我最常用到的Chrome功能面板,也是在我看来决解一般问题的主要功能面板.通常只要是开发遇到了js报错或者其他代码问题,在审视一遍自己的代码而一无所获之后,我首先就会打开So

mybatis 详解(三)------入门实例(基于注解)

1.创建MySQL数据库:mybatisDemo和表:user 详情参考:mybatis 详解(二)------入门实例(基于XML) 一致 2.建立一个Java工程,并导入相应的jar包,具体目录如下 详情参考:mybatis 详解(二)------入门实例(基于XML) 一致 3.在 MyBatisTest 工程中添加数据库配置文件 mybatis-configuration.xml 详情参考:mybatis 详解(二)------入门实例(基于XML) 一致 4.定义表所对应的实体类 详情

Android View 事件分发机制源码详解(View篇)

前言 在Android View 事件分发机制源码详解(ViewGroup篇)一文中,主要对ViewGroup#dispatchTouchEvent的源码做了相应的解析,其中说到在ViewGroup把事件传递给子View的时候,会调用子View的dispatchTouchEvent,这时分两种情况,如果子View也是一个ViewGroup那么再执行同样的流程继续把事件分发下去,即调用ViewGroup#dispatchTouchEvent:如果子View只是单纯的一个View,那么调用的是Vie

[转帖]前端-chromeF12 谷歌开发者工具详解 Network篇

前端-chromeF12 谷歌开发者工具详解 Network篇 https://blog.csdn.net/qq_39892932/article/details/82493922 blog 也是原作者转帖的 应该是 不过挺好的 可以在1906 里面仔细实验学习一下. 原文链接:https://segmentfault.com/a/1190000010302235 开发者工具初步介绍 chrome开发者工具最常用的四个功能模块: Elements:主要用来查看前面界面的html的Dom结构,和修

[转帖]前端-chromeF12 谷歌开发者工具详解 Console篇

前端-chromeF12 谷歌开发者工具详解 Console篇 https://blog.csdn.net/qq_39892932/article/details/82655866 趁着搞 cloud 的学习学一下chrome前端知识等. 大家都有用过各种类型的浏览器,每种浏览器都有自己的特色,本人拙见,在我用过的浏览器当中,我是最喜欢Chrome的,因为它对于调试脚本及前端设计调试都有它比其它浏览器有过之而无不及的地方.可能大家对console.log会有一定的了解,心里难免会想调试的时候用a

mybatis 详解(七)------一对一、一对多、多对多

前面几篇博客我们用mybatis能对单表进行增删改查操作了,也能用动态SQL书写比较复杂的sql语句.但是在实际开发中,我们做项目不可能只是单表操作,往往会涉及到多张表之间的关联操作.那么我们如何用 mybatis 处理多表之间的关联操作呢?请看本篇博客详解. 本篇详细代码:http://pan.baidu.com/s/1eSzmst8 密码:3n3o 1.一对一 我们以用户表 user 和订单表 orders 为例.设定一个订单只能由一个 用户创建,那么由订单到用户就是一对一的关系. ①.创建

BGP路由协议详解(完整篇)

原文链接:http://xuanbo.blog.51cto.com/499334/465596/ 2010-12-27 12:02:45 上个月我写一篇关于BGP协议的博文,曾许诺过要完善这个文档,但因最近的工作和授课很忙,所以没有时间进行完善.为了实现这个承诺,我在去外地出差期间对BGP协议详解博文进行一些修改,其中内容包括了一些实验,以及一些内容的补充和深入阐述,更宜于网友们学习BGP路由协议.因为这个文档出来的很晚,也希望网友们见谅! 此BGP协议的内容也不算太难,一些关于BGP的高级应用

入木三分学网络第一篇--VRRP协议详解第一篇(转)

因为keepalived使用了VRRP协议,所有有必要熟悉一下. 虚拟路由冗余协议(Virtual Router Redundancy Protocol,简称VRRP)是解决局域网中配置静态网关时,静态网关出现单点失效现象的路由协议. VRRP广泛应用在边缘网络中,它的设计目标是支持特定情况下IP数据流量失败转移不会引起混乱,允许主机使用单路由器(位于一个虚拟路由器组中, 在该组中,只有一台路由器--master路由器工作,转发数据包,其它路由器是backup路由器,不参与转发数据包),以及在实

http协议详解-经典篇

本文转载至 http://www.cnblogs.com/flychen/archive/2012/11/28/2792206.html ———————————————————————————————————————— 欢迎转载,尊重原创——flychen http://www.cnblogs.com/flychen ———————————————————————————————————————— AUTHOR:  Jeffrey.zhu  引言 HTTP是一个属于应用层的面向对象的协议,由于其