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

1.1 typeHandlers类型转换器

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

TypeHandlers

1.1.1 自定义类型转换器

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

(1)实体类

 package com.chenyanbin.beans;

 public class Dept {
private Integer deptNo;
private String dname;
private String loc;
private boolean flag;
public Integer getDeptNo() {
return deptNo;
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
public void setDeptNo(Integer deptNo) {
this.deptNo = deptNo;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
}

(2) 表中字段

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

继承并实现接口:TypeHandler.java

 package com.chenyanbin.util;

 import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import org.apache.ibatis.jdbc.Null;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;
/*
* setParameter:这个方法在生成SQL语句时才被调用
*
* getResult:查询结束之后,在将ResultSet数据行转换为实体类对象时,通知TypeHandler将当前数据行某个字段转换为何种类型
*
*
*/
public class MyTypeHandler implements TypeHandler { 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 }

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 }

public Object getResult(ResultSet rs, int columnIndex) throws SQLException {
// TODO Auto-generated method stub
return null;
} public Object getResult(CallableStatement cs, int columnIndex) throws SQLException {
// TODO Auto-generated method stub
return null;
} }

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

myBatis-config.xml

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 属性配置 -->
<properties resource="config.properties"></properties>
<!-- 别名配置 -->
<typeAliases>
<package name="com.chenyanbin.beans" />
<package name="com.chenyanbin.dao" />
</typeAliases>
<!-- 类型处理器 -->
<typeHandlers>
<!-- 从java中的Boolean转jdbc中的NUMERIC -->
<typeHandler handler="com.chenyanbin.util.MyTypeHandler"
javaType="Boolean" jdbcType="NUMERIC" />
</typeHandlers>
<!-- 环境配置 -->
<environments default="development">
<!-- 环境配置 -->
<environment id="development">
<!-- 事务管理器 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源 -->
<dataSource type="pooled">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!-- 映射器 -->
<mappers>
<package name="com.chenyanbin.dao" />
</mappers>
</configuration>

config.properties

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

(5) 创建接口:DeptMapper.java

 package com.chenyanbin.dao;

 import java.util.List;
import com.chenyanbin.beans.Dept; public interface DeptMapper {
public void deptSave(Dept dept); public List<Dept> deptFind();
}

(6)  DeptMapper.xml

 <?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.chenyanbin.dao.DeptMapper">
<insert id="deptSave">
insert into dept (DEPTNO,DNAME,LOC,flag)
values(#{deptNo},#{dname},#{loc},#{flag})
</insert>
<select id="deptFind" resultType="Dept">
select deptNo,dname,loc,flag from dept
</select>
</mapper>
 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 属性配置 -->
<properties resource="config.properties"></properties>
<!-- 别名配置 -->
<typeAliases>
<package name="com.chenyanbin.beans" />
<package name="com.chenyanbin.dao" />
</typeAliases>
<!-- 环境配置 -->
<environments default="development">
<!-- 环境配置 -->
<environment id="development">
<!-- 事务管理器 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源 -->
<dataSource type="pooled">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!-- 映射器 -->
<mappers>
<package name="com.chenyanbin.dao" />
</mappers>
</configuration>

方式二:myBatis-config.xml

 <?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.chenyanbin.dao.DeptMapper">
<insert id="deptSave">
insert into dept (DEPTNO,DNAME,LOC,flag)
values(#{deptNo},#{dname},#{loc},#{flag})
</insert>
<resultMap type="dept" id="deptMap">
<result column="flag" property="flag" typeHandler="com.chenyanbin.util.MyTypeHandler"/>
</resultMap>
<select id="deptFind" resultType="Dept">
select deptNo,dname,loc,flag from dept
</select>
</mapper>

方式二:DeptMapper.xml

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

 package com.chenyanbin.test;

 import java.io.IOException;
import java.io.InputStream;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.chenyanbin.beans.Dept;
import com.chenyanbin.dao.DeptMapper; public class TestMain_01 {
private SqlSession session; @Before
public void Start() {
try {
InputStream inputStream = Resources.getResourceAsStream("myBatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
session = factory.openSession();
} catch (Exception e) {
e.printStackTrace();
}
} @After
public void end() {
if (session == null) {
session.close();
}
} @Test
public void test01() throws IOException {
Dept d2 = new Dept();
d2.setDname("上海事业部");
d2.setLoc("上海");
d2.setFlag(false);
session.insert("deptSave", d2);
session.commit();
session.close();
} @Test
public void test02() {
DeptMapper dao=session.getMapper(DeptMapper.class);
List<Dept> deptList=dao.deptFind();
System.out.println("ok");
} }

(8) 项目目录结构

1.2 objectFactory 对象工厂

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

1.2.1 自定义对象工厂

表结构:dept

实体类:Dept.java

 package com.chenyanbin.beans;

 public class Dept {
private Integer deptNo;
private String dname;
private String loc;
private Boolean flag;
8 private String country;
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public Integer getDeptNo() {
return deptNo;
}
public Boolean getFlag() {
return flag;
}
public void setFlag(Boolean flag) {
this.flag = flag;
}
public void setDeptNo(Integer deptNo) {
this.deptNo = deptNo;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
}

(1) 继承与DefaultObjectFactory:MyObjectFactory.java

 package com.chenyanbin.util;

 import org.apache.ibatis.reflection.factory.DefaultObjectFactory;

 import com.chenyanbin.beans.Dept;

 public class MyObjectFactory extends DefaultObjectFactory {

     @Override
public Object create(Class type) {// 重新定义Dept类实例对象创建规则,其他类实例对象创建规则不想改变
if (Dept.class == type) {
// 依靠父类提供create方法创建Dept对象
Dept dept = (Dept) super.create(type);
// 设置自定义规则
dept.setCountry("China");
return dept;
}
return super.create(type);
} }

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

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 属性配置 -->
<properties resource="config.properties"></properties>
<!-- 别名配置 -->
<typeAliases>
<package name="com.chenyanbin.beans" />
<package name="com.chenyanbin.dao" />
</typeAliases>
13 <!-- ObjectFactory对象工厂 -->
14 <objectFactory type="com.chenyanbin.util.MyObjectFactory"></objectFactory>

<!-- 类型处理器 -->
<!-- <typeHandlers>
从java中的Boolean转jdbc中的NUMERIC
<typeHandler handler="com.chenyanbin.util.MyTypeHandler"
javaType="Boolean" jdbcType="NUMERIC" />
</typeHandlers> -->
<!-- 环境配置 -->
<environments default="development">
<!-- 环境配置 -->
<environment id="development">
<!-- 事务管理器 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源 -->
<dataSource type="pooled">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!-- 映射器 -->
<mappers>
<package name="com.chenyanbin.dao" />
</mappers>
</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

 package com.chenyanbin.util;

 import java.util.Properties;

 import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds; @Intercepts({ @Signature(method = "query", type = Executor.class, args = { MappedStatement.class, Object.class,
RowBounds.class, ResultHandler.class }) })
public class MySimpleInterceptor implements Interceptor {
/*
* 参数:Invocation {代理对象,被监控的方法对象,当前被监控方法运行时需要实参}
*/
public Object intercept(Invocation invocation) throws Throwable {
// TODO Auto-generated method stub
System.out.println("被拦截方法执行之前,做的辅助服务。。。。。");
Object object = invocation.proceed(); // 执行被拦截方法
System.out.println("被拦截方法执行之后,做的辅助服务。。。。。");
return object;
} /*
* 参数:target 表示被拦截的对象,应该是Executor接口实例对象 作用: 如果 被拦截的对象所在的类是有实现接口就为当前拦截对象生成一个代理对象
* 如果被拦截的对象所在的类没有指定接口,这个对象之后的行为不会被代理操作
*/
public Object plugin(Object target) {
// TODO Auto-generated method stub
return Plugin.wrap(target, this);
} public void setProperties(Properties properties) {
// TODO Auto-generated method stub } }

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

 <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 属性配置 -->
<properties resource="config.properties"></properties>
<!-- 别名配置 -->
<typeAliases>
<package name="com.chenyanbin.beans" />
<package name="com.chenyanbin.dao" />
</typeAliases>
<!-- ObjectFactory对象工厂 -->
<objectFactory type="com.chenyanbin.util.MyObjectFactory"></objectFactory>
15 <!-- Plugins拦截器 -->
16 <plugins>
17 <plugin interceptor="com.chenyanbin.util.MySimpleInterceptor"></plugin>
18 </plugins>

<!-- 类型处理器 -->
<!-- <typeHandlers> 从java中的Boolean转jdbc中的NUMERIC <typeHandler handler="com.chenyanbin.util.MyTypeHandler"
javaType="Boolean" jdbcType="NUMERIC" /> </typeHandlers> -->
<!-- 环境配置 -->
<environments default="development">
<!-- 环境配置 -->
<environment id="development">
<!-- 事务管理器 -->
<transactionManager type="JDBC"></transactionManager>
<!-- 数据源 -->
<dataSource type="pooled">
<property name="driver" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</dataSource>
</environment>
</environments>
<!-- 映射器 -->
<mappers>
<package name="com.chenyanbin.dao" />
</mappers>
</configuration>

单元测试

 package com.chenyanbin.test;

 import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import com.chenyanbin.beans.Dept;
import com.chenyanbin.dao.DeptMapper; public class TestMain_01 {
private SqlSession session; @Before
public void Start() {
try {
InputStream inputStream = Resources.getResourceAsStream("myBatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
session = factory.openSession();
} catch (Exception e) {
e.printStackTrace();
}
} @After
public void end() {
if (session == null) {
session.close();
}
} @Test
public void test01() throws IOException {
Dept d2 = new Dept();
d2.setDname("上海事业部");
d2.setLoc("上海");
d2.setFlag(false);
session.insert("deptSave", d2);
session.commit();
session.close();
} @Test
public void test02() {
Interceptor ccInterceptor;
DeptMapper dao=session.getMapper(DeptMapper.class);
List<Dept> deptList=dao.deptFind();
System.out.println("ok");
} }

 ##define an appender named console
log4j.appender.console=org.apache.log4j.ConsoleAppender
#The Target value is System.out or System.err
log4j.appender.console.Target=System.out
#set the layout type of the apperder
log4j.appender.console.layout=org.apache.log4j.PatternLayout
#set the layout format pattern
log4j.appender.console.layout.ConversionPattern=[%-5p] %m%n ##define a logger
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 id="deptFind2" resultType="Dept">
select * from ${value}
</select>

动态表名,此处只能:value

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

<select>

select  *  from dept order by ${name}

</select>

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

2.3 resultMap

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

 <!-- property对应实体类的属性名称,column为数据库结果集的列的名称 -->

映射表没有的字段

表结构

EmpMapper.xml

 <?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.chenyanbin.dao.EmpMapper">
<resultMap type="Employee" id="empMap">
<constructor>
<arg column="hireDate" javaType="java.util.Date" />
</constructor>
</resultMap>
<select id="empFind" resultMap="empMap">
select * from emp2
</select>
</mapper>

EmpMapper.java

 package com.chenyanbin.dao;

 import java.util.List;

 public interface EmpMapper {
public List empFind();
}

Employee.java

 package com.chenyanbin.beans;

 import java.text.SimpleDateFormat;
import java.util.Date; public class Employee {
private Integer empNo;
private String ename;
private String job;
private Double sal;
private Date hireDate;
// 职员工作年限
private int workAge; // 构造函数
public Employee(Date tempDate) {
this.hireDate = tempDate;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
this.workAge = Integer.valueOf(sdf.format(new Date())) - Integer.valueOf(sdf.format(tempDate)); } public int getWorkAge() {
return workAge;
} public void setWorkAge(int workAge) {
this.workAge = workAge;
} public Integer getEmpNo() {
return empNo;
} public void setEmpNo(Integer empNo) {
this.empNo = empNo;
} public String getEname() {
return ename;
} public void setEname(String ename) {
this.ename = ename;
} public String getJob() {
return job;
} public void setJob(String job) {
this.job = job;
} public Double getSal() {
return sal;
} public void setSal(Double sal) {
this.sal = sal;
} public Date getHireDate() {
return hireDate;
} public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
}

单元测试

 package com.chenyanbin.test;

 import java.io.InputStream;
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 org.junit.After;
import org.junit.Before;
import org.junit.Test; import com.chenyanbin.beans.Employee;
import com.chenyanbin.dao.DeptMapper;
import com.chenyanbin.dao.EmpMapper; public class TestMain_01 {
private SqlSession session; @Before
public void Start() {
try {
InputStream inputStream = Resources.getResourceAsStream("myBatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream);
session = factory.openSession();
} catch (Exception e) {
e.printStackTrace();
}
} @After
public void end() {
if (session == null) {
session.close();
}
}
@Test
public void test01() {
try {
EmpMapper dao=session.getMapper(EmpMapper.class);
List<Employee> deptList=dao.empFind();
System.out.println("sssss");
} catch (Exception e) {
e.printStackTrace();
}
}
}

项目结构

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作为查询条件

 public List findForeachByMap(@Param("myMap")Map amp);
 <?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.chenyanbin.dao.DeptMapper">
<resultMap type="dept" id="deptMap">
<id column="dept_deptno" property="deptNo" />
<result column="dname" property="dname" />
<result column="loc" property="loc" />
<!-- collection标签中,column属性应该填写查询临时表中来自一方表主键字段名 -->
<collection property="empList" ofType="Employee"
column="dept_deptno">
<id column="empno" property="empNo" />
<result column="ename" property="ename" />
</collection>
</resultMap>
<!-- 查询当前部门下所有的职员名称以及当前部门基本信息 -->
<select id="deptFindById" resultMap="deptMap">
select dept.deptno
dept_deptno,dept.dname,dept.loc,emp.empno,emp.ename,emp.sal from dept
join emp on dept.deptno=emp.deptno where dept.deptno=#{deptno}
</select>
</mapper> =============================
package com.chenyanbin.beans; import java.util.List; public class Dept {
private Integer deptNo;
private String dname;
private String loc;
//隶属于当前部门下的所有职员集合
private List<Employee> empList;
public List<Employee> getEmpList() {
return empList;
}
public void setEmpList(List<Employee> empList) {
this.empList = empList;
}
public Integer getDeptNo() {
return deptNo;
}
public void setDeptNo(Integer deptNo) {
this.deptNo = deptNo;
}
public String getDname() {
return dname;
}
public void setDname(String dname) {
this.dname = dname;
}
public String getLoc() {
return loc;
}
public void setLoc(String loc) {
this.loc = loc;
}
} ====================================
package com.chenyanbin.beans; import java.util.Date; public class Employee {
private Integer empNo;
private String ename;
private String job;
private Double sal;
private Date hireDate;
// 职员工作年限
private int workAge; public int getWorkAge() {
return workAge;
} public void setWorkAge(int workAge) {
this.workAge = workAge;
} public Integer getEmpNo() {
return empNo;
} public void setEmpNo(Integer empNo) {
this.empNo = empNo;
} public String getEname() {
return ename;
} public void setEname(String ename) {
this.ename = ename;
} public String getJob() {
return job;
} public void setJob(String job) {
this.job = job;
} public Double getSal() {
return sal;
} public void setSal(Double sal) {
this.sal = sal;
} public Date getHireDate() {
return hireDate;
} public void setHireDate(Date hireDate) {
this.hireDate = hireDate;
}
}

级联查询

 <?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.chenyanbin.dao.DeptMapper">
<resultMap type="dept" id="deptMap">
<id column="dept_deptno" property="deptNo" />
<result column="dname" property="dname" />
<result column="loc" property="loc" />
<!-- collection标签中,column属性应该填写查询临时表中来自一方表主键字段名 -->
<collection property="empList" ofType="Employee"
select="empFindByDeptNo" column="dept_deptno">
</collection>
</resultMap>
<!-- 根据部门编号查询部门中的职员信息 -->
<select id="empFindByDeptNo" resultType="Employee">
select empno,ename,job
from emp where deptno=#{deptno}
</select>
<!-- 根据部门编号查询部门信息 -->
<select id="deptFindByDeptNo" resultMap="deptMap">
select deptNo
dept_deptno,dname,loc from dept where deptno=#{deptno}
</select>
</mapper>

方式二

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

  1. mybatis 详解------动态SQL

    mybatis 详解------动态SQL   目录 1.动态SQL:if 语句 2.动态SQL:if+where 语句 3.动态SQL:if+set 语句 4.动态SQL:choose(when,o ...

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

    前端-chromeF12 谷歌开发者工具详解 Sources篇 原贴地址:https://blog.csdn.net/qq_39892932/article/details/82498748 cons ...

  3. [原创]mybatis详解说明

    mybatis详解 2017-01-05MyBatis之代理开发模式1 mybatis-Dao的代理开发模式 Dao:数据访问对象 原来:定义dao接口,在定义dao的实现类 dao的代理开发模式 只 ...

  4. 微信授权步骤与详解 -- c#篇

    微信授权步骤与详解 -- c#篇 注:这里不涉及界面操作,只介绍代码操作. 1.基本原理如下: 从图上所知,第一步用户访问我们的网页,第二步我们后台跳转到微信授权页面,第三步用户点击授权,第四步微信重 ...

  5. bt协议详解 DHT篇(下)

    bt协议详解 DHT篇(下) 最近开发了一个免费教程的网站,产生了仔细了解bt协议的想法,这篇文章是bt协议详解系列的第三篇,后续还会写一些关于搜索和索引的东西,都是在开发这个网站的过程中学习到的技术 ...

  6. bt协议详解 DHT篇(上)

    bt协议详解 DHT篇(上) 最近开发了一个免费教程的网站,突然产生了仔细了解bt协议的想法,这篇文章是bt协议详解系列的第三篇,后续还会写一些关于搜索和索引的东西,都是在开发这个网站的过程中学习到的 ...

  7. IIS负载均衡-Application Request Route详解第二篇:创建与配置Server Farm(转载)

    IIS负载均衡-Application Request Route详解第二篇:创建与配置Server Farm 自从本系列发布之后,收到了很多的朋友的回复!非常感谢,同时很多朋友问到了一些问题,有些问 ...

  8. IIS负载均衡-Application Request Route详解第一篇: ARR介绍(转载)

    IIS负载均衡-Application Request Route详解第一篇: ARR介绍 说到负载均衡,相信大家已经不再陌生了,本系列主要介绍在IIS中可以采用的负载均衡的软件:微软的Applica ...

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

    1.创建MySQL数据库:mybatisDemo和表:user 详情参考:mybatis 详解(二)------入门实例(基于XML) 一致 2.建立一个Java工程,并导入相应的jar包,具体目录如 ...

随机推荐

  1. JavaScript中的Cookie 和 Json的使用

    JavaScript中的Cookie 和 Json的使用 JSON JSON(JavaScript Object Notation)是一种轻量级的数据交换格式.采用的是完全独立于编程语言的文本格式来存 ...

  2. springboot的最简创建方式

    springboot是目前比较流行的技术栈之一,我在这里写一个springboot工程最简方式 首先开发工具是IDEA,双击打开IDEA,点击Create new Project 进入到这个页面,选择 ...

  3. 实现一个简易版的vuex持久化工具

    背景 最近用uni-app开发小程序项目时,部分需要持久化的内容直接使用vue中的持久化插件貌似不太行,所以想着自己实现一下类似vuex-persistedstate插件的功能,想着功能不多,代码量应 ...

  4. Vert.x Web之Router

    Vert.x Web 是一系列用于基于 Vert.x 构建 Web 应用的构建模块. Vert.x Web 的大多数特性被实现为了处理器(Handler),因此您随时可以实现您自己的处理器.我们预计随 ...

  5. Linux上安装JDK1.7步骤

    1.使用SecurtCRT连接上Linux,把jdk的压缩包传递过去:(传递的方法在我的博客中也有写,参考之前的博客) 2.解压缩jdk:tar -zxvf jdk-7u55-linux-i586.t ...

  6. TensorFlow读取数据的三种方法

    tensortlfow数据读取有三种方式 placehold feed_dict:从内存中读取数据,占位符填充数据 queue队列:从硬盘读取数据 Dataset:同时支持内存和硬盘读取数据 plac ...

  7. Hadoop常见重要命令行操作及命令作用

    关于Hadoop [root@master ~]# hadoop --help Usage: hadoop [--config confdir] COMMANDwhere COMMAND is one ...

  8. valueForKey与valueForKeyPath 区别

    1.删除数组中重复的数据 2.valueForKeyPath:可以深层次取到子属性,不管隐藏的多深  valueForKey:无法取到深层次子属性 但是也有其相似的地方: 比如:快速找到字典数组中ke ...

  9. java需要了解和学习的技能

    一:系统架构师是一个最终确认和评估系统需求,给出开发规范,搭建系统实现的核心构架,并澄清技术细节.扫清主要难点的技术人员.主要着眼于系统的“技术实现”.因此他/她应该是特定的开发平台.语言.工具的大师 ...

  10. Hadoop 之 深入探索MapReduce

    1.MapReduce基础概念 答:MapReduce作业时一种大规模数据的并行计算的便程模型.我们可以将HDFS中存储的海量数据,通过MapReduce作业进行计算,得到目标数据. 2.MapRed ...