mybatis映射器之select

select元素是最常用的,也是功能最强大的元素。他的功能就是执行select查询,可以动态设定入参,还可以把resultset的数据转为指定的javabean。

select元素的配置

元素 说明 备注
id 他和mapper的命名空间组合起来必须是唯一的,提供给mybatis调用 如果命名空间和id组合起来不唯一,mybatis将会抛异常
paramterType 入参类型可以是类的全命名,也可以使类的别名(必须是在mybatis中定义好的) 可以选择javabean,map等复杂类型传递参数给sql
parameterMap 废弃 废弃
resultType 返回结果类型,可以是类的全路径,也可以是别名,也可以是八大基础类型 不能和resultMap一起使用
resultMap 返回结果的复杂映射,可以定义复杂映射规则 需要在配置文件中设置映射规则
flushCache 在调用sql后,是否清空之前查询的本地缓存和二级缓存 取值为布尔类型,true/false
useCache 启动二级缓存,是否缓存此次结果 取值为布尔类型,true/false
timeout 设置超时参数,等待超时将抛出异常,单位为秒 默认值是jdbc驱动或连接池设置的秒数
fetchSize 获取记录的总条数设置 默认是jdbc驱动所设置的条数
statementType 选择一种statement,取值为STATEMENT,PREPARED,CallableStatement 默认为PREPARED
resultSetType 这是对JDBC的resultSet接口而言,他的值包括FORWARD_ONLY(游标允许向前访问),SCROLL_SENSITIVE(双向滚动,但不及时更新),SCROLL_INSENSITIVE(双向滚动,并及时跟踪数据库的更新,以便更改resultSet中的数据) 默认值是数据库厂商提供的JDBC驱动所设置的
databaseId 标识数据库厂商 提供多种数据库支持
resultOrdered 嵌套结果集使用 默认值为false
resultSets 适合于多个结果集的情况,它将列出执行SQL后每个结果集的名称,每个名称之间用逗号分隔 很少使用

自动映射

在mybatis的配置文件的settings中有一项配置参数autoMappingBehavior,当它不设置为NONE时,mybatis会提供自动映射的功能,只需要返回的sql列名和javabean的属性一致,mybatis就会帮助我们回填这些字段而无需任何配置。

autoMappingBehavior可以设置三种值。

  • NONE,取消自动映射。
  • PARTIAL,只会自动映射,阿弥有定义嵌套结果集映射的结果集。
  • FULL,会自动映射任意复杂的结果集(无论是否嵌套)。

默认值为PARTIAL。所以在默认情况下,它可以做到当前对象的映射,使用FULL是嵌套映射,在性能上会下降。

如果你的数据库字段是规范命名的,即每个单词都用下划线分隔,POJO采用驼峰命名,那么你也可以设置mapUnderscoreToCamelCase为true,这样就可以实现从数据库到POJO的自动映射了。

入参传递

入参传递的方式有三种,分别是map,注解和javabean。以下分别来演示,数据库配置等见之前的文章。

整个文件结构如下:

1
2
3
4
5
6
7
8
9
src/main/java/
--------------/MybatisSelectMain.java
--------------/com/gavinzh/mybatis/
----------------------------------/modal/MyInfo.java
----------------------------------/MyInfoMapper.java

src/main/resources/
------------------/mybatis_select.xml
------------------/xxx/mybatis_mapper_select.xml

首先先设置一个javabean,作为返回参数也可以作为查询入参MyInfo.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package com.gavinzh.mybatis.modal;

/**
* @author gavin
* @version V1.0
*/
public class MyInfo {
private int id;
private String userName;
private String userAge;

public int getId() {
return id;
}

public void setId(int id) {
this.id = id;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getUserAge() {
return userAge;
}

public void setUserAge(String userAge) {
this.userAge = userAge;
}
}

接下来需要有一个mybatis的配置文件mybatis_select.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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>
<!-- 对事务的管理和连接池的配置 -->
<environments default="development">
<environment id="development">
<transactionManager type="JDBC" />
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost3306/test?useUnicode=true&amp;characterEncoding=UTF-8&amp;zeroDateTimeBehavior=convertToNull&amp;allowMultiQueries=true" />
<property name="username" value="root" />
<property name="password" value="root" />
</dataSource>
</environment>
</environments>

<!-- mapping 文件路径配置 -->
<mappers>
<mapper resource="xxx/mybatis_mapper_select.xml" />
</mappers>
</configuration>

设置了mybatis的配置文件,还需要一个带有sql的mapper配置文件mybatis_mapper_select.xml:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?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.gavinzh.mybatis.MyInfoMapper">
<select id="selectTestByMap" resultType="com.gavinzh.mybatis.modal.MyInfo">
SELECT id ,user_name as userName,user_age as userAge,column_4 as column4 FROM test.my_info
WHERE id = #{id}
</select>

<select id="selectTestByParam" resultType="com.gavinzh.mybatis.modal.MyInfo" >
SELECT id ,user_name as userName,user_age as userAge,column_4 as column4 FROM test.my_info
WHERE id = #{id} OR user_name = #{userName} OR user_age = #{userAge}
</select>

<select id="selectTestByBean" resultType="com.gavinzh.mybatis.modal.MyInfo" >
SELECT id ,user_name as userName,user_age as userAge,column_4 as column4 FROM test.my_info
WHERE id = #{id}
</select>
</mapper>

有了mapper配置文件,mybatis允许我们写一个mapper文件的接口MyInfoMapper.java,有了这个接口,我们就能通过mapper来访问指定sql,而不是通过命名空间+ID的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.gavinzh.mybatis;

import com.gavinzh.mybatis.modal.MyInfo;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

/**
* @author gavin
* @version V1.0
*/
public interface MyInfoMapper {
List<MyInfo> selectTestByMap(Map<String,Object> map);

List<MyInfo> selectTestByParam(@Param("id") int id,@Param("userName") String userName,@Param("userAge") int userAge);

List<MyInfo> selectTestByBean(MyInfo myInfo);
}

有了上边的基础,接下来就可以看看Main方法了,MybatisSelectMain.java:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import com.alibaba.fastjson.JSON;
import com.gavinzh.mybatis.MyInfoMapper;
import com.gavinzh.mybatis.modal.MyInfo;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

/**
* @author gavin
* @version V1.0
*/
public class MybatisSelectMain {
public static void main(String[] args) throws IOException {
//配置
String resource = "mybatis_select.xml";

InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
SqlSession sqlSession = sqlSessionFactory.openSession();


//入参
MyInfo myInfo = new MyInfo();
myInfo.setId(1);
Map<String, Object> parameter = new HashMap<>();
parameter.put("id", 1);


//ibatis方式调用
// map方式
System.out.println(JSON.toJSONString(sqlSession.selectList("com.gavinzh.mybatis.MyInfoMapper.selectTestByMap", parameter)));
// 在ibatis方式中只能通过map代替注解
System.out.println(JSON.toJSONString(sqlSession.selectList("com.gavinzh.mybatis.MyInfoMapper.selectTestByParam", parameter)));
// javabean方式
System.out.println(JSON.toJSONString(sqlSession.selectList("com.gavinzh.mybatis.MyInfoMapper.selectTestByBean", myInfo)));


System.out.println();

//mybatis方式调用
MyInfoMapper mapper = sqlSession.getMapper(MyInfoMapper.class);
// 入参为map
System.out.println(JSON.toJSONString(mapper.selectTestByMap(parameter)));
// 入参为注解方式接入
System.out.println(JSON.toJSONString(mapper.selectTestByParam(2, "", 22)));
// 入参为javabean
System.out.println(JSON.toJSONString(mapper.selectTestByBean(myInfo)));
}
}

总结

  • 使用map传递参数。因为map导致业务可读性丧失,从而导致后续扩展和维护困难,我们应该在实际的应用中放弃这种传递参数的方式。
  • 使用注解@Param传递参数。这种方式收到参数个数的影响,当入参大于5个时,调用起来比较困难。
  • 当入参大于5个或者以后有可能扩展到5个以上,建议使用javabean方式。

高级结果映射

当我们需要在返回的结果中有嵌套或者返回的结果是组合形式的,那就需要高级结果映射了,具体的映射方法参考官网。

Mybatis高级结果映射