最近在读刘增辉老师所著的《MyBatis从入门到精通》一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸!

1. 明确需求

书中提到的需求是一个基于角色的权限控制需求(RBAC,即Role-Based Access Control),提到权限管理,相信大家都不陌生,因为大部分的系统都是需要权限管理的,我在上家公司负责的系统之一就是权限系统,设计思路和书中提到的差不多,大致描述如下:

1)权限点用来管理要控制权限的资源,比如某个页面,某个按钮。

2)创建一个角色,给这个角色分配某些权限点,比如商品模块的所有页面的权限。

3)新建一个用户,给这个用户分配某些角色。

数据关系图如下所示:

2. 数据准备

首先执行如下脚本创建上图中的5张表:用户表,角色表,权限表,用户角色关联表,角色权限关联表。

CREATE TABLE sys_user
(id BIGINT NOT NULL AUTO_INCREMENT COMMENT '用户ID',user_name VARCHAR(50) COMMENT '用户名',user_password VARCHAR(50) COMMENT '密码',user_email VARCHAR(50) COMMENT '邮箱',user_info TEXT COMMENT '简介',head_img BLOB COMMENT '头像',create_time DATETIME COMMENT '创建时间',PRIMARY KEY (id)
);
ALTER TABLE sys_user COMMENT '用户表';CREATE TABLE sys_role
(id BIGINT NOT NULL AUTO_INCREMENT COMMENT '角色ID',role_name VARCHAR(50) COMMENT '角色名',enabled INT COMMENT '有效标志',create_by BIGINT COMMENT '创建人',create_time DATETIME COMMENT '创建时间',PRIMARY KEY (id)
);
ALTER TABLE sys_role COMMENT '角色表';CREATE TABLE sys_privilege
(id BIGINT NOT NULL AUTO_INCREMENT COMMENT '权限ID',privilege_name VARCHAR(50) COMMENT '权限名称',privilege_url VARCHAR(200) COMMENT '权限URL',PRIMARY KEY (id)
);
ALTER TABLE sys_privilege COMMENT '权限表';CREATE TABLE sys_user_role
(user_id BIGINT COMMENT '用户ID',role_id BIGINT COMMENT '角色ID'
);
ALTER TABLE sys_user_role COMMENT '用户角色关联表';CREATE TABLE sys_role_privilege
(role_id BIGINT COMMENT '角色ID',privilege_id BIGINT COMMENT '权限ID'
);
ALTER TABLE sys_role_privilege COMMENT '角色权限关联表';

然后执行如下脚本添加测试数据:

INSERT INTO sys_user VALUES (1,'admin','123456','admin@mybatis.tk','管理员',NULL,current_timestamp);
INSERT INTO sys_user VALUES (1001,'test','123456','test@mybatis.tk','测试用户',NULL,current_timestamp);INSERT INTO sys_role VALUES (1,'管理员',1,1,current_timestamp);
INSERT INTO sys_role VALUES (2,'普通用户',1,1,current_timestamp);INSERT INTO sys_user_role VALUES (1,1);
INSERT INTO sys_user_role VALUES (1,2);
INSERT INTO sys_user_role VALUES (1001,2);INSERT INTO sys_privilege VALUES (1,'用户管理','/users');
INSERT INTO sys_privilege VALUES (2,'角色管理','/roles');
INSERT INTO sys_privilege VALUES (3,'系统日志','/logs');
INSERT INTO sys_privilege VALUES (4,'人员维护','/persons');
INSERT INTO sys_privilege VALUES (5,'单位维护','/companies');INSERT INTO sys_role_privilege VALUES (1,1);
INSERT INTO sys_role_privilege VALUES (1,2);
INSERT INTO sys_role_privilege VALUES (1,3);
INSERT INTO sys_role_privilege VALUES (2,4);
INSERT INTO sys_role_privilege VALUES (2,5);

3. 创建实体类

在包com.zwwhnly.mybatisaction.model下依次创建这5张表对应的实体类:

package com.zwwhnly.mybatisaction.model;import java.util.Date;/*** 用户表*/
public class SysUser {/*** 用户ID*/private Long id;/*** 用户名*/private String userName;/*** 密码*/private String userPassword;/*** 邮箱*/private String userEmail;/*** 简介*/private String userInfo;/*** 头像*/private byte[] headImg;/*** 创建时间*/private Date createTime;// 按Alt+Insert快捷键生成get和set方法
}
package com.zwwhnly.mybatisaction.model;import java.util.Date;/*** 角色表*/
public class SysRole {/*** 角色ID*/private Long id;/*** 角色名*/private String roleName;/*** 有效标志*/private Integer enabled;/*** 创建人*/private Long createBy;/*** 创建时间*/private Date createTime;// 按Alt+Insert快捷键生成get和set方法
}

可以参考类似的命名方式创建SysPrivilege.java,SysUserRole.java,SysRolePrivilege.java。

也可以按照文末提供的源码地址下载下源代码。

注意事项:

1)MyBatis默认遵循“下划线转驼峰”命名方式。

如sys_user表对应的实体类名是Sys_User,数据库字段user_name对应的实体类字段是userName。

2)在实体类中不要使用Java的基本类型,基本类型包括byte、int、short、long、float、doubule、char、boolean。

因为Java中的基本类型会有默认值,例如当某个类中存在private int age;字段时,age的默认值为0,所以无法满足age为null的情况,如果使用age !=null,结果总为ture,会导致一些隐藏的bug。

4. 创建Mapper.xml文件

在src/main/resources下的com/zwwhnly/mybatisaction/mapper目录下依次创建5张表对应的Mapper.xml文件。

为了后续更快速的创建Mapper.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>
</mapper>

然后选中目录,右键新增文件,如下图所示:


刚生成的SysUserMapper.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>
</mapper>

我们只需要给mapper标签添加个namespace属性即可:

<?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="com.zwwhnly.mybatisaction.mapper.SysUserMapper">
</mapper>

按照同样的方式依次创建SysRoleMapper.xml,SysPrivilegeMapper.xml,SysUserRoleMapper.xml和SysRolePrivilegeMapper.xml。

创建完成后,打开我们在上篇博客中创建的mybatis-config.xml文件,修改节点的内容为:

<mappers><mapper resource="com/zwwhnly/mybatisaction/mapper/CountryMapper.xml"/><mapper resource="com/zwwhnly/mybatisaction/mapper/SysUserMapper.xml"/><mapper resource="com/zwwhnly/mybatisaction/mapper/SysRoleMapper.xml"/><mapper resource="com/zwwhnly/mybatisaction/mapper/SysPrivilegeMapper.xml"/><mapper resource="com/zwwhnly/mybatisaction/mapper/SysUserRoleMapper.xml"/><mapper resource="com/zwwhnly/mybatisaction/mapper/SysRolePrivilegeMapper.xml"/>
</mappers>

使用这种方式,最明显的缺点就是,我们后续如果新增了Mapper.xml文件,仍然需要来修改文件,非常不好维护,因此我们修改成如下配置方式,配置一个包名:

<mappers><package name="com.zwwhnly.mybatisaction.mapper"/>
</mappers>

修改完成后,运行上篇博客中的单元测试CountryMapperTest,发现执行报如下错误:

报错的原因是上篇博客中,我们并没有为CountryMapper.xml文件创建对应的接口,使用包名配置方式后,就需要创建,所以解决方案就是在src/main/java下新建包com.zwwhnly.mybatisaction.mapper下,然后在该包下新建接口CountryMapper,然后在接口中添加方法selectAll()。

package com.zwwhnly.mybatisaction.mapper;import com.zwwhnly.mybatisaction.model.Country;import java.util.List;public interface CountryMapper {/*** 查询全部国家** @return*/List<Country> selectAll();
}

5. 创建Mapper接口

找到src/main/java目录下的包com.zwwhnly.mybatisaction.mapper,在该包下创建XML文件对应的接口类,分别为SysUserMapper.java,SysRoleMapper.java,SysPrivilegeMapper.java,SysUserRoleMapper.java,SysRolePrivilegeMapper.java。

这里只展示下SysUserMapper.java的代码:

package com.zwwhnly.mybatisaction.mapper;public interface SysUserMapper {}

注意事项:当Mapper接口和XML文件关联的时候,命名空间namespace的值需要配置成接口的全限定名称,MyBatis内部就是通过这个值将接口和XML关联起来的。

例如SysUserMapper.xml中配置的namespace就com.zwwhnly.mybatisaction.mapper.SysUserMapper

6. select用法

6.1 查询单条数据

假设我们需要通过id查询用户的信息,首先,我们需要打开SysUserMapper.java接口定义方法:

/*** 通过id查询用户** @param id* @return*/
SysUser selectById(Long id);

然后打开对应的SysUserMapper.xml文件添加如下内容:

<resultMap id="sysUserMap" type="com.zwwhnly.mybatisaction.model.SysUser"><id property="id" column="id"/><result property="userName" column="user_name"/><result property="userPassword" column="user_password"/><result property="userEmail" column="user_email"/><result property="userInfo" column="user_info"/><result property="headImg" column="head_img" jdbcType="BLOB"/><result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
</resultMap><select id="selectById" resultMap="sysUserMap">SELECT * FROM sys_user WHERE id = #{id}
</select>

说明:

1)MyBatis通过select标签的id属性值和接口的名称进行关联。

2)标签的id属性值不能出现英文句号"."。

3)标签的id属性值在同一个命名空间下不能重复。

4)因为接口方法是可以重载的,所以接口中可以出现多个同名但参数不同的方法,但是XML中id的值不能重复,因此接口中的所有同名方法会对应着XML中的同一个id的方法。

为了验证第2点,我们将selectById修改成select.ById:

<select id="select.ById" resultMap="sysUserMap">SELECT * FROM sys_user WHERE id = #{id}
</select>

此时如果调用该方法,会报如下错误:

为了验证第3点,我们将XML内容修改为如下:

<select id="selectById" resultMap="sysUserMap">SELECT * FROM sys_user WHERE id = #{id}
</select>
<select id="selectById" resultMap="sysUserMap">SELECT * FROM sys_user WHERE id = #{id}
</select>

此时如果调用该方法,会报如下错误:

XML 代码讲解:

  • select:映射查询语句使用的标签。
  • id:查询语句的唯一标识符,可用来代表这条语句。
  • resultMap:用于设置数据库返回列和Java对象的映射关系。
  • SELECT * FROM sys_user WHERE id = #{id}是查询语句。
  • {id}:MyBatis SQL中使用预编译参数的一种方式,大括号中的id代表传入的参数名。

resultMap标签用于配置Java对象的属性和查询结果列的对应关系,通过resultMap中配置的column和property可以将查询列的值映射到type对象的属性上。

上面查询语句用到的resultMap标签讲解:

  • id:必填且唯一。select标签resultMap属性的值为此处id设置的值。
  • type:必填。用于配置查询列所映射到的Java对象模型。
  • column:从数据库中得到的列名或者列的别名。
  • property:要映射到的列结果的属性,即Java对象模型的属性。
  • jdbcType:列对应的数据库类型。

6.2 查询多条数据

假设我们需要查询所有用户的信息,首先,我们需要打开SysUserMapper.java接口定义方法:

/*** 查询全部用户** @return*/
List<SysUser> selectAll();

然后打开对应的SysUserMapper.xml文件添加如下内容:

<select id="selectAll" resultType="com.zwwhnly.mybatisaction.model.SysUser">SELECT id,user_name     userName,user_password userPassword,user_email    userEmail,user_info     userInfo,head_img      headImg,create_time   createTimeFROM sys_user
</select>

注意事项:这里我们并没有使用resultMap属性来设置要返回结果的类型,而是通过resultType属性直接指定

要返回结果的类型,使用此种方式需要设置查询列的别名,别名要和resultType指定对象的属性名保持一致,

进而实现自动映射。

MyBatis提供了一个全局属性mapUnderscoreToCamelCase,将这个属性的值设置为ture可以自动将以下划线命名的数据库列映射到Java对象的驼峰式命名属性中。

那么如何打开呢?

方法是打开我们在上篇博客中新建的mybatis-config文件,在settings节点添加如下配置:

<settings><!--其他配置--><setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>

此时,前面的selectAll语句可以简化为如下。

<select id="selectAll" resultType="com.zwwhnly.mybatisaction.model.SysUser">SELECT id,user_name,user_password,user_email,user_info,head_img,create_timeFROM sys_user
</select>

7. 单元测试

新建基础测试类BaseMapperTest,代码如下。

package com.zwwhnly.mybatisaction.mapper;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.BeforeClass;import java.io.IOException;
import java.io.Reader;/*** 基础测试类*/
public class BaseMapperTest {private static SqlSessionFactory sqlSessionFactory;@BeforeClasspublic static void init() {try {Reader reader = Resources.getResourceAsReader("mybatis-config.xml");sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);reader.close();} catch (IOException e) {e.printStackTrace();}}public SqlSession getSqlSession() {return sqlSessionFactory.openSession();}
}

将上篇博客中的CountryMapperTest类代码修改为如下。

package com.zwwhnly.mybatisaction.mapper;import com.zwwhnly.mybatisaction.model.Country;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;import java.util.List;public class CountryMapperTest extends BaseMapperTest {@Testpublic void testSelectAll() {SqlSession sqlSession = getSqlSession();try {List<Country> countryList = sqlSession.selectList("com.zwwhnly.mybatisaction.mapper.CountryMapper.selectAll");printCountryList(countryList);} finally {sqlSession.close();}}private void printCountryList(List<Country> countryList) {for (Country country : countryList) {System.out.printf("%-4d%4s%4s\n", country.getId(), country.getCountryname(), country.getCountrycode());}}
}

修改点:

1)继承基础测试类BaseMapperTest,调用基类getSqlSession()方法即可获取SqlSession对象,实现代码重用。

2)selectList()方法的参数值由selectAll修改为com.zwwhnly.mybatisaction.mapper.CountryMapper.selectAll,

因为在SysUserMapper中也添加了一个selectAll()方法,selectAll不再唯一,因此调用时必须带上namespace。

参考CountryMapperTest测试类新建SysUserMapperTest测试类,代码如下。

package com.zwwhnly.mybatisaction.mapper;import com.zwwhnly.mybatisaction.model.SysUser;
import org.apache.ibatis.session.SqlSession;
import org.junit.Assert;
import org.junit.Test;import java.util.List;public class SysUserMapperTest extends BaseMapperTest {@Testpublic void testSelectById() {SqlSession sqlSession = getSqlSession();try {SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);SysUser sysUser = sysUserMapper.selectById(1L);Assert.assertNotNull(sysUser);Assert.assertEquals("admin", sysUser.getUserName());} finally {sqlSession.close();}}@Testpublic void testSelectAll() {SqlSession sqlSession = getSqlSession();try {SysUserMapper sysUserMapper = sqlSession.getMapper(SysUserMapper.class);List<SysUser> sysUserList = sysUserMapper.selectAll();Assert.assertNotNull(sysUserList);Assert.assertTrue(sysUserList.size() > 0);} finally {sqlSession.close();}}
}

运行测试类代码,测试通过,输出日志如下所示。

DEBUG [main] - ==> Preparing: SELECT id, user_name, user_password, user_email, user_info, head_img, create_time FROM sys_user

DEBUG [main] - ==> Parameters:

TRACE [main] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time

TRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, <>, <>, 2019-06-27 18:21:07.0

TRACE [main] - <== Row: 1001, test, 123456, test@mybatis.tk, <>, <>, 2019-06-27 18:21:07.0

DEBUG [main] - <== Total: 2

DEBUG [main] - ==> Preparing: SELECT * FROM sys_user WHERE id = ?

DEBUG [main] - ==> Parameters: 1(Long)

TRACE [main] - <== Columns: id, user_name, user_password, user_email, user_info, head_img, create_time

TRACE [main] - <== Row: 1, admin, 123456, admin@mybatis.tk, <>, <>, 2019-06-27 18:21:07.0

DEBUG [main] - <== Total: 1

8. 源码及参考

源码地址:https://github.com/zwwhnly/mybatis-action.git,欢迎下载。

刘增辉《MyBatis从入门到精通》

IntelliJ IDEA中创建xml文件

9. 最后

打个小广告,欢迎扫码关注微信公众号:「申城异乡人」,定期分享Java技术干货,让我们一起进步。

转载于:https://www.cnblogs.com/zwwhnly/p/11118566.html

MyBatis从入门到精通(二):MyBatis XML方式的基本用法之Select相关推荐

  1. Mybatis从入门到精通二(入门详解)

    Mybatis从入门到精通二(想学Mybatis,看了这一篇你就不需要其他的了) 本课程分为两天第一天的请参考: https://blog.csdn.net/weixin_43564627/artic ...

  2. MyBatis从入门到精通(一)—MyBatis基础知识和快速入门

    Mybatis简介 原始jdbc操作(查询数据) Connection connection = null;PreparedStatement preparedStatement = null;Res ...

  3. MyBatis从入门到精通(三):MyBatis XML方式的基本用法之多表查询

    最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 1. 多表查询 上篇博客中,我们示例的 ...

  4. Mybatis从入门到精通上篇

    Mybatis从入门到精通上篇: 学习过的持久层框架:DBUtils , Hibernate Mybatis就是类似于hibernate的orm持久层框架. Mybatis介绍: Mybatis是面向 ...

  5. Mybatis从入门到精通下篇

    Mybatis从入门到精通下篇: 输入类型: 输出类型: ResultMap: 动态sql: if标签: where标签: sql片段: foreach标签: 关联查询: 以订单作为主体: 一对一查询 ...

  6. Mybatis从入门到精通(全)

    目录 前言 1. idea软件小技巧 2. mybatis优势 3. mybatis入门项目 3.1 项目具体步骤 3.2 创建数据表 3.3 创建maven项目 3.4 pom.xml配置文件 3. ...

  7. MyBatis从入门到精通(1):MyBatis入门

    作为一个自学Java的自动化专业211大学本科生,在学习和实践过程中"趟了不少雷",所以有志于建立一个适合同样有热情学习Java技术的参考"排雷手册". 最近在 ...

  8. MyBatis从入门到精通(一):MyBatis入门

    最近在读刘增辉老师所著的<MyBatis从入门到精通>一书,很有收获,于是将自己学习的过程以博客形式输出,如有错误,欢迎指正,如帮助到你,不胜荣幸! 1. MyBatis简介 ​ 2001 ...

  9. MyBatis从入门到精通 PDF 完整版

    给大家带来的一篇关于MyBatis相关的电子书资源,介绍了关于MyBatis.入门到精通方面的内容,本书是由电子工业出版社出版,格式为PDF,资源大小116.8 MB,刘增辉编写,目前豆瓣.亚马逊.当 ...

最新文章

  1. Maven 概要介绍
  2. vSphere vCenter 4.0 安装图解
  3. C语言基础语言总结(二)
  4. VTK:Cell Edge Neighbors用法实战
  5. 收集Redis16个最常见面试问题
  6. java kcp,重新认识KCP - osc_rreaoxa0的个人空间 - OSCHINA - 中文开源技术交流社区
  7. 2018年9月杭州云栖大会Workshop - 基于日志的安全分析实战
  8. 作者:单志广(1974-),男,博士,国家信息中心信息化研究部副主任
  9. python中不包不包括_Unittest-断言列表中的一组项包含在(或不包含在)另一个lis中...
  10. mysql建表主键_常见的MySQL命令大全second
  11. python如何叉乘_向量点乘与向量叉乘
  12. 计算机读研云计算,快来看看2022云计算考研专业有哪些?
  13. 商城管理系统源码 商城APP源码 电子商城源码
  14. 虚拟光驱 win7虚拟光驱下载 ultraiso
  15. 脉歌蓝牙耳机线评测_感受震撼,更贴耳的蓝牙耳机,脉歌MT70让你感受超值音效...
  16. python没有pygame_Python菜鸟快乐游戏编程_pygame
  17. con 元器件符号_关于元器件名称、符号和封装的命名问题
  18. 记录Magisk面具root,并使用HttpCanary获取APP或小程序请求 (一)
  19. php升序排列,php关联数组怎么按键名实现升序排列
  20. centos 7.5 安装桌面环境及报错

热门文章

  1. python求解一元二次方程的解_python练习题1-一元二次方程解
  2. 利用Linux的特性恢复误删的数据文件
  3. openwrt取消strip 软件包
  4. vue 手机移动端预览pdf
  5. 使用idea打包出现Could not find artifact com.ms:---:pom:0.0.1-SNAPSHOT
  6. REDIS 客户端封装 SPARROW 框架源码
  7. [渝粤教育] 西南科技大学 律师实务 在线考试复习资料2021版
  8. 没有免费的午餐-原理剖析(详细)
  9. SAP校园精英同略会邀请 参考答案
  10. 香港科大(广州)8位创校教授获评2020南沙高端领军人才