本章节将介绍 <constructor> 标签的用法,该标签用来根据 JavaBean 中不同的构造器创建出 JavaBean 对象。<constructor> 标签需要配合 <idArg> 和 <arg> 标签一起使用,下面通过实例来介绍它的用法:
(1)假设我们定义了如下 UserBean:
public class UserBean {
private Integer userId;
private String name;
private String sex;
private Integer age;
public UserBean(Integer userId, String name) {
this.userId = userId;
this.name = name;
}
// 忽略 getter 和 setter
}(2)XML 结果映射代码如下:
<resultMap id="RESULT_MAP" type="com.hxstrive.mybatis.resultmap.demo5.UserBean"> <!-- constructor 用来映射 UserBean(Integer userId, String name) 构造方法 --> <constructor> <idArg column="user_id" javaType="int" /> <arg column="name" javaType="String" /> </constructor> <result column="sex" jdbcType="VARCHAR" property="sex" /> <result column="age" jdbcType="INTEGER" property="age" /> </resultMap>
上面实例使用 <constructor> 标签匹配 UserBean(Integer userId, String name) 构造器,其中:
idArg:用来映射参数时数据表ID字段
arg:用来映射普通参数
column:用来指定构造器参数对应的数据库表列
javaType:用来指定参数的Java类型,如:int、String
上面定义的 UserBean 中仅有一个 UserBean(Integer userId, String name) 构造器。<resultMap> 默认情况下会根据默认构造器(无参构造器)来创建该JavaBean的对象。如果我们不使用 <constructor> 标签匹配该构造器,将抛出如下错误:
### Cause: org.apache.ibatis.reflection.ReflectionException: Error instantiating class com.hxstrive.mybatis.resultmap.demo5.UserBean with invalid types () or values (). Cause: java.lang.NoSuchMethodException: com.hxstrive.mybatis.resultmap.demo5.UserBean.<init>()
constructor 属性列表:
| 属性 | 描述 |
|---|---|
| column | 数据库中的列名,或者是列的别名。一般情况下,这和传递给 resultSet.getString(columnName) 方法的参数一样。 |
| javaType | 一个 Java 类的完全限定名,或一个类型别名(关于内置的类型别名,可以参考上面的表格)。如果你映射到一个 JavaBean,MyBatis 通常可以推断类型。然而,如果你映射到的是 HashMap,那么你应该明确地指定 javaType 来保证行为与期望的相一致。 |
| jdbcType | JDBC 类型,所支持的 JDBC 类型参见这个表格之前的“支持的 JDBC 类型”。只需要在可能执行插入、更新和删除的且允许空值的列上指定 JDBC 类型。这是 JDBC 的要求而非 MyBatis 的要求。如果你直接面向 JDBC 编程,你需要对可能存在空值的列指定这个类型。 |
| typeHandler | 我们在前面讨论过默认的类型处理器。使用这个属性,你可以覆盖默认的类型处理器。这个属性值是一个类型处理器实现类的完全限定名,或者是类型别名。 |
| select | 用于加载复杂类型属性的映射语句的 ID,它会从 column 属性中指定的列检索数据,作为参数传递给此 select 语句。具体请参考关联元素。 |
| resultMap | 结果映射的 ID,可以将嵌套的结果集映射到一个合适的对象树中。它可以作为使用额外 select 语句的替代方案。它可以将多表连接操作的结果映射成一个单一的 ResultSet。这样的 ResultSet将会将包含重复或部分数据重复的结果集。为了将结果集正确地映射到嵌套的对象树中,MyBatis 允许你 “串联”结果映射,以便解决嵌套结果集的问题。想了解更多内容,请参考下面的关联元素。 |
| name | 构造方法形参的名字。从 3.4.3 版本开始,通过指定具体的参数名,你可以以任意顺序写入 arg 元素。参看上面的解释。 |
(1)MyBatis 配置文件 mybatis-cfg.xml 内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="database.properties"/>
<environments default="MySqlDatabase" >
<environment id="MySqlDatabase" >
<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>
<mappers>
<mapper resource="com\hxstrive\mybatis\resultmap\demo5\UserMapper.xml" />
</mappers>
</configuration>(2)Mapper 接口 UserMapper 内容如下:
package com.hxstrive.mybatis.resultmap.demo5;
import java.util.List;
public interface UserMapper {
/** 查询所有用户信息 */
List<UserBean> findAll();
}(3)Mapper XML 文件 UserMapper 内容如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.hxstrive.mybatis.resultmap.demo5.UserMapper"> <!-- 如果我们没有使用 <constructor> 则会抛出如下错误信息: ### Cause: org.apache.ibatis.reflection.ReflectionException: Error instantiating class com.hxstrive.mybatis.resultmap.demo5.UserBean with invalid types () or values (). Cause: java.lang.NoSuchMethodException: com.hxstrive.mybatis.resultmap.demo5.UserBean.<init>() 抛出这个错误的原因是因为 UserBean 中没有提供默认构造方法 --> <resultMap id="RESULT_MAP" type="com.hxstrive.mybatis.resultmap.demo5.UserBean"> <!-- constructor 用来映射 UserBean(Integer userId, String name) 构造方法 --> <constructor> <idArg column="user_id" javaType="int" /> <arg column="name" javaType="String" /> </constructor> <result column="sex" jdbcType="VARCHAR" property="sex" /> <result column="age" jdbcType="INTEGER" property="age" /> </resultMap> <select id="findAll" resultMap="RESULT_MAP"> select `user_id`, `name`, `sex`, `age` from `user` </select> </mapper>
(4)JavaBean UserBean 内容如下:
package com.hxstrive.mybatis.resultmap.demo5;
public class UserBean {
private Integer userId;
private String name;
private String sex;
private Integer age;
public UserBean(Integer userId, String name) {
this.userId = userId;
this.name = name;
}
// 忽略 getter 和 setter
@Override
public String toString() {
return "UserBean{" +
"userId=" + userId +
", name='" + name + '\'' +
", sex='" + sex + '\'' +
", age=" + age +
'}';
}
}(5)客户端代码如下:
package com.hxstrive.mybatis.resultmap.demo5;
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.InputStream;
import java.util.List;
public class ResultMapDemo5 {
public static void main(String[] args) throws Exception {
// 获取 Mapper 对象
String cfgName = "com/hxstrive/mybatis/resultmap/demo5/mybatis-cfg.xml";
InputStream input = Resources.getResourceAsStream(cfgName);
SqlSessionFactoryBuilder factoryBuilder = new SqlSessionFactoryBuilder();
SqlSessionFactory sqlFactory = factoryBuilder.build(input);
SqlSession sqlSession = sqlFactory.openSession(true);
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<UserBean> userBeanList = userMapper.findAll();
for(UserBean userBean : userBeanList) {
System.out.println("结果:" + userBean);
}
}
}