封装输出结果: MyBatis执行sql语句,得到ResultSet, 转为java对象。
1.resultType
数据库表t_user
数据库表的字段用的是下划线分隔单词, 而对象属性用的是驼峰命名, 所以要在mybatis的主配置文件中开启驼峰命名映射
<configuration>
<settings>
<!--开启驼峰命名映射-->
<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>
</configuration>
resultType属性: 在执行select时使用, 作为标签的属性出现的。表示结果类型 , mysql执行sql语句, 得到java对象的类型。 它的值有两种
- java类型的全限定名称
- 使用别名
1.简单类型
xml
<select id="getAllUserCount" resultType="int">
<!--int是java.lang.Integer的别名-->
select count(*) from t_user
</select>
dao
int getAllUserCount();
测试
System.out.println("userCount="+userDao.getAllUserCount());
2.对象类型
xml
<select id="getUserById" resultType="com.limi.entity.User">
<!--要执行的 sql 语句-->
select * from t_user where id = #{id}
</select>
<!--
resultType:现在使用java类型的全限定名称。 表示的意思 mybatis执行sql,把ResultSet中的数据转为User类型的对象。 mybatis会做以下操作:
1. 调用com.limi.entity.User的无参数构造方法(如果有全参构造方法则调用全参构造方法),创建对象。
User user = new User(); //使用反射创建对象
2. 同名的列赋值给同名的属性。
user.setId( rs.getInt("id"));
user.setUserName(rs.getString("user_name"));
user.setPassWord(rs.getString("pass_word"))
3. 得到java对象, 如果dao接口返回值是List集合, mybatis把user对象放入到List集合。
-->
dao
User getUserById(int id);
测试
User user = userDao.getUserById(2);
System.out.println(user);
/*所以执行 User user = userDao.getUserById(2); 得到 数据库表t_user中 id=2这行数据, 这行数据的列值, 赋值给了user对象的属性。 */
注意要点:
1.对象的类名可以和数据库表名毫无关系, 但是属性名必须要和数据库的字段名相对应, 否则mybatis无法完成赋值.
2.如果类没有全参构造方法, 则类的属性必须要有set方法, 否则mybatis无法完成赋值.
3.如果属性名就是和数据库表字段名(列名)不一致, 则我们可以采用取别名的方式来解决, 主要有两种方式, 一种是在sql语句中取别名, 另一种就是使用resultMap来编写属性和列名的映射关系
第一种. 在sql语句中取别名
xml
<select id="getMyUserById" resultType="com.limi.entity.MyUser">
<!--要执行的 sql 语句-->
select id as myId, user_name as myUserName, pass_word as myPassWord from t_user where id = #{id}
</select>
MyUser
package com.limi.entity;
public class MyUser {
private Integer myId;
private String myUserName;
private String myPassWord;
@Override
public String toString() {
return "MyUser{" +
"myId=" + myId +
", myUserName='" + myUserName + '\'' +
", myPassWord='" + myPassWord + '\'' +
'}';
}
public Integer getMyId() {
return myId;
}
public void setMyId(Integer myId) {
this.myId = myId;
}
public String getMyUserName() {
return myUserName;
}
public void setMyUserName(String myUserName) {
this.myUserName = myUserName;
}
public String getMyPassWord() {
return myPassWord;
}
public void setMyPassWord(String myPassWord) {
this.myPassWord = myPassWord;
}
}
dao
MyUser getMyUserById(Integer id);
测试
MyUser myUser = userDao.getMyUserById(2);
System.out.println(myUser);
第二种方法稍后介绍
3.Map类型
sql 的查询结果作为 Map 的 key 和 value, 推荐使用 Map<Object,Object>。
注意:Map 作为接口返回值,sql 语句的查询结果最多只能有一条记录。大于一条记录会发生报错.
<select id="getUserMapById" resultType="java.util.HashMap">
select * from t_user where id = #{id}
</select>
dao
Map<Object, Object> getUserMapById(Integer id);
测试
Map<Object, Object> map = userDao.getUserMapById(2);
System.out.println(map.toString());
2.resultMap
resultMap 可以自定义 sql 的结果和 java 对象属性的映射关系。更灵活的把列值赋值给指定属性。常用在列名和 java 对象属性名不一样的情况, 这也就是我要介绍的属性名和数据库表字段名不一致时的第二种解决办法。
使用方式:
1.先定义 resultMap,指定列名和属性的对应关系。
2.在 < select > 中把 resultType 替换为 resultMap。
xml
<!-- 创建 resultMap
id:自定义的唯一名称,在<select>使用
type:期望转为的 java 对象的全限定名称或别名
-->
<resultMap id="userMap" type="com.limi.entity.MyUser">
<!-- column数据库字段名, property类的属性名 -->
<!--主键字段使用id标签, 非主键字段使用 result标签-->
<id column="id" property="myId" />
<result column="user_name" property="myUserName"/>
<result column="pass_word" property="myPassWord" />
</resultMap>
<select id="getAllMyUser" resultMap="userMap">
select * from t_user
</select>
dao
List<MyUser> getAllMyUser();
测试
List<MyUser> myUserList = userDao.getAllMyUser();
myUserList.forEach(myUser -> System.out.println(myUser));
3.自定义别名
每个标签中都使用类的全限定名称, 有点长, 可能有些人会觉得麻烦, 所以mybatis支持使用< typeAliases >标签给类的全限定名称取别名.
自定义别名的步骤:
1)在mybatis主配置文件,使用 typeAliases标签声明别名
2)在mapper文件中, resultType=“别名”
< typeAliases >里有< typeAlias >和 < package >两个子标签
1. < typeAlias >标签
mybatis的主配置文件中加入如下配置代码(注意不是mapper文件中加)
<configuration>
<typeAliases>
<!-- com.limi.entity.User 取个别名叫MyUser-->
<typeAlias type="com.limi.entity.User" alias="MyUser"></typeAlias>
</typeAliases>
</configuration>
xml
<select id="getMyUserList" resultType="MyUser">
select * from t_user
</select>
dao
List<User> getMyUserList();
测试
List<User> myUserList = userDao.getMyUserList();
myUserList.forEach(myUser -> System.out.println(myUser));
2. < package > 标签
也可以使用< package >指定一个包名,MyBatis 会在包名下面搜索需要的 Java Bean,比如:
<typeAliases>
<package name="com.limi.entity"/>
</typeAliases>
a. 当这样配置时,每一个在包 com.limi.entity中的 Java Bean,在没有注解的情况下,会使用 Bean 的首字母小写的非限定类名来作为它的别名。 比如 com.limi.entity.User 的别名为user, 缺点是如果不同包中有相同的类名, 可能会发生错误.
xml
<select id="getMyUserList" resultType="user">
select * from t_user
</select>
dao
List<User> getMyUserList();
测试
List<User> myUserList = userDao.getMyUserList();
myUserList.forEach(myUser -> System.out.println(myUser));
b. 若有注解,则别名为其注解值, 见下面的例子:
@Alias("oneUser") //那么别名就是myUser
public class User{
...
}
xml
<select id="getMyUserList" resultType="oneUser">
select * from t_user
</select>
dao
List<User> getMyUserList();
测试
List<User> myUserList = userDao.getMyUserList();
myUserList.forEach(myUser -> System.out.println(myUser));
最后说一句, 其实真实开发中还是更推荐使用类的全限定名称, 这样可读性会更好一些, 也不容易出错.