mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心。
以下测试方法需要在测试类内运行
public class UserMapperTest extends TestCase {
private SqlSessionFactory sqlSessionFactory;
@Override
protected void setUp() throws Exception {
// mybatis配置文件
String resource = "mybatisConfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 使用SqlSessionFactoryBuilder创建sessionFactory
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
//测试方法
}
parameterType(输入类型)
1、传递简单类型
#{}与${}
#{}实现的是向prepareStatement中的预处理语句中设置参数值,sql语句中#{}表示一个占位符即"?"。
<!-- 根据id查询用户信息 -->
<select id="findUserById" parameterType="int" resultType="user">
select * from user where id = #{id}
</select>
使用占位符#{}可以有效防止sql注入,在使用时不需要关心参数值的类型,mybatis会自动进行java类型和jdbc类型的转换。#{}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
${}和#{}不同,通过${}可以将parameterType 传入的内容拼接在sql中且不进行jdbc类型转换, ${}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,${}括号中只能是value。使用${}不能防止sql注入,但是有时用${}会非常方便,如下的例子:
<!-- 根据名称模糊查询用户信息 -->
<select id="selectUserByName" parameterType="string" resultType="user">
select * from user where username like '%${value}%'
</select>
如果本例子使用#{}则传入的字符串中必须有%号,而%是人为拼接在参数中,显然有点麻烦,如果采用${}在sql中拼接为%的方式则在调用mapper接口传递参数就方便很多。
//如果使用占位符号则必须人为在传参数中加%
List<User> list = userMapper.selectUserByName("%管理员%");
//如果使用${}原始符号则不用人为在参数中加%
List<User>list = userMapper.selectUserByName("管理员");
再比如order by排序,如果将列名通过参数传入sql,根据传的列名进行排序,应该写为:ORDER BY ${columnName},如果使用#{}将无法实现此功能。
2、传递pojo包装对象
开发中通过pojo传递查询条件 ,查询条件是综合的查询条件,不仅包括用户查询条件还包括其它的查询条件(比如将用户购买商品信息也作为查询条件),这时可以使用包装对象传递输入参数。
定义包装对象,将查询条件以类组合的方式包装起来。
public class QueryUserVo {
// 自定义用户扩展类
private UserCustom userCustom;
public UserCustom getUserCustom() {
return userCustom;
}
public void setUserCustom(UserCustom userCustom) {
this.userCustom = userCustom;
}
}
public class UserCustom extends User {
}
mapper.xml映射文件
<select id="findUserList" parameterType="org.haiwen.pojo.QueryUserVo" resultType="user">
select * from user where id = #{userCustom.id} and username like '%${userCustom.username}%'
</select>
public List<User> findUserList(QueryUserVo queryUserVo) throws Exception;
测试
@Test
public void testFindUserList() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserCustom userCustom = new UserCustom();
userCustom.setId(1);
userCustom.setUsername("马");
QueryUserVo queryUserVo = new QueryUserVo();
queryUserVo.setUserCustom(userCustom);
List<User> list = userMapper.findUserList(queryUserVo);
for (User user : list) {
System.out.println(user);
}
}
说明:mybatis底层通过ognl从pojo中获取属性值:#{userCustom.id},userCustom即是传入的包装对象的属性。属性值需要通过“包装类属性.属性”的方法获取。
3、传递HashMap
mapper.xml映射文件
<select id="findUserByHashmap" parameterType="hashmap" resultType="user">
select * from user where id = #{id} and username like '%${username}%'
</select>
public List<User> findUserByHashmap(Map<String, Object> map) throws Exception;
测试
@Test
public void testFindUserByHashmap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
Map<String, Object> map = new HashMap();
map.put("id", 1);
map.put("username", "马");
List<User> list = userMapper.findUserByHashmap(map);
for (User user : list) {
System.out.println(user);
}
}
resultType(输出类型)
1、输出简单类型
mapper.xml映射文件
<select id="findUserCount" resultType="int">
select count(1) from user
</select>
public int findUserCount() throws Exception;
测试
@Test
public void testFindUserCount() throws Exception {
SqlSession session = sqlSessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
int count = userMapper.findUserCount();
System.out.println(count);
session.close();
}
总结
输出简单类型必须查询出来的结果集有一条记录,最终将第一个字段的值转换为输出类型。
使用session的selectOne可查询单条记录。
2、输出pojo对象
mapper.xml映射文件
<select id="findUserById" parameterType="int" resultType="org.haiwen.entity.User">
select * from user where id = #{id}
</select>
public User findUserById(int id) throws Exception;
测试
@Test
public void testFindUserById() throws Exception {
SqlSession session = sqlSessionFactory.openSession();
UserMapper userMapper = session.getMapper(UserMapper.class);
User user = userMapper.findUserById(1);
System.out.println(user);
session.close();
}
3、输出pojo列表
mapper.xml映射文件
<select id="findUserByUsername" parameterType="java.lang.String" resultType="org.haiwen.entity.User">
select * from user where username like '%${value}%'
</select>
public List<User> findUserByUsername(String username) throws Exception;
测试
@Test
public void testFindUserByUsername() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> list = userMapper.findUserByUsername("马");
for (User user : list) {
System.out.println(user);
}
}
总结
输出pojo对象和输出pojo列表在sql中定义的resultType是一样的。
返回单个pojo对象要保证sql查询出来的结果集为单条,内部使用session.selectOne方法调用,mapper接口使用pojo对象作为方法返回值。
返回pojo列表表示查询出来的结果集可能为多条,内部使用session.selectList方法,mapper接口使用List<pojo>对象作为方法返回值。
4、输出resultMap
resultType将查询结果映射为pojo,需要pojo的属性名和sql查询的列名一致方可映射成功。
resultMap也可以将查询结果映射为pojo,不需要pojo的属性名和sql查询的列名一致,但是要通过resultMap将字段名和属性名作一个对应关系。
mapper.xml映射文件
<!--定义resultMap
将select id user_id,username user_username from user 和User类中的属性作一个映射关系
type:resultMap最终映射的java对象类型,可以使用别名
id:对resultMap的唯一标识-->
<resultMap type="org.haiwen.entity.User" id="userResultMap">
<!--id表示查询结果集中唯一标识
column:查询出来的列名
property:type指定的pojo类型中的属性名
最终resultMap对column和property作一个映射关系(对应关系)-->
<id column="user_id" property="id" />
<!--result:对普通名映射定义
column:查询出来的列名
property:type指定的pojo类型中的属性名
最终resultMapx对column和property作一个映射关系(对应关系)-->
<result column="user_password" property="password" />
</resultMap>
<select id="findUserListResultMap" resultMap="userResultMap">
select id user_id,password user_password from user
</select>
public List<User> findUserListResultMap() throws Exception;
测试
@Test
public void testFindUserListResultMap() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> list = userMapper.findUserListResultMap();
for (User user : list) {
System.out.println(user);
}
}