阿里P7架构师带你修炼MyBatis

简介: 我们通过一个简单的权限控制需求(RABC,Role-Based Access Control,基于角色的访问控制),来讲解通过XML方式配置MyBatis的基本用法(即select、update、insert、delete等操作的XML配置方式)。

我们通过一个简单的权限控制需求(RABC,Role-Based Access Control,基于角色的访问控制),来讲解通过XML方式配置MyBatis的基本用法(即select、update、insert、delete等操作的XML配置方式)。
工具

JDK 1.6及以上版本
MyBatis 3.30版本
MySQL 6.3版本
Eclipse4 及以上版本
Apache Maven 构建工具

项目源码下载地址:https://github.com/JFAlex/MyBatis/tree/master/MyBatis_No.3/alex
权限控制需求

一个用户拥有若干个角色,一个角色拥有若干权限,权限就是对某个资源的(模块)的某种操作(增、删、改、查),这样就构成了“用户--角色--权限”的授权模型。在这种模型中,用户与角色之间、角色与权限之间,一般是多对多的关系。

创建数据库表

首先我们需要创建五个表:用户表、角色表、权限表、用户角色关系表、角色权限关系表。在已经创建好的mybatis数据库中执行如下SQL脚本:

创建数据库,并制定编码格式为UTF-8

CREATE DATABASE mybatis DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

切换数据库到mybatis

use mybatis;

创建用户表

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_uri 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 bigint comment '权限ID'
);
alter table sys_role_privilege comment '角色权限关联表';

测试数据

insert into sys_user(id,user_name, user_password, user_email, user_info, head_img, create_time)
values(1,'admin','123456','admin@mybais.alex','管理员',null,'2017-8-09 15:26:52'),
(2,'test','123456','test@mybais.alex','测试用户',null,'2017-8-09 15:27:30');

insert into sys_role(id,role_name, enabled, create_by, create_time)
values(1,'管理员','1','1','2017-8-09 15:26:52'),(2,'普通用户','1','1','2017-8-09 15:26:52');

insert into sys_privilege(id,privilege_name, privilege_uri)
values(1,'用户管理','/users'),(2,'角色管理','/roles'),(3,'系统日志','/logs'),(4,'人员维护','/persons'),(5,'部门维护','/companies');

insert into sys_user_role values(1,1),(1,2),(2,2);
insert into sys_role_privilege values(1,1),(1,2),(1,3),(2,4),(2,5);

此处没有创建表之间的外键关系。对于表之间的关系,我们可以通过业务逻辑来进行限制。
创建实体类

MyBatis默认遵循“下划线转驼峰”命名方式,所以在创建实体类时一般都按照这种方式进行创建。而具体采用什么命名方式并不重要,在我们使用对象的时候,可以通过resultMap对数据库的列和类的字段配置隐射关系。

用户类SysUser

package mybatis.simple.model;

import java.util.Arrays;
import java.util.Date;

public class SysUser {

private Long id;
private String userName;
private String userPassword;
private String userEmail;
private String userInfo;
private byte[] headImg;
private Date createTime;

public SysUser() {
    super();
}

public SysUser(Long id, String userName, String userPassword, String userEmail, String userInfo, byte[] headImg,
        Date createTime) {
    super();
    this.id = id;
    this.userName = userName;
    this.userPassword = userPassword;
    this.userEmail = userEmail;
    this.userInfo = userInfo;
    this.headImg = headImg;
    this.createTime = createTime;
}

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getUserName() {
    return userName;
}

public void setUserName(String userName) {
    this.userName = userName;
}

public String getUserPassword() {
    return userPassword;
}

public void setUserPassword(String userPassword) {
    this.userPassword = userPassword;
}

public String getUserEmail() {
    return userEmail;
}

public void setUserEmail(String userEmail) {
    this.userEmail = userEmail;
}

public String getUserInfo() {
    return userInfo;
}

public void setUserInfo(String userInfo) {
    this.userInfo = userInfo;
}

public byte[] getHeadImg() {
    return headImg;
}

public void setHeadImg(byte[] headImg) {
    this.headImg = headImg;
}

public Date getCreateTime() {
    return createTime;
}

public void setCreateTime(Date createTime) {
    this.createTime = createTime;
}

@Override
public String toString() {
    return "SysUser [id=" + id + ", userName=" + userName + ", userPassword=" + userPassword + ", userEmail="
            + userEmail + ", userInfo=" + userInfo + ", headImg=" + Arrays.toString(headImg) + ", createTime="
            + createTime + "]";
}

}

[点击并拖拽以移动]

角色类SysRole

package mybatis.simple.model;

import java.sql.Date;

public class SysRole {
private Long id;
private String role_name;
private Integer enabled;
private Long create_by;
private Date create_time;

public SysRole() {
    super();
}

public SysRole(Long id, String role_name, Integer enabled, Long create_by, Date create_time) {
    super();
    this.id = id;
    this.role_name = role_name;
    this.enabled = enabled;
    this.create_by = create_by;
    this.create_time = create_time;
}

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getRole_name() {
    return role_name;
}

public void setRole_name(String role_name) {
    this.role_name = role_name;
}

public Integer getEnabled() {
    return enabled;
}

public void setEnabled(Integer enabled) {
    this.enabled = enabled;
}

public Long getCreate_by() {
    return create_by;
}

public void setCreate_by(Long create_by) {
    this.create_by = create_by;
}

public Date getCreate_time() {
    return create_time;
}

public void setCreate_time(Date create_time) {
    this.create_time = create_time;
}

@Override
public String toString() {
    return "SysRole [id=" + id + ", role_name=" + role_name + ", enabled=" + enabled + ", create_by=" + create_by
            + ", create_time=" + create_time + "]";
}

}

[点击并拖拽以移动]

权限类SysPrivilege

package mybatis.simple.model;

public class SysPrivilege {

private Long id;
private String privilege_name;
private String privilege_uri;

public SysPrivilege() {
    super();
}

public SysPrivilege(Long id, String privilege_name, String privilege_uri) {
    super();
    this.id = id;
    this.privilege_name = privilege_name;
    this.privilege_uri = privilege_uri;
}

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public String getPrivilege_name() {
    return privilege_name;
}

public void setPrivilege_name(String privilege_name) {
    this.privilege_name = privilege_name;
}

public String getPrivilege_uri() {
    return privilege_uri;
}

public void setPrivilege_uri(String privilege_uri) {
    this.privilege_uri = privilege_uri;
}

@Override
public String toString() {
    return "SysPrivilege [id=" + id + ", privilege_name=" + privilege_name + ", privilege_uri=" + privilege_uri
            + "]";
}

}

[点击并拖拽以移动]

用户角色关系类SysUserRole

package mybatis.simple.model;

public class SysUserRole {
private Long user_id;
private Long role_id;

public SysUserRole() {
    super();
}

public SysUserRole(Long user_id, Long role_id) {
    super();
    this.user_id = user_id;
    this.role_id = role_id;
}

public Long getUser_id() {
    return user_id;
}

public void setUser_id(Long user_id) {
    this.user_id = user_id;
}


public Long getRole_id() {
    return role_id;
}

public void setRole_id(Long role_id) {
    this.role_id = role_id;
}

@Override
public String toString() {
    return "SysUserRole [user_id=" + user_id + ", role_id=" + role_id + "]";
}

}

[点击并拖拽以移动]

角色权限关系类

package mybatis.simple.model;

public class SysRolePrivilege {
private Long role_id;
private Long privilege;

public SysRolePrivilege() {
    super();
}

public SysRolePrivilege(Long role_id, Long privilege) {
    super();
    this.role_id = role_id;
    this.privilege = privilege;
}

public Long getRole_id() {
    return role_id;
}

public void setRole_id(Long role_id) {
    this.role_id = role_id;
}

public Long getPrivilege() {
    return privilege;
}

public void setPrivilege(Long privilege) {
    this.privilege = privilege;
}

@Override
public String toString() {
    return "SysRolePrivilege [role_id=" + role_id + ", privilege=" + privilege + "]";
}

}

[点击并拖拽以移动]

在完成上面5个实体类的创建之后,下面我们开始MyBatis XML方式的基本用法。
使用XML方式

MyBatis的真正强大之处在于它的映射语句,由于他的映射语句异常强大,映射器的XML文件就显得相对简单。而MyBatis3.0相比2.0版本的一个最大变化,就是支持使用接口的来调用方法。

在【MyBatis修炼之二】中我们使用的是SqlSession通过命名空间调用MyBatis方法,我们需要用到命名空间和方法id组成的字符串来调用相应的方法。而当参数多于1个的时候,需要将参数放到一个Map对象中。通过Map传递多个参数,使用起来很不方便。

使用接口调用的方式就会方便很多,MyBatis使用Java的动态代理可以直接通过接口来调用相应的方法,不需要提供接口的实现类,并且也不需要使用SqlSession以通过命名空间间接调用。同时,当有多个参数时,可以通过在参数之前添加@Param("fieldName")设置参数的名字,这样我们就可以不用手动构造Map参数了,尤其是在Spring中使用的时候,可以配置为自动扫描所有的接口类,直接将接口注入需要用到的地方。

接下来我们便开始使用MyBatis的XML方式。
首先,在src/main/resource的mybatis.simple.mapper目录下创建和我们创建的5个表对应的XML文件,分别为UserMapper.xml、RoleMapper.xml、PrivilegeMapper.xml、UserRoleMapper.xml、RolePrivilegeMapper.xml,然后在src/main/java下面创建包mybatis.simple.mapper,接着在该包下创建XML文件对应的接口类,分别为UserMapper.java、RoleMapper.java、PrivilegeMapper.java、UserRoleMapper.java、RolePrivilegeMapper.java。
下面以用户表对应的Mapper接口UserMapper.java为例进行说明。

package mybatis.simple.mapper;

public interface UserMapper {

}

[点击并拖拽以移动]

现在这些文件都是空的,后续使用的时候我们将陆续向其中添加接口方法。创建了所有的接口文件之后,打开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">



我们特别需要注意的地方是根标签namespace属性。当Mapper接口和XML文件关联的时候,命名空间namespace的值就需要配置成接口的权限定名称(包名+接口类名),MyBatis内部将通过这个值将接口和XML关联在一起。按照相同的方法创建另外4个Mapper.xml文件。准备好这些XML映射文件后,我们需要在mybatis-config.xml配置文件中的mappers元素中配置所有的mapper,部分配置代码如下。








[点击并拖拽以移动]

这种配置方式需要将所有的映射文件一一列举出来,如果增加了新的映射文件,还需要在此处进行配置,操作起来比较麻烦,因为此处所有的XML映射文件都多有对应的Mapper接口,所有还有一种更简单的配置方式:

<mappers>
    <package name="mybatis.simple.mapper"/>
</mappers>

[点击并拖拽以移动]

这种配置会先查找mybatis.simple.mapper包下的所有接口,然后循环对接口进行如下操作:
① 判断接口对应的命名空间是否已经存在,如果存在就抛出异常,不存在就继续进行接下来的操作。
② 加载接口对应的XML映射文件,将接口权限定名转换为路径,例如,将接口mybatis.simple.mapper.UserMapper转换为mybatis/simple/mapper/UserMapper.xml,以.xml为后缀搜索XML资源,如果找打就解析XML。
③ 处理接口中的注解方法。
注意: 使用Mapper接口包名批量加载的方式时,需要将Mapper接口类名和Mapper.xml映射文件名称保持一致并且包名一致(Mapper.xml可以放在src/main/resource目录下,但是需要和接口类的包名保持一致,Mapper.xml也可以和接口类在同一个包下),因此直接配置接口包名,就可以自动扫描包下的接口和XML映射文件

完整mybatis-config.xml文件如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">































[点击并拖拽以移动]
select用法

我们执行查询操作,使用MyBatis,我们只需要在XML中添加select元素,然后写上SQL语句,然后再做一些简单的配置,就可以将查询的结果直接映射到对象中。

希望对大家有所帮助,有用的话点赞给我支持!

相关文章
|
2月前
|
存储 前端开发 架构师
阿里资深架构师带你深入浅出JVM!
JVM = 类加载器(classloader) + 执行引擎(execution engine) + 运行时数据区域(runtime data area)
40 1
|
22天前
|
敏捷开发 监控 前端开发
Spring+SpringMVC+Mybatis的分布式敏捷开发系统架构
Spring+SpringMVC+Mybatis的分布式敏捷开发系统架构
53 0
|
1月前
|
存储 缓存 Java
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制
什么!?实战项目竟然撞到阿里面试的原题!???关于MyBatis Plus的缓存机制
|
2月前
|
架构师 Java API
阿里P7架构师带你深入剖析synchronized的实现原理
显示锁ReentrantLock的内部同步依赖于AQS(AbstractQueuedSynchronizer),因此,分析ReentrantLock必然涉及AQS。
19 1
|
2月前
|
存储 监控 安全
阿里云云通信短信服务安全之安全架构
阿里云云通信长期致力于通过多种渠道向客户透明服务相关情况。客户一般可通过阿里云官网提出对阿里云云通信相关资质、服务使用情况、产品说明等信息,我们将7*24小时不间断处理您的建议与咨询。对于客户合理的要求,阿里云云通信服务团队均会及时响应客户的需求。同时,阿里云云通信也在探索更多增加透明度的方式,如对公邮箱、线上查询接口、钉钉服务客户群等。
|
10天前
|
API 数据库 开发者
构建高效可靠的微服务架构:后端开发的新范式
【4月更文挑战第8天】 随着现代软件开发的复杂性日益增加,传统的单体应用架构面临着可扩展性、维护性和敏捷性的挑战。为了解决这些问题,微服务架构应运而生,并迅速成为后端开发领域的一股清流。本文将深入探讨微服务架构的设计原则、实施策略及其带来的优势与挑战,为后端开发者提供一种全新视角,以实现更加灵活、高效和稳定的系统构建。
18 0
|
24天前
|
负载均衡 测试技术 持续交付
高效后端开发实践:构建可扩展的微服务架构
在当今快速发展的互联网时代,后端开发扮演着至关重要的角色。本文将重点探讨如何构建可扩展的微服务架构,以及在后端开发中提高效率的一些实践方法。通过合理的架构设计和技术选型,我们可以更好地应对日益复杂的业务需求,实现高效可靠的后端系统。
|
25天前
|
监控 持续交付 API
构建高效可扩展的微服务架构
在当今快速迭代和竞争激烈的软件市场中,构建一个高效、可扩展且易于维护的后端系统变得尤为重要。微服务架构作为一种流行的分布式系统设计方式,允许开发者将应用程序划分为一系列小型、自治的服务,每个服务负责执行特定的业务功能。本文将探讨如何利用现代技术栈搭建一个符合这些要求的微服务架构,并讨论其潜在的挑战与解决方案。我们将涵盖服务划分策略、容器化、服务发现、API网关、持续集成/持续部署(CI/CD)以及监控和日志管理等关键主题,以帮助读者构建出既可靠又灵活的后端系统。
|
9天前
|
Kubernetes 安全 Java
构建高效微服务架构:从理论到实践
【4月更文挑战第9天】 在当今快速迭代与竞争激烈的软件市场中,微服务架构以其灵活性、可扩展性及容错性,成为众多企业转型的首选。本文将深入探讨如何从零开始构建一个高效的微服务系统,覆盖从概念理解、设计原则、技术选型到部署维护的各个阶段。通过实际案例分析与最佳实践分享,旨在为后端工程师提供一套全面的微服务构建指南,帮助读者在面对复杂系统设计时能够做出明智的决策,并提升系统的可靠性与维护效率。
|
19天前
|
存储 监控 Kubernetes
探索微服务架构下的系统监控策略
在当今软件开发领域,微服务架构因其灵活性、可扩展性和容错性而日益受到青睐。然而,这种架构的复杂性也为系统监控带来了新的挑战。本文旨在探讨在微服务环境下实现有效系统监控的策略,以及如何利用这些策略来确保系统的健壮性和性能。我们将从监控的关键指标入手,讨论分布式追踪的重要性,并分析不同的监控工具和技术如何协同工作以提供全面的系统视图。