MyBatis详解 一篇就够啦
第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详解 一篇就够啦的更多相关文章
- mybatis 详解------动态SQL
mybatis 详解------动态SQL 目录 1.动态SQL:if 语句 2.动态SQL:if+where 语句 3.动态SQL:if+set 语句 4.动态SQL:choose(when,o ...
- [转帖]前端-chromeF12 谷歌开发者工具详解 Sources篇
前端-chromeF12 谷歌开发者工具详解 Sources篇 原贴地址:https://blog.csdn.net/qq_39892932/article/details/82498748 cons ...
- [原创]mybatis详解说明
mybatis详解 2017-01-05MyBatis之代理开发模式1 mybatis-Dao的代理开发模式 Dao:数据访问对象 原来:定义dao接口,在定义dao的实现类 dao的代理开发模式 只 ...
- 微信授权步骤与详解 -- c#篇
微信授权步骤与详解 -- c#篇 注:这里不涉及界面操作,只介绍代码操作. 1.基本原理如下: 从图上所知,第一步用户访问我们的网页,第二步我们后台跳转到微信授权页面,第三步用户点击授权,第四步微信重 ...
- bt协议详解 DHT篇(下)
bt协议详解 DHT篇(下) 最近开发了一个免费教程的网站,产生了仔细了解bt协议的想法,这篇文章是bt协议详解系列的第三篇,后续还会写一些关于搜索和索引的东西,都是在开发这个网站的过程中学习到的技术 ...
- bt协议详解 DHT篇(上)
bt协议详解 DHT篇(上) 最近开发了一个免费教程的网站,突然产生了仔细了解bt协议的想法,这篇文章是bt协议详解系列的第三篇,后续还会写一些关于搜索和索引的东西,都是在开发这个网站的过程中学习到的 ...
- IIS负载均衡-Application Request Route详解第二篇:创建与配置Server Farm(转载)
IIS负载均衡-Application Request Route详解第二篇:创建与配置Server Farm 自从本系列发布之后,收到了很多的朋友的回复!非常感谢,同时很多朋友问到了一些问题,有些问 ...
- IIS负载均衡-Application Request Route详解第一篇: ARR介绍(转载)
IIS负载均衡-Application Request Route详解第一篇: ARR介绍 说到负载均衡,相信大家已经不再陌生了,本系列主要介绍在IIS中可以采用的负载均衡的软件:微软的Applica ...
- mybatis 详解(三)------入门实例(基于注解)
1.创建MySQL数据库:mybatisDemo和表:user 详情参考:mybatis 详解(二)------入门实例(基于XML) 一致 2.建立一个Java工程,并导入相应的jar包,具体目录如 ...
随机推荐
- LeetCode - 字符串数字相乘与相加
43. 字符串相乘 给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式. 示例 1: 输入: num1 = "2& ...
- DNS解析域名的过程
一.DNS解析域名的过程 1.大的过程可分为三步: (1).在缓存中查找是否之前解析过 (2).在windows系统的host文件中查找 (3).请求DNS服务器 2.小的过程可分为十步: (1).浏 ...
- SpringCloud超简单的入门(1)--一些简单的介绍
简介 简单来说,springcloud的就是由一组springboot应用(服务)组成,相互之间通过REST等方式进行通信. 两个springboot应用,其中一个作为服务提供者,一个作为服务消费者, ...
- ImageView的功能和使用
ImageView继承自View类,它的功能用于显示图片, 或者显示Drawable对象 xml属性: src和background区别 参考:http://hi.baidu.com/sunboy_2 ...
- Python Flask高级编程之RESTFul API前后端分离精讲 (网盘免费分享)
Python Flask高级编程之RESTFul API前后端分离精讲 (免费分享) 点击链接或搜索QQ号直接加群获取其它资料: 链接:https://pan.baidu.com/s/12eKrJK ...
- java基本数据类型与引用类型
基本数据类型: byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0 short:短整型,在内存中占16位,即2个字节,取值范围-32768~3 ...
- STL中区间最值max_element和min_element的用法
前面的博客已经讲解了nth_element寻找区间第K大的用法,现在我们来说说这两个找区间最值的用法.两个函数都包含在algorithm库中. 一.函数原型 max_element template& ...
- ElasticSearch实战系列二: ElasticSearch的DSL语句使用教程---图文详解
前言 在上一篇中介绍了ElasticSearch集群和kinaba的安装教程,本篇文章就来讲解下 ElasticSearch的DSL语句使用. ElasticSearch DSL 介绍 Elastic ...
- Python 踩坑之旅文件系统篇其一文件夹也是个文件
目录 1.1 案例 1.2 分析 1.3 扩展 1.4 技术关键字 下期预告 代码示例支持 平台: Mac OS Python: 2.7.10 代码示例: - wx: 菜单 - Python踩坑指南代 ...
- java8 新特性精心整理(全)
前言 越来越多的项目已经使用 Java 8 了,毫无疑问,Java 8 是Java自Java 5(发布于2004年)之后的最重要的版本.这个版本包含语言.编译器.库.工具和 JVM 等方面的十多个新特 ...