MyBatis的输入和输出映射,通过parameterType完成输入映射,通过resultType和resultMap完成输出映射。

1、输入映射parameterType

  输入映射中,可以给出类的全名,也可以给出类的别名,但是别名必须是MyBatis内部定义或者自定义的,可以选择JavaBean、Map等简单的参数类型传递给SQL。

1.1基本类型

  基本类型可以使用别名的方式,如果想要查看常见的 Java 类型内建的相应的类型别名,点击这里,它们都是不区分大小写的。(具体的测试方法可以看我上一篇写的博客)

1
2
3
<delete id="deleteUserById" parameterType="Integer">
delete from user where u_id = #{id}
</delete>

1.2自定义对象

  输入类型还可以为自定义的对象,在书写Sql语句获取数值的时候,可以使用”#{对象字段名}”的方式取得数值。以下就是通过输入一个自定义对象的方式将参数传递给SQL,实现修改指定用户名的功能。(具体的测试方法可以看我上一篇写的博客)

1
2
3
<update id="updateUser" parameterType="io.xiezhenyu98.bean.User">
update user set u_username = #{u_username} where u_id=#{u_id}
</update>

1.3自定义包装类

  输入类型还可以为自定义的包装类,在书写SQL语句获取数值的时候,可以使用”#{包装类字段.被包装类字段}”的方法获得数值。
UserVo.java包装类

1
2
3
4
5
6
7
8
9
10
11
12
public class UserVo {
//包装类
//需要全部的user对象信息
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
//需要表B的id name属性
}

UserMapper.java接口

1
2
//通过UserVo id查询一个用户
public User selectUserByUserVoId(UserVo vo);

UserMapper.xml映射文件

1
2
3
4
<!-- 查找用户UserVo -->
<select id="selectUserByUserVoId" parameterType="UserVo" resultType="user">
select * from user where u_id = #{user.u_id}
</select>

测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Test
public void Test3() throws IOException {
String resource = "sqlMapConfig.xml";
//读取配置文件
InputStream in = Resources.getResourceAsStream(resource);
//需要sqlSessionFactoryBulider
SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
//创建sqlSessionFactory
SqlSessionFactory ssf = ssfb.build(in);
//生产一个sqlSession
SqlSession session = ssf.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
UserVo vo = new UserVo();
User user = new User();
user.setU_id(1);
vo.setUser(user);
User resultUser = mapper.selectUserByUserVoId(vo);
System.out.println(resultUser);
}

结果

1
User [u_id=1, u_username=老王, u_password=123, u_sex=1, u_createTime=null, u_cid=1]

2、输出映射resultType、resultMap

2.1resultType

  resultType,定义类的全路径,在允许自动匹配的情况下,结果集将通过JavaBean的规范映射,数据库中表的字段名和JavaBean中的字段名对应,或定义为int、double、float、map等参数,也可以使用别名,但是要符合别名的规范,且不能和resultMap同时使用。resultType是常用的参数之一,比如统计总条数时可以把它设置为int。

2.1.1基本类型

  输出映射的基本类型和输入映射的基本类型一样,可以使用别名的方式,如果想要查看常见的 Java 类型内建的相应的类型别名,点击这里,它们都是不区分大小写的。以下是查询用户总数返回Integer的返回值。

1
2
3
4
<!-- 查询用户总条数 -->
<select id="selectUserCount" resultType="Integer">
select count(*) from user
</select>

2.1.2自定义类型

输出映射的自定义类型(具体的测试方法可以看我上一篇写的博客)

1
2
3
4
<!-- 查找用户 -->
<select id="selectUserById" parameterType="Integer" resultType="user">
select * from user where u_id = #{id}
</select>

2.2resultMap

  resultMap,它是映射集的引用,将执行强大的映射功能。可以使用resultType、resultMap的其中一个,resultMap能提供自定义映射规则的机会,数据库中表的字段名和JavaBean中的字段名不对应,则需要添加自定义映射。resultMap是MyBatis最复杂的元素,可以配置映射规则、级联、typeHandler等等。

2.2.1Bean对象字段与数据库中字段不匹配

创建Country实例,实例中Country的id与数据库中的不匹配(数据库中的为c_id)

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
public class Country {
private Integer id;
private String c_countryname;
private String c_capital;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getC_countryname() {
return c_countryname;
}
public void setC_countryname(String c_countryname) {
this.c_countryname = c_countryname;
}
public String getC_capital() {
return c_capital;
}
public void setC_capital(String c_capital) {
this.c_capital = c_capital;
}
@Override
public String toString() {
return "Country [id=" + id + ", c_countryname=" + c_countryname + ", c_capital=" + c_capital + "]";
}
}

创建CountryMapper接口

1
2
3
4
5
6
import java.util.List;
import com.siliedu.bean.Country;
public interface CountryMapper {
//查询所有
public List<Country> selectAll();
}

创建CountryMapper映射文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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.siliedu.mapper.CountryMapper">
<!-- 查询所有 -->
<!-- country为resultMap起一个名字 -->
<resultMap type="Country" id="country">
<!-- id为javaBean中的字段,c_id为数据库中的字段,两个字段不匹配 -->
<result property="id" column="c_id"/>
</resultMap>
<!-- country为使用名为country的resultMap -->
<select id="selectAll" resultMap="country">
select * from country
</select>
</mapper>

测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void Test5() throws IOException {
String resource = "sqlMapConfig.xml";
//读取配置文件
InputStream in = Resources.getResourceAsStream(resource);
//需要sqlSessionFactoryBulider
SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
//创建sqlSessionFactory
SqlSessionFactory ssf = ssfb.build(in);
//生产一个sqlSession
SqlSession session = ssf.openSession();
CountryMapper mapper = session.getMapper(CountryMapper.class);
List<Country> list = mapper.selectAll();
for(Country c : list) {
System.out.println(c);
}
}

结果

1
2
3
4
Country [id=1, c_countryname=中国, c_capital=北京]
Country [id=3, c_countryname=美国, c_capital=华盛顿]
Country [id=4, c_countryname=英国, c_capital=伦敦]
Country [id=5, c_countryname=日本, c_capital=东京]

在这里如果我们将resultMap改成resultType的话,id将查询不到。

1
2
3
<select id="selectAll" resultType="country">
select * from country
</select>

结果

1
2
3
4
Country [id=null, c_countryname=中国, c_capital=北京]
Country [id=null, c_countryname=美国, c_capital=华盛顿]
Country [id=null, c_countryname=英国, c_capital=伦敦]
Country [id=null, c_countryname=日本, c_capital=东京]

2.2.2关联查询

2.2.2.1一对一

  一个用户只对应一个国家。(在单表查询的时候,javaBean对象的字段和数据库字段一致的时候可以省略但在多表查询的时候,我们要查询什么字段,就必须把什么字段列在映射文件上)
UserVo包装类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class UserVo extends User{
private Country country;
public Country getCountry() {
return country;
}
public void setCountry(Country country) {
this.country = country;
}
@Override
public String toString() {
return "UserVo [country=" + country + ", getU_id()=" + getU_id() + ", getU_username()=" + getU_username()
+ ", getU_sex()=" + getU_sex() + "]";
}
}

UserMapper接口

1
2
//查询所有用户的包装类
public List<UserVo> selectAllUserVo();

UserMapper.xml映射文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!-- 查询所有用户的包装类 -->
<resultMap type="UserVo" id="uservolist">
<!-- 在单表查询的时候,javaBean对象的字段和数据库字段一致的时候可以省略
但在多表查询的时候,我们要查询什么字段,就必须把什么字段列上去 -->
<id property="u_id" column="u_id"/>
<id property="u_username" column="u_username"/>
<id property="u_sex" column="u_sex"/>
<association property="country" javaType="Country">
<result property="id" column="c_id"/>
<result property="c_countryname" column="c_countryname"/>
</association>
</resultMap>
<select id="selectAllUserVo" resultMap="uservolist">
select u.u_id,u.u_username,u.u_sex,c.c_id,c.c_countryname from user u left join country c on u.u_cid=c.c_id
</select>

测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void Test6() throws IOException {
String resource = "sqlMapConfig.xml";
//读取配置文件
InputStream in = Resources.getResourceAsStream(resource);
//需要sqlSessionFactoryBulider
SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
//创建sqlSessionFactory
SqlSessionFactory ssf = ssfb.build(in);
//生产一个sqlSession
SqlSession session = ssf.openSession();
UserMapper mapper = session.getMapper(UserMapper.class);
List<UserVo> list = mapper.selectAllUserVo();
for(UserVo userVo : list) {
System.out.println(userVo);
}
}

结果:查询到了所有的用户,以及用户的国家,没有国家的用户也查询到了

1
2
3
4
5
6
7
8
9
10
11
12
UserVo [country=Country [id=1, c_countryname=中国, c_capital=null], getU_id()=1, getU_username()=老王, getU_sex()=1]
UserVo [country=Country [id=3, c_countryname=美国, c_capital=null], getU_id()=2, getU_username()=jack, getU_sex()=1]
UserVo [country=Country [id=3, c_countryname=美国, c_capital=null], getU_id()=3, getU_username()=alice, getU_sex()=0]
UserVo [country=Country [id=1, c_countryname=中国, c_capital=null], getU_id()=4, getU_username()=王司机, getU_sex()=1]
UserVo [country=Country [id=4, c_countryname=英国, c_capital=null], getU_id()=5, getU_username()=anna, getU_sex()=0]
UserVo [country=Country [id=1, c_countryname=中国, c_capital=null], getU_id()=6, getU_username()=李师傅, getU_sex()=1]
UserVo [country=Country [id=5, c_countryname=日本, c_capital=null], getU_id()=7, getU_username()=漩涡鸣人, getU_sex()=1]
UserVo [country=Country [id=5, c_countryname=日本, c_capital=null], getU_id()=8, getU_username()=娜美, getU_sex()=0]
UserVo [country=Country [id=1, c_countryname=中国, c_capital=null], getU_id()=9, getU_username()=王五, getU_sex()=1]
UserVo [country=null, getU_id()=10, getU_username()=老赵, getU_sex()=null]
UserVo [country=null, getU_id()=11, getU_username()=老孙, getU_sex()=null]
UserVo [country=null, getU_id()=12, getU_username()=98k, getU_sex()=null]
2.2.2.1一对多

一个国家有多个用户。
CountryVo包装类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.List;
public class CountryVo extends Country{
//需要维护一个User集合
private List<User> userList;
public List<User> getUserList() {
return userList;
}
public void setUserList(List<User> userList) {
this.userList = userList;
}
@Override
public String toString() {
return "CountryVo [userList=" + userList + ", toString()=" + super.toString() + "]";
}
}

CountryMapper接口

1
2
//查询所有的CountryVo
public List<CountryVo> selectAllCountryVo();

CountryMapper映射文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!-- 查询所有的CountryVo -->
<resultMap type="CountryVo" id="countryvo">
<id property="id" column="c_id"/>
<result property="c_countryname" column="c_countryname"/>
<result property="c_capital" column="c_capital"/>
<!-- 一对多关系 -->
<collection property="userList" ofType="User">
<id property="u_id" column="u_id"/>
<result property="u_username" column="u_username"/>
</collection>
</resultMap>
<select id="selectAllCountryVo" resultMap="countryvo">
select
c.c_id,
c.c_countryname,
c.c_capital,
u.u_id,
u.u_username
from country c
left join
user u on
u.u_cid=c.c_id
</select>

测试方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test
public void Test7() throws IOException {
String resource = "sqlMapConfig.xml";
//读取配置文件
InputStream in = Resources.getResourceAsStream(resource);
//需要sqlSessionFactoryBulider
SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
//创建sqlSessionFactory
SqlSessionFactory ssf = ssfb.build(in);
//生产一个sqlSession
SqlSession session = ssf.openSession();
CountryMapper mapper = session.getMapper(CountryMapper.class);
List<CountryVo> list = mapper.selectAllCountryVo();
for(CountryVo countryVo : list) {
System.out.println(countryVo);
}
}

结果:查询出了,一个国家有几个用户

1
2
3
4
CountryVo [userList=[User [u_id=1, u_username=老王, u_password=null, u_sex=null, u_createTime=null, u_cid=null], User [u_id=4, u_username=王司机, u_password=null, u_sex=null, u_createTime=null, u_cid=null], User [u_id=6, u_username=李师傅, u_password=null, u_sex=null, u_createTime=null, u_cid=null], User [u_id=9, u_username=王五, u_password=null, u_sex=null, u_createTime=null, u_cid=null]], toString()=Country [id=1, c_countryname=中国, c_capital=北京]]
CountryVo [userList=[User [u_id=2, u_username=jack, u_password=null, u_sex=null, u_createTime=null, u_cid=null], User [u_id=3, u_username=alice, u_password=null, u_sex=null, u_createTime=null, u_cid=null]], toString()=Country [id=3, c_countryname=美国, c_capital=华盛顿]]
CountryVo [userList=[User [u_id=5, u_username=anna, u_password=null, u_sex=null, u_createTime=null, u_cid=null]], toString()=Country [id=4, c_countryname=英国, c_capital=伦敦]]
CountryVo [userList=[User [u_id=7, u_username=漩涡鸣人, u_password=null, u_sex=null, u_createTime=null, u_cid=null], User [u_id=8, u_username=娜美, u_password=null, u_sex=null, u_createTime=null, u_cid=null]], toString()=Country [id=5, c_countryname=日本, c_capital=东京]]