JavaEE——MyBaits配置详解

1. 全局配置 SqlMapConfig

1.1 配置内容和顺序

SqlMapConfig.xml 是 Mybatis 的全局配置文件,其配置的内容和顺序如下:
1:properties(属性)
2:settings(全局配置参数)
3:typeAliases(类型别名)
4:typeHandlers(类型处理器)
5:objectFactory(对象工厂)
6:plugins(插件)
7:environments(环境集合属性对象)
8: environment(环境子属性对象)
9: transactionManager(事务管理)
10: dataSource(数据源)
11:mappers(映射器)

1.2 properties(属性)

properties 属性可以加载数据库配置信息。在 src/main/resources 中创建db.properties,
内容如下所示:

jdbc.driver=com.mysql.jdbc.Driver 
jdbc.url=jdbc:mysql://localhost:3306/eshop?characterEncoding=utf8 
jdbc.username=root 
jdbc.password=123456

在 SqlMapConfig.xml 中加载 db.properties

<?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="db.properties"></properties> 
  <environments default="development"> 
    <environment id="development"> 
      <transactionManager type="JDBC" /> 
      <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> 
</configuration> 

1.3 settings(全局配置)

settings 是 mybatis 全局配置参数,可根据项目的需要进行设置,其可设置的参数详见以下配置:

<!-- settings 是  MyBatis  中极为重要的调整设置,它们会改变  MyBatis  的运行时行为。--> 
<settings>     
        <!--  该配置影响的所有映射器中配置的缓存的全局开关。默认值 true -->     
        <setting name="cacheEnabled" value="true"/> 
        <!--延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。特定关联关系中可通过设置 fetchType
属性来覆盖该项的开关状态。默认值 false    --> 
        <setting name="lazyLoadingEnabled" value="true"/>     
        <!--  是否允许单一语句返回多结果集(需要兼容驱动)。默认值 true --> 
        <setting name="multipleResultSetsEnabled" value="true"/>     
        <!--  使用列标签代替列名。不同的驱动在这方面会有不同的表现,具体可参考相关驱动文档或通过测
试这两种不同的模式来观察所用驱动的结果。默认值 true --> 
        <setting name="useColumnLabel" value="true"/>     
        <!--  允许 JDBC 支持自动生成主键,需要驱动兼容。如果设置为 true 则这个设置强制使用自动生成主键,
尽管一些驱动不能兼容但仍可正常工作(比如 Derby)。默认值 false    --> 
        <setting name="useGeneratedKeys" value="false"/> 
        <!--指定 MyBatis 应如何自动映射列到字段或属性。NONE 表示取消自动映射;PARTIAL 只会自动映射没
有定义嵌套结果集映射的结果集。FULL 会自动映射任意复杂的结果集(无论是否嵌套)。默认值 PARTIAL--> 
        <setting name="autoMappingBehavior" value="PARTIAL"/> 
        <!--配置默认的执行器。SIMPLE 就是普通的执行器;REUSE 执行器会重用预处理语句(prepared 
statements);BATCH 执行器将重用语句并执行批量更新。默认 SIMPLE--> 
        <setting name="defaultExecutorType" value="SIMPLE"/> 
        <!--  设置超时时间,它决定驱动等待数据库响应的秒数。--> 
        <setting name="defaultStatementTimeout" value="25"/> 
        <!--  允许在嵌套语句中使用分页(RowBounds)默认值 False --> 
        <setting name="safeRowBoundsEnabled" value="false"/> 
        <!--  是否开启自动驼峰命名规则(camel case)映射,即从经典数据库列名  A_COLUMN 到经典 Java 属
性名 aColumn 的类似映射。默认 false --> 
        <setting name="mapUnderscoreToCamelCase" value="false"/>     
        <!-- MyBatis 利用本地缓存机制(Local Cache)防止循环引用(circular references)和加速重复嵌套查询。
默认值为 SESSION,这种情况下会缓存一个会话中执行的所有查询。若设置值为 statement,本地会话仅用
在语句执行上,对相同 SqlSession  的不同调用将不会共享数据。  --> 
        <setting name="localCacheScope" value="SESSION"/> 
          <!--  当没有为参数提供特定的 JDBC 类型时,为空值指定 JDBC 类型。某些驱动需要指定列的 JDBC 类型,
多数情况直接用一般类型即可,比如 NULL、VARCHAR 或 OTHER。  --> 
        <setting name="jdbcTypeForNull" value="OTHER"/> 
        <!--  指定哪个对象的方法触发一次延迟加载。--> 
        <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/> 
</settings> 

1.4 typeAliases(类型别名)

Mapper Statement 中的 parameterType 和 resultType 的值是类的全路径,例如

<insert parameterType="java.lang.String" resultType="java.lang.Integer"> 

中的 java.lang.String 和 java.lang.Integer 是类的全路径。使用类的全路径在开发中不方便,使用 typeAliases 可以为类的全路径起一个简单的别名,方便使用。使用 typeAliases 将上面的配置改为

<insert parameterType="string " resultType="int"> 

其值的 string 是 java.lang.String 的别名,int 是 java.lang.Integer 的别名。Mybatis 默认支持的别名如下表:
在这里插入图片描述
在这里插入图片描述
但针对 POJO 类型需要自定义别名。在 SqlMapConfig.xml 中通过 typeAliases 可以为 POJO定义别名。

<typeAliases> 
<!--  单个定义别名  --> 
<typeAlias alias="userInfoModel" type="cn.itlaobing.mybatis.model.UserInfoModel"/> 
<!--  批量定义别名,扫描整个包下的类,别名为类名(首字母大写或小写都可以)  --> 
<package name="cn.itlaobing.mybatis.model"/> 
</typeAliases> 
<!—使用别名  --> 
<select id="finduserinfobyid" parametertype="int" resultType="userInfoModel"> 
  select * from userinfo where id=#{id} 
</select> 

1.5 typeHandlers(类型处理器)

typeHandlers 用于 java 类型和 jdbc 类型映射,例如在 Java 中 String 表示字符串,而在数据库中 varchar 表示字符串,typeHandlers 用于将 java 中的 String 映射为数据库中的 varchar。Mybatis 提供的 typeHandlers 以满足大部分开发需要,通常开发人员不需要自定义typeHandlers。Mybatis 提供的默认 typeHandlers 如下表:
在这里插入图片描述
在这里插入图片描述

1.6 mappers(映射器)

mappers 用于加载映射文件到全局配置文件中,Mybatis 有四种加载映射文件的方法。分别是 resource、url、class、package。参考配置如下:

<mappers> 
<mapper resource="userInfoMapper.xml" /> 
<mapper url="file:///D:\mybatis-1\config\userInfoMapper.xml" /> 
<mapper class="cn.itlaobing.mybatis.mapper.IUserInfoMapper"/> 
<package name="cn.itlaobing.mybatis.mapper"/> 
</mappers> 

resource
使用相对于类路径的资源,如:<mapper resource="userInfoMapper.xml" />。这种方法一次加载一个映射文件。
url
使用完全限定路径,如:<mapper url="file:///D:\mybatis-1\config\userInfoMapper.xml" />。这种方法一次加载一个映射文件。由于使用了绝对路径,不建议使用这种方式。
class
使用 mapper 接口路径,如<mapper class="cn.itlaobing.mybatis.mapper.IUserInfoMapper"/>。注意:这种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。
package
注册指定包下的所有mapper 接口,如:<package name="cn.itlaobing.mybatis.mapper"/>。注意:此种方法要求 mapper 接口名称和 mapper 映射文件名称相同,且放在同一个目录中。这种方式可以实现批量加载,推荐使用。

2 输入映射 parameterType

输入映射是由 Mapper Statement 的 parameterType 属性设置的。所有的输入映射都需要以下两步来完成:

  1. Mapper 映射配置
  2. Mapper 接口定义

Mybatis 的输入映射就是将 Java 的对象映射为 SQL 语句中列的值。Mybatis 的输入映射形式包括简单类型输入映射、POJO 类型输入 映射、VO 类型输入映射、HashMap 输入映射。

2.1 简单类型输入映射

需求:根据 id 查询指定的用户

  1. Mapper 映射配置
<select id="findUserInfoById" parameterType="int" 
  resultType="cn.itlaobing.mybatis.model.UserInfoModel"> 
  select * from userInfo where id=#{id} 
</select> 
  1. Mapper 接口定义
public UserInfoModel findUserInfoById(int id) throws Exception; 
  1. 单元测试
@Test 
public void testFindUserInfoById() throws Exception { 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  //创建 IUserInfoMapper 对象,mybatis 自动生成 IUserInfoMapper 的代理对象 
  IUserInfoMapper userInfoMapper = sqlSession.getMapper(IUserInfoMapper.class); 
  UserInfoModel model = userInfoMapper.findUserInfoById(1); 
  sqlSession.close(); 
  System.out.println(model); 
} 
  1. 运行结果
Preparing: SELECT * FROM userInfo WHERE id=? 
Parameters: 1(Integer) 
Total: 1 
1--admin--admin--1980-10-10--男--陕西西安 

Mapper 映射配置中的 parameterType 是简单类型中的 int 类型,与 Mapper 接口中的方法参数 id 是匹配的数据类型。

2.2 POJO 类型输入映射

需求:添加用户

  1. Mapper 映射配置
<insert id="insertUserInfo" parameterType="cn.itlaobing.mybatis.model.UserInfoMo 
del"> 
  <selectKey keyProperty="id" order="AFTER" resultType="java.lang.Integer"> 
    select last_insert_id() 
  </selectKey> 
  insert into userinfo(userName,userPass,birthday,gender,address) 
   values(#{userName},#{userPass},#{birthday},#{gender},#{address}); 
</insert> 
  1. Mapper 接口定义
public void insertUserInfo(UserInfoModel model) throws Exception; 

Mapper 映射配置中的 parameterType 是 UserInfoModel 类型,与 Mapper 接口中的方法参数 UserInfoModel model 是匹配的数据类型。 Mapper 映射文件中的#{userName}中的 userName 就是 parameterType 属性的值UserInfoModel 类的属性名。

  1. 单元测试
@Test 
public void testInsertUser() throws Exception { 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  //创建 IUserInfoMapper 对象,mybatis 自动生成 IUserInfoMapper 的代理对象 
  IUserInfoMapper userInfoMapper = sqlSession.getMapper(IUserInfoMapper.class); 
  UserInfoModel model = new UserInfoModel(); 
  model.setUserName("李应"); 
  model.setUserPass("liying"); 
  model.setBirthday(new Date()); 
  model.setGender("男"); 
  model.setAddress("山东聊城"); 
  userInfoMapper.insertUserInfo(model); 
  sqlSession.commit(); 
  sqlSession.close(); 
} 
  1. 运行结果
Preparing: INSERT INTO userinfo(userName,userPass,birthday,gender,address) VALUES(?,?,?,?,?); 
Parameters:  李应(String),  liying(String),  2017-09-26  17:42:02.394(Timestamp),  男
(String),  山东聊城(String) 
Updates: 1 
Preparing: SELECT LAST_INSERT_ID() 
Parameters: 
Total: 1 

2.3 VO 类型输入映射

VO 有两种说法,一是 Value Object,二是 View Object,它的作用是把某个指定页面的所有数据封装起来,一个 VO 对象中可以对应数据库中的多张表。PO(persistant object)是持久对象,PO 类与表对应,PO 类中的属性与表的列对应。 例如有学生表 Student 和课程表 course,为学生表定义 PO 类StudentModel,为课程表定义 PO 类 CourseModel。在视图中需要显示学生姓名和课程名称,而学生姓名在学生表中,课程名称在课程表中,因此创建 VO 类将 StudentModel 和 CourseModel 封装在一起。如果将VO 对象传到视图,视图就可以在 VO 对象中既能获取到 Student 表的数据,也能获取到 course表的数据,如下图所示。
在这里插入图片描述
在 MVC 模式中,VO 多用在视图层,用于在视图层与控制层之间传递数据。PO 多用在模型层,用于在模型层与数据库之间传递数据。VO 和 PO 都可以用在控制层与模型层之间传递数据。VO 和 PO 在 MVC 中的作用如下图所示:
在这里插入图片描述
需求:多条件查询用户
针对 VO 类型作为输入映射,现在给出一个需求,要求实现多条件查询用户。可根据用户名、用户性别、订单号或者以上任意组合对用户进行查询,参考查询界面如下图所示,此界面仅用于参考,以控制台作为界面。
在这里插入图片描述
查询条件中的用户名、用户性别在 userInfo 表中,订单号在 order 表中,因此创建一个名称为 UserInfoQueryVO 的 VO 对象,该 VO 对象将 userInfo 表的 PO 和 order 表的 PO 封装在一起,用来在视图上获取用户输入的查询条件。
1. 创建 OrderModel 类
根据 order 表中的列在 cn.itlaobing.mybatis.model 包中创建 OrderModel 类。

public class OrdersModel implements Serializable{ 
private int id; 
  private int userId; 
  private int orderId; 
  private Date createtime; 
  private String memo; 
  //省略 get/set 方法 
} 

2. 创建 UserInfoQueryVO 类
在项目中创建一个新的包,命名为 cn.itlaobing.mybatis.vo,该包用于定义 VO 类。在该包下创建类 UserInfoQueryVO,代码如下:

public class UserInfoQueryVO { 
  //UserInfoModel 的 PO 作为 VO 的属性 
  private UserInfoModel userInfoModel; 
  //OrdersModel 的 PO 作为 VO 的属性 
  private OrdersModel ordersModel; 
//省略 get/set 方法 
} 

3. 配置 Mapper 映射文件

<select id="findByCondition" parameterType="cn.itlaobing.mybatis.vo.UserInfoQueryVO" 
resultType="cn.itlaobing.mybatis.model.UserInfoModel"> 
SELECT * FROM userinfo WHERE userName =#{userInfoModel.userName} AND   
gender=#{userInfoModel.gender} AND id IN(SELECT userId FROM orders   
WHERE id=#{ordersModel.id}) 
</select> 

(1). userInfoModel 和 ordersModel 是 UserInfoQueryVO 的属性
(2). userName 和 gender 是 userInfoModel 的属性
(3). id 是 ordersModel 的属性

4. 定义 Mapper 接口

public List<UserInfoModel>    findByCondition(UserInfoQueryVO userInfoQueryVO)   
throws Exception; 

5. 单元测试

@Test 
public void testUserInfoQueryVo() throws Exception { 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  //创建 IUserInfoMapper 对象,mybatis 自动生成 IUserInfoMapper 的代理对象 
  IUserInfoMapper userInfoMapper = sqlSession.getMapper(IUserInfoMapper.class); 
  //定义查询条件 
  UserInfoQueryVO userInfoQueryVO =new UserInfoQueryVO(); 
  UserInfoModel userInfoModel =new UserInfoModel(); 
  userInfoModel.setUserName("林冲");//多条件查询的用户名是“林冲” 
  userInfoModel.setGender("男");          //多条件查询的性别是“男” 
  OrdersModel ordersModel =new OrdersModel(); 
  ordersModel.setId(1);                            //多条件查询的订单号是“1” 
  userInfoQueryVO.setUserInfoModel(userInfoModel); 
  userInfoQueryVO.setOrdersModel(ordersModel); 
  //执行查询 
  List<UserInfoModel> list = userInfoMapper.findByCondition(userInfoQueryVO); 
  sqlSession.close(); 
  System.out.println(list); 

6. 运行结果

Preparing: SELECT * FROM userinfo WHERE userName =? AND gender=? AND id IN(SELECT userId 
FROM orders WHERE id=?) 
Parameters:  林冲(String),  男(String), 1(Integer) 
Total: 1 
[2--林冲--lichong--1982-11-10--男--河南开封] 

2.4 HashMap 类型输入映射

需求:根据用户名和性别查询用户
1. Mapper 映射配置

<select id="findByHashMap" parameterType="hashmap" 
  resultType="cn.itlaobing.mybatis.model.UserInfoModel"> 
  SELECT * FROM userinfo WHERE userName =#{userName} AND 
  gender=#{gender} 
</select> 

2. Mapper 接口定义

public  List<UserInfoModel>    findByHashMap(HashMap<String, String> hashMap)  throws Exception; 

3. 单元测试

@Test 
public void testFindByHashMap() throws Exception { 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  //  创建 IUserInfoMapper 对象,mybatis 自动生成 IUserInfoMapper 的代理对象 
  IUserInfoMapper userInfoMapper = sqlSession.getMapper(IUserInfoMapper.class); 
  //  定义查询条件 
  HashMap<String, String> hashMap = new HashMap<String, String>(); 
  hashMap.put("userName", "林冲"); 
  hashMap.put("gender", "男"); 
  //  执行查询 
  List<UserInfoModel> list = userInfoMapper.findByHashMap(hashMap); 
  sqlSession.close(); 
  System.out.println(list); 
} 

4. 运行结果

Preparing: SELECT * FROM userinfo WHERE userName =? AND gender=? 
Parameters:  林冲(String),  男(String) 
Total: 1 
[2--林冲--lichong--1982-11-10--男--河南开封] 
  1. hashmap 是 java.util.HashMap 的别名
  2. 映射文件中的 userName 和 gender 是 HashMap 中的键

3 . 输出映射 resultType

输出映射是由 Mapper Statement 的 resultType 属性设置的。所有的输出映射都需要以下两步来完成:

  1. Mapper 映射配置
  2. Mapper 接口定义

Mybatis 的输出映射就是将查询的结果映射为 Java 的对象。Mybatis 可以将查询出的单个数据(如聚合查询)映射为 Java 的简单类型,将查询出的单条记录映射为 POJO 对象,将查询出的多条记录映射为集合。 如果查询单条记录,Mybatis 调用 selectOne()方法,并将查询结果映射为 POJO 对象。如果查询多条记录,Mybatis 调用 selectList()方法,并将查询结果映射为 POJO 的集合。Mybatis调用 selectOne()方法还是 selectList()方法是根据 Mapper 接口中方法的返回值决定的,如果返回值是集合类型,则调用 selectList()方法,如果返回值是 POJO 对象,则调用 selectOne()方法。

3.1 简单类型输出映射

需求:查询 userInfo 表的记录数量
1. Mapper 映射配置

<select id="findUserInfoCount" resultType="int"> 
  select count(1) from userInfo 
</select> 

2. Mapper 接口定义

public int findUserInfoCount() throws Exception; 

3. 单元测试

@Test 
public void testFindUserInfoCount() throws Exception { 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  //  创建IUserInfoMapper对象,mybatis自动生成IUserInfoMapper的代理对象 
  IUserInfoMapper userInfoMapper = sqlSession.getMapper(IUserInfoMapper.class); 
  //  执行查询 
  int count = userInfoMapper.findUserInfoCount(); 
  sqlSession.close(); 
  System.out.println("共有"+count+"个用户"); 
  } 

4. 运行结果

Preparing: select count(1) from userInfo 
Parameters: 
Total: 1 
共有 8 个用户  

3.2 POJO 对象输出映射

需求:根据 id 查询指定的用户,本例同 findUserInfoById。
1. Mapper 映射配置

<select id="findUserInfoById" parameterType="int" 
  resultType="cn.itlaobing.mybatis.model.UserInfoModel"> 
  select * from userInfo where id=#{id} 
</select> 

2. Mapper 接口定义

public UserInfoModel findUserInfoById(int id) throws Exception; 

3. 单元测试

@Test 
public void testFindUserInfoById() throws Exception { 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  //创建 IUserInfoMapper 对象,mybatis 自动生成 IUserInfoMapper 的代理对象 
  IUserInfoMapper userInfoMapper = sqlSession.getMapper(IUserInfoMapper.class); 
  UserInfoModel model = userInfoMapper.findUserInfoById(1); 
  sqlSession.close(); 
  System.out.println(model); 
} 

4. 运行结果

Preparing: SELECT * FROM userInfo WHERE id=? 
Parameters: 1(Integer) 
Total: 1 
1--admin--admin--1980-10-10--男--陕西西安  

3.3 POJO 集合输出映射

需求:查询所有的用户,本例同 findAll。
1. Mapper 映射配置

<select id="findAll" resultType="cn.itlaobing.mybatis.model.UserInfoModel"> 
  select * from userInfo 
</select> 

2. Mapper 接口定义

public List<UserInfoModel> findAll() throws Exception; 

3. 单元测试

@Test 
public void testFindAll() throws Exception { 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  //  创建 IUserInfoMapper 对象,mybatis 自动生成 IUserInfoMapper 的代理对象 
  IUserInfoMapper userInfoMapper = sqlSession.getMapper(IUserInfoMapper.class); 
  List<UserInfoModel> list = userInfoMapper.findAll(); 
  sqlSession.close(); 
  System.out.println(list); 
} 

4. 运行结果

Preparing: SELECT * FROM userInfo 
Parameters: 
Total: 6 

3.4 HashMap 类型输出映射

需求:查询所有的用户。
1. Mapper 映射配置

<select id="findToHashMap" resultType="hashmap"> 
  select * from userinfo 
</select> 

2. Mapper 接口定义

public List<Map<String, String>> findToHashMap() throws Exception; 

3. 单元测试

@Test 
public void testFindToHashMap() throws Exception { 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  //  创建 IUserInfoMapper 对象,mybatis 自动生成 IUserInfoMapper 的代理对象 
  IUserInfoMapper userInfoMapper = sqlSession.getMapper(IUserInfoMapper.class); 
  List<Map<String, String>> list = userInfoMapper.findToHashMap(); 
  sqlSession.close(); 
   System.out.println(list); 
}

4. 运行结果

Preparing: select * from userinfo 
Parameters: 
Total: 6 

(1). 单元测试中的 findToHashMap()方法返回了 list 集合,集合中存储的是 Map<String,String>对象。
(2). list 集合中的每一个 Map<String,String>对象对应表中的一条记录。
(3). Map<String,String>中的键对应表中的列名称,值对应表中列的值。

4 输出映射 resultMap

4.1 resultMap 的作用

Mybatis 可以将查询结果映射为 resultType 指定的 PO 类型,但需要 PO 的属性名称与select 语句查询的列名必须一致才能映射成功。如下图所示,查询结果集中的列名称为 id 和userName,而 PO 类的属性名称也必须是 id 和 userName 就可以映射成功。
在这里插入图片描述

如果执行查询 select id id_,userName userName_ from userInfo,导致 PO 属性名称与查询列名不一致,无法实现映射。此时可以使用 resutlMap 将 PO 的属性名称与查询列名进行映射。如下图所示,resutlMap 中的 property 设置 PO 的属性名称,column 设置查询列名,完成 PO 属性与查询列名映射。
在这里插入图片描述

4.2 定义 resultMap

需求:查询所有用户
1. 定义 resutlMap

<resultMap id="userInfoResultMap" type="cn.itlaobing.mybatis.model.UserInfoModel"> 
  <id column="id" property="id_"/> 
  <result property="userName" column="userName_" /> 
  <result property="userPass" column="userPass_" /> 
  <result property="birthday" column="birthday_" /> 
  <result property="gender" column="gender_" /> 
  <result property="address" column="address_" /> 
</resultMap> 

(1). resutlMap 的 id 属性是 resutlMap 的唯一标识,本例中定义为“userInfoResultMap”
(2). resutlMap 的 id 属性是映射的 POJO 类
(3). id 标签映射主键,result 标签映射非主键
(4). property 设置 POJO 的属性名称,column 映射查询结果的列名称

4.2 使用 resutlMap

2. 使用 resultMap

<select id="findUserInfoResultMap" resultMap="userInfoResultMap"> 
  SELECT id id_,userName userName_,userPass userPass_,birthday birthday_, 
  gender gender_,address address_ FROM userinfo userinfo_ 
</select> 

(1). 本例的输出映射使用的是 resultMap,而非 resultType
(2). resultMap 引用了 userInfoResultMap
3. Mapper 接口定义

public List<UserInfoModel> findUserInfoResultMap() throws Exception; 

4. 单元测试

@Test 
public void testFindUserInfoResultMap() throws Exception { 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  //  创建 IUserInfoMapper 对象,mybatis 自动生成 IUserInfoMapper 的代理对象 
  IUserInfoMapper userInfoMapper = sqlSession.getMapper(IUserInfoMapper.class); 
  List<UserInfoModel> list = userInfoMapper.findUserInfoResultMap(); 
  sqlSession.close(); 
    System.out.println(list); 
} 

5. 运行结果

Preparing: SELECT id id_,userName userName_,userPass userPass_,birthday birthday_, gender   
gender_,address address_ FROM userinfo userinfo_ 
Parameters: 
Total: 6 

5 动态 SQL

5.1 where 和 if

需求:多条件查询用户
下图是多条件查询用户的界面,查询条件可以任意组合。
在这里插入图片描述
可能的查询结果有以下几种

  1. 不输入任何条件
    select * from userInfo
  2. 只输入用户名
    select * from userInfo where userName=#{userName}
  3. 只输入性别
    select * from userInfo where gender=#{gender}
  4. 只输入订单号
    select * from userInfo where id in(select userId from orders where id=#{orderId})
  5. 输入用户名和用户性别
    select * from userInfo where userName=#{userName} and gender=#{gender}
  6. 输入用户名和订单号
    select * from userInfo where userName=#{userName}
    and id in(select userId from orders where id=#{orderId})
  7. 输入用户性别和订单号
    select * from userInfo whre gender=#{gender}
    and id in(select userId from orders where id=#{orderId})
  8. 输入用户名、用户性别和订单号
    select * from userInfo where userName=#{userName} and gender=#{gender}
    and id in(select userId from orders where id=#{orderId})

像这种多条件查询,其中的 where 子句部分需要根据用户选择的查询条件动态拼接。Mybatis 提供了动态 SQL,动态 SQL 是指通过 Mybatis 提供的各种标签实现动态拼接 SQL 语句。
1. Mapper 映射配置

<!--  动态 SQL-多条件查询  --> 
<select id="findUserInfoCondition" parameterType="hashmap"   
resultType="cn.itlaobing.mybatis.model.UserInfoModel"> 
  select * from userInfo 
  <!-- where 标签自动去掉满足条件的第一个 and --> 
  <where> 
    <!--  如果 userName 不为空,则将 userName 拼接到查询条件中  --> 
    <if test="userName!=null"> 
      and userName=#{userName} 
    </if> 
    <!--  如果 gender 不为空,则将 gender 拼接到查询条件中  -->  
    <if test="gender!=null"> 
      and gender=#{gender} 
    </if> 
    <!--  如果 orderId 不为空,则将 orderId 拼接到查询条件中  -->  
    <if test="orderId!=null"> 
      and id in(select userId from orders where id=#{orderId}) 
    </if>  
  </where>  
</select> 

2. Mapper 接口定义

public  List<UserInfoModel>  findUserInfoCondition(HashMap<String,  String>  condition)  throws Exception; 

3. 单元测试

@Test 
public void testFindUserInfoCondition() throws Exception { 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  //  创建 IUserInfoMapper 对象,mybatis 自动生成 IUserInfoMapper 的代理对象 
  IUserInfoMapper userInfoMapper = sqlSession.getMapper(IUserInfoMapper.class); 
  //定义查询条件 
  HashMap<String, String> condition =new HashMap<String, String>(); 
  //此处设置查询条件,例如 condition.put("userName", "林冲"); 
  List<UserInfoModel> list = userInfoMapper.findUserInfoCondition(condition); 
  sqlSession.close(); 
  System.out.println(list); 
} 

如果查询条件为
condition.put(“userName”, “林冲”);
condition.put(“gender”, “女”);
生成的 SQL 语句为
select * from userInfo WHERE userName=? and gender=? and id in(select userId from orders where id=?)
如果查询条件为
condition.put(“userName”, “林冲”);
condition.put(“gender”, “女”);
则生成的 SQL 语句为
select * from userInfo WHERE userName=? and gender=?
如果查询条件为
condition.put(“userName”, “林冲”);
select * from userInfo WHERE userName=?
如果查询条件为空,则生成的 SQL 语句为
select * from userInfo

5.2 foreach

需求:批量删除用户
下图是批量删除用户的界面。
在这里插入图片描述
当用户选中了要删除的用户后,点击批量删除按钮,然后执行 delete from userInfo where id in(1,2,3,4)即可将主键为 1、2、3、4 的用户删除。
本例中表单向服务器提交了多个要删除用户的主键,多个主键可以存储在数组或 List 集合中,然后将数组或 List 集合作为输入映射,传递给 SQL 语句。当向 SQL 语句传递数组或List 集合时,需要使用 foreach 标签解析。

1. Mapper 映射配置

<!--  动态 sql foreach --> 
<delete id="deleteUserInfos" parameterType=" java.util.List "> 
  delete from userInfo 
  <where> 
    <if test=" list !=null and list.size()>0"> 
      <foreach   
        collection="list"   
        item="id"   
        open=" id in ("   
        separator=","   
        close=")"> 
        #{id} 
      </foreach>  
    </if> 
     </where> 
</delete> 

(1). parameterType 的值为 java.util.List 时,参数名为 list
(2). foreach 标签用于迭代数组或集合
(3). collection 属性表示被迭代的数组或集合
(4). item 属性表示被迭代数组或集合中的每一个元素
(5). open 属性表示遍历前拼接的字符串
(6). close 属性表示遍历后拼接的字符串
(7). separator 属性表示每遍历一个元素后的分隔符
(8). 拼接过程如下图所示
在这里插入图片描述

2. Mapper 接口定义

public void deleteUserInfos(List<Integer> list) throws Exception; 

3. 单元测试

@Test 
public void testDeleteUserInfos() throws Exception { 
  SqlSession sqlSession = sqlSessionFactory.openSession(); 
  //  创建 IUserInfoMapper 对象,mybatis 自动生成 IUserInfoMapper 的代理对象 
  IUserInfoMapper userInfoMapper = sqlSession.getMapper(IUserInfoMapper.class); 
  //定义查询条件 
  List<Integer> ids =new ArrayList<Integer>(); 
  ids.add(10); 
  ids.add(11); 
  ids.add(12); 
  ids.add(13); 
  userInfoMapper.deleteUserInfos(ids); 
  sqlSession.close(); 
} 

4. 运行结果

Preparing: delete from userInfo WHERE id in ( ? , ? , ? , ? ) 
Parameters: 10(Integer), 11(Integer), 12(Integer), 13(Integer) 
Updates: 4 

5.3 Sql 片段

Sql 片段是将重复的 Sql 提取出来,进行单独定义的节点。使用时用 include 引用 Sql 片段即可,最终达到 Sql 片段重用的目的。
1. 定义 Sql 片段

<!--  定义 Sql 片段  --> 
<sql id=" queryUserInfoWhere "> 
  <if test="userName!=null"> 
    and userName=#{userName} 
  </if> 
  <if test="gender!=null"> 
    and gender=#{gender} 
  </if> 
  <if test="orderId!=null"> 
    and id in(select userId from orders where id=#{orderId}) 
  </if> 
</sql> 

(1). 节点定义 Sql 片段
(2). 节点的 id 属性是 Sql 片段的唯一标识
2. 含入 Sql 片段

<select id="findUserInfoCondition" parameterType="hashmap" 
  resultType="cn.itlaobing.mybatis.model.UserInfoModel"> 
  select * from userInfo 
  <!--含入 sql 片段--> 
  <where> 
    <include refid=" queryUserInfoWhere  "></include> 
  </where> 
</select> 

(1). 标签用于含入 Sql 片段
(2). refId 是被含入 Sql 片段的 id

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Geek Li

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值