Mapper映射文件是在实际开发过程中使用最多的。Mapper文件中包含的元素有:
UserMapper.xml
测试
结果出错,错误信息参数userName找不到,可用参数为0,1,param1,param2
![](https://img-blog.csdn.net/20170208202050348?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVjaGFvMjAxNQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
修改参数:
测试
加入全局配置文件mybatis-config.xml
在mapper映射文件中引用:
- cache – 配置给定命名空间的缓存。
- cache-ref – 从其他命名空间引用缓存配置。
- resultMap – 映射复杂的结果对象。
- sql – 可以重用的 SQL 块,也可以被其他语句引用。
- insert – 映射插入语句
- update – 映射更新语句
- delete – 映射删除语句
- select – 映射查询语句
select – 映射查询语句
<select id="queryUserById" resultType="User" parameterType="Long">
SELECT * FROM tb_user WHERE id = #{id}
</select>
id:是当前命名空间下的Statement的唯一标识(必须属性);
parameterType:输入的参数类型(可以省略);
resultType:将结果集映射为的java对象类型(必须属性);
标签内部:编写SQL语句
insert – 映射插入语句
<insert id="saveUser" parameterType="cn.zto.mybatis.pojo.User">
INSERT INTO tb_user (
id,
user_name,
password,
name,
age,
sex,
birthday,
created,
updated
)
VALUES
(
NULL,
#{userName},
#{password},
#{name},
#{age},
#{sex},
#{birthday},
NOW(),
NOW()
);
</insert>
id:是当前命名空间下的Statement的唯一标识(必须属性);
parameterType:输入的参数类型(可以省略);
标签内部:编写SQL语句
获取自增Id
<!-- useGeneratedKeys: 开启自增id回填
keyColumn: 指定数据库表中列名
keyProperty: 指定对象的属性名
如果keyColumn 和 keyProperty 相同,则keyColumn可以省略不写 -->
<insert id="saveUser" parameterType="cn.zto.mybatis.pojo.User" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
INSERT INTO tb_user (
id,
user_name,
password,
name,
age,
sex,
birthday,
created,
updated
)
VALUES
(
NULL,
#{userName},
#{password},
#{name},
#{age},
#{sex},
#{birthday},
NOW(),
NOW()
);
</insert>
@Test
public void testSaveUser() {
User user = new User();
user.setAge(20);
user.setBirthday(new Date());
user.setName("test_3");
user.setPassword("123456");
user.setSex(1);
user.setUserName("test_username_3");
this.userMapper.saveUser(user);
//获取自增id
System.out.println("id:"+user.getId());
}
update – 映射更新语句
<update id="updateUser" parameterType="cn.zto.mybatis.pojo.User">
UPDATE tb_user
SET
user_name = #{userName},
password = #{password},
name = #{name},
age = #{age},
sex = #{sex},
birthday = #{birthday},
updated = NOW()
WHERE
id = #{id}
</update>
id:是当前命名空间下的Statement的唯一标识(必须属性);
parameterType:输入的参数类型(可以省略);
标签内部:编写SQL语句
delete – 映射删除语句
<delete id="deleteUserById">
DELETE FROM tb_user WHERE id = #{id}
</delete>
id:是当前命名空间下的Statement的唯一标识(必须属性);
parameterType:输入的参数类型(可以省略);
标签内部:编写SQL语句
parameterType的传入参数
传入类型有三种:
在使用#{}传参时,#{}只是做占位符,与参数名无关。
在使用${}传参时,是通过参数名获取参数的,如果没有指定参数名则可以通过value获取,如果指定则需要按照名称获取。
- 1、简单类型,string、long、integer等
- 2、Pojo类型,User等
- 3、HashMap类型。
在使用${}传参时,是通过参数名获取参数的,如果没有指定参数名则可以通过value获取,如果指定则需要按照名称获取。
parameterType的传入多个参数
当Mapper接口中需要传递多个参数时有两种方法传递:
- 使用默认规则获取参数;
- 使用@Param注解表明参数传递;
其实parameterType参数是可以省略的
UserMapper.java
package cn.zto.mybatis.mapper;
import cn.zto.mybatis.pojo.User;
public interface UserMapper {
/**
* 模拟登陆
* @Title: login
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param: @param userName
* @param: @param passwd
* @param: @return
* @return: User
* @throws
*/
public User login(String userName,String passwd);
}
UserMapper.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="cn.zto.mybatis.mapper.UserMapper">
<select id="login" resultType="User" >
SELECT * FROM tb_user WHERE user_name = #{userName} and password = #{passwd}
</select>
</mapper>
测试
package cn.zto.mybatis.mapper;
import java.io.InputStream;
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.junit.Before;
import org.junit.Test;
import cn.zto.mybatis.pojo.User;
/**
* 动态代理实现类测试用例
*
*/
public class UserMapperTest {
private UserMapper userMapper;
@Before
public void setUp() throws Exception {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream, "test");
SqlSession sqlSession = sqlSessionFactory.openSession(true);
// 通过sqlSession获取到动态代理的实现类
this.userMapper = sqlSession.getMapper(UserMapper.class);
}
@Test
public void testLogin() {
User user = this.userMapper.login("zhangsan","123");
System.out.println(user);
}
}
结果出错,错误信息参数userName找不到,可用参数为0,1,param1,param2
<select id="login" resultType="User" >
<!-- SELECT * FROM tb_user WHERE user_name = #{userName} and password = #{passwd} -->
SELECT * FROM tb_user WHERE user_name = #{0} and password = #{1}
</select>
或者:
<select id="login" resultType="User" >
<!-- SELECT * FROM tb_user WHERE user_name = #{userName} and password = #{passwd} -->
SELECT * FROM tb_user WHERE user_name = #{param1} and password = #{param2}
</select>
测试通过。这种方式为使用默认规则参数,还有一种是通过@param注解获取参数
/**
* 模拟登陆
* @Title: login
* @Description: TODO(这里用一句话描述这个方法的作用)
* @param: @param userName
* @param: @param passwd
* @param: @return
* @return: User
* @throws
*/
public User login(@Param("userName")String userName,@Param("passwd")String passwd);
<select id="login" resultType="User" >
SELECT * FROM tb_user WHERE user_name = #{userName} and password = #{passwd}
<!-- SELECT * FROM tb_user WHERE user_name = #{param1} and password = #{param2} -->
</select>
ResultType结果输出
输出类型有三种:
- 简单类型,string、long、integer等
- Pojo类型,User等
- HashMap类型。
‘#{}’与‘${}’的区别
在Mybatis的mapper中,参数传递有2种方式,一种是#{}另一种是${},两者有着很大的区别:
是不是${}就没用了呢?不是的,有些情况下就必须使用${},举个例子:
在分表存储的情况下,我们从哪张表查询是不确定的,也就是说sql语句不能写死,表名是动态的,查询条件的固定的,这样:SELECT * FROM ${tableName} WHERE id = #{id}
CommonMapper.java
- #{} 实现的是sql语句的预处理参数,之后执行sql中用?号代替,使用时不需要关注数据类型,Mybatis自动实现数据类型的转换。并且可以防止SQL注入。
- ${} 实现是sql语句的直接拼接,不做数据类型转换,需要自行判断数据类型。不能防止SQL注入。
是不是${}就没用了呢?不是的,有些情况下就必须使用${},举个例子:
在分表存储的情况下,我们从哪张表查询是不确定的,也就是说sql语句不能写死,表名是动态的,查询条件的固定的,这样:SELECT * FROM ${tableName} WHERE id = #{id}
CommonMapper.java
package cn.zto.mybatis.mapper;
import java.util.List;
import java.util.Map;
import org.apache.ibatis.annotations.Param;
public interface CommonMapper {
/**
* 根据表名查询表数据
*
* @param id
* @return
*/
public List<Map<String,Object>> queryByTableName(@Param("tableName")String tableName);
}
CommonMapper.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="cn.zto.mybatis.mapper.CommonMapper">
<!--SELECT * FROM ${value} ${value}:value是mybatis默认的参数名-->
<!--在接口中通过@Param来自定义参数名 -->
<select id="queryByTableName" resultType="HashMap" parameterType="String">
SELECT * FROM ${tableName}
</select>
</mapper>
测试
@Test
public void queryByTableName() {
List<Map<String, Object>> queryByTableName = this.commonMapper.queryByTableName("tb_user");
for (Map<String, Object> map : queryByTableName) {
System.out.println(map);
}
}
总结:
#{} 占位符,用于参数传递,和参数名称无关。
${}用于SQL拼接。
#{} 占位符,用于参数传递,和参数名称无关。
${}用于SQL拼接。
resultMap – 映射复杂的结果对象
ResultMap是Mybatis中最重要最强大的元素,使用ResultMap可以解决两大问题:
POJO属性名和表结构字段名不一致的问题(有些情况下也不是标准的驼峰格式)
完成高级查询,比如说,一对一、一对多、多对多。
解决表字段名和属性名不一致的问题有两种方法:
1、如果是驼峰似的命名规则可以在Mybatis配置文件中设置<setting name="mapUnderscoreToCamelCase" value="true"/>解决
2、使用ResultMap解决。
3、还可以起别名.
POJO属性名和表结构字段名不一致的问题(有些情况下也不是标准的驼峰格式)
完成高级查询,比如说,一对一、一对多、多对多。
解决表字段名和属性名不一致的问题有两种方法:
1、如果是驼峰似的命名规则可以在Mybatis配置文件中设置<setting name="mapUnderscoreToCamelCase" value="true"/>解决
2、使用ResultMap解决。
SQL片段
我们在java代码中会将公用的一些代码提取出来需要的地方直接调用方法即可,在Mybatis也是有类似的概念,那就是SQL片段。
在Mybatis中使用<sql id=”” />标签定义SQL片段,在需要的地方通过<include refid=“”/>引用
例如:
<sql id="userColumns">id,user_name,password,name,age,sex,birthday,created,updated</sql>
<select id="queryUserById" resultMap="userResultMap" parameterType="Long">
SELECT <include refid="userColumns"/> FROM tb_user WHERE id = #{id}
</select>
另外一种用法:
将所有的公用的SQL片段集中定义到一个Mapper.xml文件中,并将此Mapper.xml加入到全局配置文件mybatis-config.xml ,其他Mapper.xml文件如需引入,通过命名空间.id即可。
<?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="my.common">
<sql id="userColumns">id,user_name,password,name,age,sex,birthday,created,updated</sql>
</mapper>
加入全局配置文件mybatis-config.xml
<mappers>
<mapper resource="UserMapper.xml" />
<mapper resource="CommonMapper.xml" />
</mappers>
在mapper映射文件中引用:
<select id="queryUserById" resultMap="userResultMap" parameterType="Long">
SELECT <include refid="my.common.userColumns"/> FROM tb_user WHERE id = #{id}
</select>