什么是MyBatis?
MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
配置:
- configuration(配置)
- properties(属性)
- settings(设置)
- typeAliases(类型别名)
- typeHandlers(类型处理器)
- objectFactory(对象工厂)
- plugins(插件)
- environments(环境配置)
- environment(环境变量)
- transactionManager(事务管理器)
- dataSource(数据源)
- environment(环境变量)
- databaseldProvider(数据库厂商标识)
- mappers(映射器)
动态SQL:
什么是动态SQL:传统的使用JDBC的方法,相信大家在组合复杂的的SQL语句的时候,需要去拼接,稍不注意哪怕少了个空格,都会导致错误。Mybatis的动态SQL功能正是为了解决这种问题, 其通过 if, choose, when, otherwise, trim, where, set, foreach标签,可组合成非常灵活的SQL语句,从而提高开发人员的效率。下面就去感受Mybatis动态SQL的魅力吧。
标签 | 说明 |
---|---|
if | 条件判断,与Java中的if语句类似 |
where | 为SQL语句动态添加where关键字 |
choose | 条件判断,这是一个组合标签,需要与when、otherwise标签搭配使用。可实现与java中的switch语句类似的功能 |
foreach | 以遍历方式处理集合类型参数 |
set | 为SQL语句动态添加set关键字,实现动态实现数据更新功能 |
trim | 对SQL语句进行格式化处理,添加或移除前后缀 |
if标签:
if标签是MyBatis框架动态SQL技术中重要且常用的标签之一,它所实现的功能与Java中的if语句基本相同,用法也很相似。
//语法
<if test = "条件判断,返回true或false">
SQL语句...
</if>
where标签:
where标签的主要作用是对SQL语句中的where关键字进行简化处理,并可以智能地处理其内部and、or等关键字,避免多余字符带来的语法错误。
//语法
<where>
<if test = "条件判断">
SQL语句
</if>
</where>
choose(when、otherwise)标签
choose标签是一个组合标签,通常与when、otherwise标签配合使用,实现了类似于Java中switch语句的功能。
//语法
<choose>
<when test = "条件判断,返回true或false">
SQL语句...
</when>
<when test = "条件判断,返回true或false">
SQL语句...
<otherwise>
SQL语句...
</otherwise>
</choose>
foreach标签
foreach标签处理List类型参数,例如以下:
//示例
//在SysUserMapper中添加getUserByRoleIdList()
//根据角色ID集合 查询用户列表信息
//@param roleList
//@return
public List<SysUser> getUserByRoleIdList(List<Integer> roleList);
//在SysUserMapper.xml中添加的查询代码:
<select id = "getUserByRoleIdList" resultType = "SysUser">
select * from t_sys_user where roleId in
<foreach collection = "List" item = "item" open ="("separator","close=")">
#{item}
</foreach>
</select>
//在测试类中创建测试方法testGetUserByRoleIdByList(),关键代码如下所示:
List<Integer> roleList = new ArrayList<Integer>();
roleList.add(1);
roleList.add(2);
userList = sqlSession.getMapper(SysUserMapper.class).getUserByRoleIdList(roleList);
foreach标签处理Map类型参数,例如以下:
在SysUserMapper类型时,例如:
//根据角色ID集合(集合存在Map中)查询用户列表信息
//@param roleMap
//@reture
public List<SysUser> getUserByRoleIdMap(Map<String,Object> roleMap);
//SysUserMapper.xml中添加的查询代码:
<select id = "getUserByRoleIdMap" resultType = "SysUser">
select * from t_sys_user where roleId in
<foreach collection="roleIdList" item="item" open = "("separator = ","close =")">
#{item}
</foreach>
</select>
//在测试类中创建测试方法testGetUserByRoleIdMap(),关键代码如下所示:
List<Integer> roleIdList = new ArrayList<Integer>();
roleIdList.add(1);
roleIdList.add(2);
Map<String,Object> roleMap = new HashMap<String,Object>;
roleMap.put("roleIdList",roleIdList);
userList = sqlSession.getMapper(SysUserMapper.class).getUserByRoleIdMap(roleMap);
foreach小结:
- 当参数为数据基本类型或数组、List集合类型时,MyBatis框架会将参数封装在一个Map对象中。
- 当参数为数组类型时,collection对应默认为array。
- 当参数为List集合类型时,collection对应值默认为list。
- 如果使用@Param注解为参数设置了名称,collection对应值为参数名。
- 当参数为Map对象时,collection对应值为该Map对象中数组或集合元素对应的key。
set标签:
set标签的用法和功能都与where标签非常相似,可以在其包裹的语句前拼接一个set关键字,并继忽略更新语句尾部多余出来的逗号。配合if标签灵活使用set标签,就可以在拼接SQL时忽略不需要修改的字段,从而实现数据部分更新的功能。
//语法
<set>
<if test = "条件判断">
SQL语句
</if>
</set>
trim标签:
where、set标签能够动态地为SQL语句添加前后缀,并可以智能地忽略标签前后多余的and、or或逗号等字符。除where和set标签外,MyBatis框架还提供了更为灵活的trim标签来实现类似的功能。
//语法
<trim prefix = "前缀" suffix = "后缀" prefixOverrides = "忽略前缀"
suffixOverrides = "忽略后缀">
....
</trim>
trim标签的属性介绍如下:
- prefix:前缀,可以自动对trim标签所包含的语句是否有返回值进行判断。如果有返回值,则为SQL语句拼接相应前缀。
- suffix:后缀,在trim标签包含的语句末尾拼接后缀。
- prefixOverrides:忽略的前缀,忽略trim标签内部首部指定的内容。
- suffixOverrides:忽略的后缀,忽略trim标签包含内容尾部指定的内容。
MySQL的分页查询:
MySQL数据库的分页关键字为limit,使用MyBatis框架对其进行操作时,用法与在客户端的操作基本相同。例如以下:
//示例
//SysUserMapper中分页查询方法selectPageList()的代码:
//分页查询用户列表
//@param realName
//@param roleId
//@param pageBegin
//@param pageSize
//@return
public List<SysUser> selectPageList(@Param("realName") String realName
,@Param("roleId")Integer roleId
,@Param("pageBegin")Integer pageBegin
,@Param("pageSize")Integer pageSize);
//SysUserMapper.xml中分页查询的代码:
<select id = "selectPageList" resultType="SysUser">
select * from t_sys_user
<trim prefix="where" prefixOverrides="and | or">
<if test="realName !=null and realName != ''">
and realName like CONCAT('%',#{realName},'%')
</if>
<if test="roleId !=null">
and roleId = #{roleId}
</if>
</trim>
order by createdTime desc limit #{pageBegin},#{pageSize}
</select>
//测试类中测试方法testGetUserPage()的代码:
@Test
public void testGetUserPage(){
SqlSession sqlSession = null;
List<SysUser> userList = new ArrayList<SysUser>();
try{
sqlSession = MyBatisUtil.createSqlSession();
String realName="";
Integer roleId = 2;
Integer pageIndex = 2;
Integer pageSize = 2;
Integer pageBegin = (pageIndex - 1) * pageSize; //计算查询起始位置
userList = sqlSession.getMapper(SysUserMapper.class)
.selectPageList(realName,roleId,pageBegin,pageSize); //查询分页数据
} catch (Exception e) {
e.printStackTrace();
} finally {
MyBatisUtil.closeSqlSession(sqlSession);
}
logger.info("查询到用户数量:" + userList.size());
for(SysUser user : userList){
logger.info("查询到用户信息:" + user);
}
}