本章节将介绍 <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); } } }