文章目录
- [1. NONE关闭自动映射](#1. NONE关闭自动映射)
- [2. PARTIAL非嵌套结果映射](#2. PARTIAL非嵌套结果映射)
- [3. FULL全自动映射](#3. FULL全自动映射)
众所周知mybatis中标签< resultMap >是用来处理数据库库字段与java对象属性映射的。通常java对象属性(驼峰格式)与数据库表字段(下划线形式)是一 一对应的情况下,是不用定义< resultMap >标签的,是因为数据库表字段会自动映射到java对象的对应属性上的,比如数据库表一个字段为USER_NAME,java对象对应的属性为userName,默认情况下会自动映射的。
数据库表字段为什么会和java对象属性自动映射的?什么情况下会自动映射?什么情况下不会自动映射?实现这种自动映射行为就是通过< settings >标签下的autoMappingBehavior属性控制的。
xml
<settings>
<setting name="autoMappingBehavior" value="PARTIAL"/>
</settings>
autoMappingBehavior指定 MyBatis 应如何自动映射列到字段或属性。 该属性有3种取值NONE, PARTIAL, FULL, NONE 表示关闭自动映射;PARTIAL 只会自动映射没有定义嵌套结果映射的字段。 FULL 会自动映射任何复杂的结果集(无论是否嵌套)。如不配置,模式是PARTIAL部分映射的。下面分别看下三种情况是如何映射的
1. NONE关闭自动映射
关闭自动映射后,数据库表字段就不会自动映射到java对象属性中,此时就得自定义< resultMap >。
下面以查询用户信息为例,数据库表为USER,对应java类为User
package com.lzj.bean;
java
public class User {
private int id;
private String name;
private int age;
//省略get/set/toString
}
对应数据库表USER为
mybatis配置文件中< settings >配置如下所示
xml
<settings>
<!--设置打印日志工具-->
<setting name="logImpl" value="STDOUT_LOGGING"/>
<--关闭自动映射-->
<setting name="autoMappingBehavior" value="NONE"/>
</settings>
mapper文件对应如下所示
xml
<select id="selectOne" parameterType="int" resultType="com.lzj.bean.User">
select * from user where id=#{id}
</select>
然后通过如下案例执行该mapper对应的SQL
java
public void sqlSessionTest(){
SqlSessionFactory factory = mybatisUtil.getFactory();
SqlSession sqlSession = factory.openSession(true); //true表示自动提交
List<Object> list = sqlSession.selectList("com.lzj.dao.UserDao.selectOne", 2);
System.out.println("输出结果:" + list.get(0));
}
输出结果如下所示,发现该SQL命中了数据库中id=2的一条数据,但是没有映射到user对象上,导致打印出的user对象为null。
java
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Cache Hit Ratio [com.lzj.dao.UserDao]: 0.0
Opening JDBC Connection
Created connection 671187578.
==> Preparing: select * from user where id=?
==> Parameters: 2(Integer)
<== Columns: id, name, age
<== Row: 2, xiaoli, 26
<== Total: 1
输出结果:null
那么在关闭自动映射的情况下如何把查到的数据库表数据映射到java对象user中呢?可以通过下面自定resultMap标签进行手动映射,把mapper文件改成如下方式
xml
<resultMap id="userResultMap" type="com.lzj.bean.User">
<result property="id" column="ID"></result>
<result property="name" column="NAME"></result>
<result property="age" column="AGE"></result>
</resultMap>
<select id="selectOne" parameterType="int" resultMap="userResultMap">
select * from user where id=#{id}
</select>
然后再执行上述案例,输出结果如下所示,打印出的user对象已有值,说明数据库表中数据映射到了java对象user中。
java
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Cache Hit Ratio [com.lzj.dao.UserDao]: 0.0
Opening JDBC Connection
Created connection 953253248.
==> Preparing: select * from user where id=?
==> Parameters: 2(Integer)
<== Columns: id, name, age
<== Row: 2, xiaoli, 26
<== Total: 1
输出结果:User{id=2, name='xiaoli', age=26}
2. PARTIAL非嵌套结果映射
PARTIAL 只会自动映射没有定义嵌套结果映射的字段。什么意思呢,不同于上面案例,一个库表对应一个简单的java对象,如果两个库表对应一个嵌套的java对象,如何进行映射的呢?
比如查询用户名下的车辆,对应的User类为
java
package com.lzj.bean;
import java.util.List;
public class User {
private int id;
private String name;
private int age;
private List<Car> cars;
//省略get/set/toString方法
}
对应的Car类为
package com.lzj.bean;
java
public class Car {
private String name;
private String brand;
//省略get/set/toString方法
}
数据库表USER如下所示
数据库表CAR如下所示
mybatis的配置文件中setting标签改为如下配置
xml
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="autoMappingBehavior" value="PARTIAL"/>
</settings>
mapper文件改为如下所示
java
<select id="selectOne" parameterType="int" resultMap="userResultMap">
select * from user where id=#{id}
</select>
然后运行下面demo
java
public void sqlSessionTest2(){
SqlSessionFactory factory = mybatisUtil.getFactory();
SqlSession sqlSession = factory.openSession(true); //true表示自动提交
List<Object> list = sqlSession.selectList("com.lzj.dao.UserDao.select2", 2);
System.out.println("输出结果:" + list.get(0));
}
输出结果如下所示,输出的user对象中id、name、age都有值,唯独cars没有值,说明mybatis只自动映射没有定义嵌套结果映射的字段,只映射了user对象中最外层的属性的值,没有映射嵌套的CAR数据库表中数据到cars对象中。
java
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Cache Hit Ratio [com.lzj.dao.UserDao]: 0.0
Opening JDBC Connection
Created connection 140778365.
==> Preparing: select u.id,u.name,u.age,c.name,c.brand from user u, car c where u.id=?
==> Parameters: 2(Integer)
<== Columns: id, name, age, name, brand
<== Row: 2, xiaoli, 26, xiaoli, BYD
<== Total: 1
输出结果:User{id=2, name='xiaoli', age=26, cars=null}
那么这种情况下如何把CAR表中数据映射到嵌套的对象cars中呢,也是通过resultMap进行自定义映射,mapper改为如下方式
xml
<resultMap id="userResultMap2" type="com.lzj.bean.User">
<!--由于设置的是非嵌套自动映射,库表USER中数据会自动映射到user对象的id、name、age上,所以此处没有再自定义映射,只指定CAR表中字段数据是如何映射到cars上面的就可以了。-->
<collection property="cars" column="NAME" ofType="com.lzj.bean.Car">
<result property="name" column="NAME"></result>
<result property="brand" column="BRAND"></result>
</collection>
</resultMap>
<select id="select2" resultMap="userResultMap2">
select u.id,u.name,u.age,c.name,c.brand from user u, car c where u.id=#{id}
</select>
然后重新执行上面demo案例结果如下所示,发现user对象中嵌套的cars对象中属性也有值了,映射成功。
java
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Cache Hit Ratio [com.lzj.dao.UserDao]: 0.0
Opening JDBC Connection
Created connection 77215921.
==> Preparing: select u.id,u.name,u.age,c.name,c.brand from user u, car c where u.id=?
==> Parameters: 2(Integer)
<== Columns: id, name, age, name, brand
<== Row: 2, xiaoli, 26, xiaoli, BYD
<== Total: 1
输出结果:User{id=0, name='null', age=0, cars=[Car{name='xiaoli', brand='BYD'}]}
3. FULL全自动映射
FULL 会自动映射任何复杂的结果集(无论是否嵌套)。
还是以上面嵌套映射的为例,把< settings 配置修改为如下所示>
xml
<settings>
<setting name="logImpl" value="STDOUT_LOGGING"/>
<setting name="autoMappingBehavior" value="FULL"/>
</settings>
mapper文件修改为如下所示,直接返回user对象,没有设置resultMap自定义映射
xml
<select id="select3" resultType="com.lzj.bean.User">
select u.id,u.name,u.age,c.name,c.brand from user u, car c where u.id=#{id}
</select>
执行上面案例结果输出显示,即使没有配置resultMap自定义映射,mybatis自动的进行了嵌套结果的映射
java
Logging initialized using 'class org.apache.ibatis.logging.stdout.StdOutImpl' adapter.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
PooledDataSource forcefully closed/removed all connections.
Cache Hit Ratio [com.lzj.dao.UserDao]: 0.0
Opening JDBC Connection
Created connection 520082748.
==> Preparing: select u.id,u.name,u.age,c.name,c.brand from user u, car c where u.id=?
==> Parameters: 2(Integer)
<== Columns: id, name, age, name, brand
<== Row: 2, xiaoli, 26, xiaoli, BYD
<== Total: 1
输出结果:User{id=2, name='null', age=26, cars=[Car{name='xiaoli', brand='BYD'}]}