本教程源码请访问:tutorial_demo
通过前面的学习我们对MyBatis进行单表的CRUD操作,已经有了一个基本的了解,在前面的学习中MyBatis持久层接口的映射配置文件涉及很多参数,下面我们就学习一下这些参数的基本使用。
一、parameterType
MyBatisSQL语句传参,使用标签的parameterType属性来设定。这个属性的取值可以是基本数据类型,String类型,实体类类型(pojo类),也可以是自定义的类类型(一般数据库表有对应的实体类,自定义的类类型不和数据库表对应,通常用来传递综合的查询条件)。
1.1、注意事项
基本类型和String可以直接写类型名称,也可以使用全类名(例如:java.lang.String)。MyBatis在加载时默认已经把常用的数据类型注册了别名,从而在使用时我们可以不写包名,关于别名,请看下面的表格(来自MyBatis官网)。
实体类类型(pojo类),目前只能使用全限定类名。MyBatis在加载时默认没有为实体类注册别名,所以必须写全限定类名(后面的教程会将到如何注册实体类的别名)。
![0934d5f573d7556bb321aca994afd760.png](https://i-blog.csdnimg.cn/blog_migrate/e8b682d96eba6f64fde60fa59c695bd5.jpeg)
1.2、传递自定义类对象
一般数据库表有对应的实体类,自定义的类类型不和数据库表对应,通常用来传递综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
1.2.1 编写QueryVo
这个类在org.codeaction.domain包下
package org.codeaction.domain;
public class QueryVo {
private User user;
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@Override
public String toString() {
return "QueryVo{" +
"user=" + user +
'}';
}
}
1.2.2 在持久层接口IUserDao中添加相应方法
List<User> findUserByVo(QueryVo vo);
1.2.3 在持久层接口的映射配置文件IUserDao.xml添加配置
<select id="findUserByVo"
parameterType="org.codeaction.domain.QueryVo"
resultType="org.codeaction.domain.User">
<!-- 由于username在user属性中,所以前面一定要加上user -->
select * from user where username like #{user.username}
</select>
1.2.4 修改测试类MyBatisTest
@Test
public void testFindByQueryVo() {
QueryVo vo = new QueryVo();
User user = new User();
user.setUsername("%王%");
vo.setUser(user);
IUserDao userDao = session.getMapper(IUserDao.class);
List<User> list = userDao.findUserByVo(vo);
list.forEach(System.out::println);
}
运行测试方法,控制台输出如下:
User{id=41, username='王一', birthday=Tue Dec 27 17:47:08 CST 2011, sex='男', address='北京'}
User{id=42, username='王二', birthday=Sat Mar 12 15:09:37 CST 2011, sex='女', address='上海'}
User{id=46, username='老王', birthday=Sat Aug 07 17:37:26 CST 1999, sex='女', address='拉萨'}
二、resultType
resultType属性可以指定结果集的类型,它支持基本数据类型和实体类类型。
resultType和parameterType一样,如果注册过类型别名,可以直接使用别名。没有注册过的必须使用全限定类名(后面的教程会将到如何注册实体类的别名)。
当是实体类名称时,实体类中的属性名称必须和查询语句中的列名保持一致,否则无法实现封装。
2.1、基本类型
2.1.1、持久层接口IUserDao中的方法
Integer findTotal();
2.1.2、持久层接口的映射配置文件IUserDao.xml中的配置
<!-- <select id="findTotal" resultType="java.lang.Integer"> -->
<!-- 我们这里使用了Integer类型的别名,没有使用全限定类名 -->
<select id="findTotal" resultType="int">
select count(id) from user
</select>
2.2、实体类类型
2.2.1、持久层接口IUserDao中的方法
List<User> findAll();
2.2.2、持久层接口的映射配置文件IUserDao.xml中的配置
<select id="findAll" resultType="org.codeaction.domain.User">
select * from user
</select>
2.3、特殊情况
在这种情况下,实体类属性和数据库表的列名不一致。
2.3.1、修改实体类User
package org.codeaction.domain;
import java.io.Serializable;
import java.util.Date;
public class User implements Serializable {
//属性名和列名不一致
private Integer userId;
private String userName;
private Date userBirthday;
private String userSex;
private String userAddress;
public Integer getUserId() {
return userId;
}
public void setUserId(Integer userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Date getUserBirthday() {
return userBirthday;
}
public void setUserBirthday(Date userBirthday) {
this.userBirthday = userBirthday;
}
public String getUserSex() {
return userSex;
}
public void setUserSex(String userSex) {
this.userSex = userSex;
}
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
@Override
public String toString() {
return "User{" +
"userId=" + userId +
", userName='" + userName + ''' +
", userBirthday=" + userBirthday +
", userSex='" + userSex + ''' +
", userAddress='" + userAddress + ''' +
'}';
}
}
2.3.2、持久层接口IUserDao
package org.codeaction.dao;
import org.codeaction.domain.User;
import java.util.List;
public interface IUserDao {
//查询所有用户
List<User> findAll();
}
2.3.3、持久层接口的映射配置文件IUserDao.xml
<?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="org.codeaction.dao.IUserDao">
<select id="findAll" resultType="org.codeaction.domain.User">
select * from user
</select>
</mapper>
2.3.4、测试类
package org.codeaction.test;
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 org.codeaction.dao.IUserDao;
import org.codeaction.domain.User;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
public class MyBatisTest {
private InputStream in;
private SqlSession session;
@Before
public void init() throws IOException {
//读取配置文件
in = Resources.getResourceAsStream("SqlMapConfig.xml");
//创建SqlSessionFactory工厂
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = builder.build(in);
//使用工厂生产SqlSession对象
session = factory.openSession();
}
@After
public void destroy() throws IOException {
//提交事务
session.commit();
//释放资源
session.close();
in.close();
}
@Test
public void testFindAll() {
IUserDao userDao = session.getMapper(IUserDao.class);
List<User> users = userDao.findAll();
users.forEach(System.out::println);
}
}
运行测试方法,控制台输出如下
User{userId=null, userName='王一', userBirthday=null, userSex='null', userAddress='null'}
User{userId=null, userName='王二', userBirthday=null, userSex='null', userAddress='null'}
User{userId=null, userName='老李', userBirthday=null, userSex='null', userAddress='null'}
User{userId=null, userName='Max', userBirthday=null, userSex='null', userAddress='null'}
User{userId=null, userName='老王', userBirthday=null, userSex='null', userAddress='null'}
User{userId=null, userName='John', userBirthday=null, userSex='null', userAddress='null'}
User{userId=null, userName='Lucy', userBirthday=null, userSex='null', userAddress='null'}
User{userId=null, userName='张三', userBirthday=null, userSex='null', userAddress='null'}
由于实体类属性和数据库表的列名不一致,导致查询出的数据为null;
mysql在windows系统中不区分大小写,所以userName有值。
2.3.5、修改映射配置
<?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="org.codeaction.dao.IUserDao">
<select id="findAll" resultMap="org.codeaction.domain.User">
select
id as userId,
username as userName,
birthday as userBirthday,
sex as userSex,
address as userAddress
from
user
</select>
</mapper>
运行测试方法,控制台输出如下
User{userId=41, userName='王一', userBirthday=Tue Dec 27 17:47:08 CST 2011, userSex='男', userAddress='北京'}
User{userId=42, userName='王二', userBirthday=Sat Mar 12 15:09:37 CST 2011, userSex='女', userAddress='上海'}
User{userId=43, userName='老李', userBirthday=Wed Mar 14 11:34:34 CST 2012, userSex='女', userAddress='天津'}
User{userId=45, userName='Max', userBirthday=Tue May 04 12:04:06 CST 2010, userSex='男', userAddress='西宁'}
User{userId=46, userName='老王', userBirthday=Sat Aug 07 17:37:26 CST 1999, userSex='女', userAddress='拉萨'}
User{userId=48, userName='John', userBirthday=Mon Jan 08 11:44:00 CST 1990, userSex='女', userAddress='广州'}
User{userId=50, userName='Lucy', userBirthday=Wed Dec 03 20:09:32 CST 2008, userSex='m', userAddress='哈尔滨'}
User{userId=58, userName='张三', userBirthday=Fri May 15 18:50:04 CST 2020, userSex='男', userAddress='南昌'}
能够查询出结果,如果查询的SQL语句特别多,都使用别名会很麻烦,接下来为了解决这个问题,我们看一下resultMap。
三、resultMap
resultMap 标签可以建立查询的列名和实体类的属性名称不一致时建立对应关系。从而实现封装。
3.1、修改持久层接口的映射配置文件IUserDao.xml
<?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="org.codeaction.dao.IUserDao">
<!--
resultMap标签建立User实体和数据库表的对应关系;
id属性:给定一个唯一标识,是给查询select标签引用用的;
type属性:指定实体类的全限定类名。
-->
<resultMap id="userMap" type="org.codeaction.domain.User">
<!--
id标签:用于指定主键字段
result标签:用于指定非主键字段
column属性:用于指定数据库列名
property属性:用于指定实体类属性名称
-->
<id property="userId" column="id" />
<result property="userName" column="username" />
<result property="userBirthday" column="birthday" />
<result property="userSex" column="sex" />
<result property="userAddress" column="address" />
</resultMap>
<!--
resultMap属性用来引用上面配置的resultMap,值为上面的resultMap的id
-->
<select id="findAll" resultMap="userMap">
select * from user
</select>
</mapper>
3.2、测试
运行测试方法,控制台输出如下
User{userId=41, userName='王一', userBirthday=Tue Dec 27 17:47:08 CST 2011, userSex='男', userAddress='北京'}
User{userId=42, userName='王二', userBirthday=Sat Mar 12 15:09:37 CST 2011, userSex='女', userAddress='上海'}
User{userId=43, userName='老李', userBirthday=Wed Mar 14 11:34:34 CST 2012, userSex='女', userAddress='天津'}
User{userId=45, userName='Max', userBirthday=Tue May 04 12:04:06 CST 2010, userSex='男', userAddress='西宁'}
User{userId=46, userName='老王', userBirthday=Sat Aug 07 17:37:26 CST 1999, userSex='女', userAddress='拉萨'}
User{userId=48, userName='John', userBirthday=Mon Jan 08 11:44:00 CST 1990, userSex='女', userAddress='广州'}
User{userId=50, userName='Lucy', userBirthday=Wed Dec 03 20:09:32 CST 2008, userSex='m', userAddress='哈尔滨'}
User{userId=58, userName='张三', userBirthday=Fri May 15 18:50:04 CST 2020, userSex='男', userAddress='南昌'}