MyBatis-02 MyBatis XML方式概述及配置步骤

概述

我们通过一个简单的权限控制需求,采用RBAC(Role-Based Access Control基于角色的访问控制)方式,通过这个示例我们来学习 MyBatis XML方式的基本用法。


一个简单的权限控制需求

需求: 一个用户拥有若干角色,一个角色拥有若干权限。 权限就是对摸个资源或者模块的某种操作(CRUD). 这样就构成了“用户-角色-权限”的授权模型。

在这种模型中,用户与角色、角色与权限,一般都是多对多的关系

我们先来看下数据模型

这里写图片描述


创建数据库表

5张表,创建在mysql数据库中。

-- ----------------------------
-- Table structure for sys_privilege
-- ----------------------------
DROP TABLE IF EXISTS `sys_privilege`;
CREATE TABLE `sys_privilege` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '权限ID',
  `privilege_name` varchar(50) DEFAULT NULL COMMENT '权限名称',
  `privilege_url` varchar(200) DEFAULT NULL COMMENT '权限URL',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='权限表';

-- ----------------------------
-- Records of sys_privilege
-- ----------------------------
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');

-- ----------------------------
-- Table structure for sys_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_role`;
CREATE TABLE `sys_role` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '角色ID',
  `role_name` varchar(50) DEFAULT NULL COMMENT '角色名',
  `enabled` int(11) DEFAULT NULL COMMENT '有效标志',
  `create_by` bigint(20) DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT='角色表';

-- ----------------------------
-- Records of sys_role
-- ----------------------------
INSERT INTO `sys_role` VALUES ('1', '管理员', '1', '1', SYSDATE());
INSERT INTO `sys_role` VALUES ('2', '普通用户', '1', '1', SYSDATE());

-- ----------------------------
-- Table structure for sys_role_privilege
-- ----------------------------
DROP TABLE IF EXISTS `sys_role_privilege`;
CREATE TABLE `sys_role_privilege` (
  `role_id` bigint(20) DEFAULT NULL COMMENT '角色ID',
  `privilege_id` bigint(20) DEFAULT NULL COMMENT '权限ID'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色权限关联表';

为了方便对表进行直接操作,此处没有创建表之间的外键关系。 对于表之间的关系,会通过业务逻辑来进行限制


-- ----------------------------
-- Records of sys_role_privilege
-- ----------------------------
INSERT INTO `sys_role_privilege` VALUES ('1', '1');
INSERT INTO `sys_role_privilege` VALUES ('1', '3');
INSERT INTO `sys_role_privilege` VALUES ('1', '2');
INSERT INTO `sys_role_privilege` VALUES ('2', '4');
INSERT INTO `sys_role_privilege` VALUES ('2', '5');

-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名',
  `user_password` varchar(50) DEFAULT NULL COMMENT '密码',
  `user_email` varchar(50) DEFAULT 'test@artisan.com' COMMENT '邮箱',
  `user_info` text COMMENT '简介',
  `head_img` blob COMMENT '头像',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1035 DEFAULT CHARSET=utf8 COMMENT='用户表';

-- ----------------------------
-- Records of sys_user
-- ----------------------------
INSERT INTO `sys_user` VALUES ('1', 'admin', '123456', 'admin@artisan.com', '管理员用户', 0x1231231230, SYSDATE());
INSERT INTO `sys_user` VALUES ('1001', 'test', '123456', 'test@artisan.com', '测试用户', 0x1231231230, SYSDATE());
-- ----------------------------
-- Table structure for sys_user_role
-- ----------------------------
DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
  `user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
  `role_id` bigint(20) DEFAULT NULL COMMENT '角色ID'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户角色关联表';

为了方便对表进行直接操作,此处没有创建表之间的外键关系。 对于表之间的关系,会通过业务逻辑来进行限制



-- ----------------------------
-- Records of sys_user_role
-- ----------------------------
INSERT INTO `sys_user_role` VALUES ('1', '1');
INSERT INTO `sys_user_role` VALUES ('1', '2');
INSERT INTO `sys_user_role` VALUES ('1001', '2');

创建实体类

MyBatis默认遵循“下面线转驼峰”命名方式的规则,所以在创建实体类时一般都按照这种方式进行创建。

首先看下用户表对应的实体类SysUser的代码

package com.artisan.mybatis.xml.domain;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 
 * 
 * @ClassName: SysUser
 * 
 * @Description: 用户表
 * 
 * @author: Mr.Yang
 * 
 * @date: 2018年4月13日 下午9:24:21
 */
public class SysUser implements Serializable {

    private static final long serialVersionUID = 5736486618394472355L;

    /**
     * 用户ID
     */
    private Long id;

    /**
     * 用户名
     */
    private String userName;

    /**
     * 密码
     */
    private String userPassword;

    /**
     * 邮箱
     */
    private String userEmail;

    /**
     * 简介
     */
    private String userInfo;

    /**
     * 头像
     */
    private byte[] headImg;

    /**
     * 创建时间
     */
    private Date createTime;

    /**
     * 用户角色
     */
    private SysRole sysRole;

    /**
     * 用户的角色集合
     */
    private List<SysRole> roleList;

    //  省略setter和getter方法

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

}

对于SysUser实体类,首先需要注意的是命名方式,它的类名和属性名都采用了“下面线转驼峰”方式。 具体采用什么样的命名方式并不重要(方式一致即可)。 在后面使用这些对象的时候,可以通过resultMap对数据库中的列和类的字段配置映射关系

在 MyBatis中,关于数据库字段和Java类型的对应关系,不需要可以的去记,但需要注意的一个特殊的类型,byte[] ,这个类型一般对应数据库中的BLOB、LONGVARBINARY以及一些二进制流相关的字段类型

注意: 由于Java中的基本类型会有默认值,例如当某个类中存在private int age字段时,创建这个类时,age会有个默认值0。 当使用age属性时,它总会有值。 因此在某些情况下,便无法实现age为null . 并且在动态SQL的部分,如果使用age !=null 进行判断,结果总会为true,因而会导致很多隐藏的问题。

所以在实体类中不要使用基本类型。 基本类型包括:byte、int、short、long、float、double、char、boolean


SysRole

package com.artisan.mybatis.xml.domain;

import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * 
 * 
 * @ClassName: SysRole
 * 
 * @Description: 角色表
 * 
 * @author: Mr.Yang
 * 
 * @date: 2018年4月13日 下午9:29:31
 */
public class SysRole implements Serializable {
    private static final long serialVersionUID = 6320941908222932112L;
    /**
     * 角色ID
     */
    private Long id;
    /**
     * 角色名
     */
    private String roleName;
    /**
     * 有效标志
     */
    private Integer enabled;
    /**
     * 创建人
     */
    private String createBy;
    /**
     * 创建时间
     */
    private Date createTime;


    /**
     * 用户信息
     */
    private SysUser user;

    /**
     * 角色包含的权限列表
     */
    List<SysPrivilege> privilegeList;

    // 省略setter和getter

    @Override
    public String toString() {
        return "SysRole [id=" + id + ", roleName=" + roleName + ", enabled=" + enabled + ", createBy=" + createBy + ", createTime=" + createTime + ", user=" + user + ", privilegeList="
                + privilegeList + "]";
    }


}

SysUserRole

package com.artisan.mybatis.xml.domain;

/**
 * 
 * 
 * @ClassName: SysUserRole
 * 
 * @Description: 用户角色关联表
 * 
 * @author: Mr.Yang
 * 
 * @date: 2018年4月13日 下午9:44:31
 */
public class SysUserRole {
    /**
     * 用户ID
     */
    private Long userId;
    /**
     * 角色ID
     */
    private Long roleId;

    // 省略setter和getter

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

}

SysPrivilege

package com.artisan.mybatis.xml.domain;

import java.io.Serializable;

/**
 * 
 * 
 * @ClassName: SysPrivilege
 * 
 * @Description: 权限表
 * 
 * @author: Mr.Yang
 * 
 * @date: 2018年4月13日 下午9:45:15
 */
public class SysPrivilege implements Serializable {

    private static final long serialVersionUID = 6315662516417216377L;
    /**
     * 权限ID
     */
    private Long id;
    /**
     * 权限名称
     */
    private String privilegeName;
    /**
     * 权限URL
     */
    private String privilegeUrl;

    // 省略setter和getter

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

}

SysRolePrivilege

package com.artisan.mybatis.xml.domain;

/**
 * 
 * 
 * @ClassName: SysRolePrivilege
 * 
 * @Description: 角色权限关联表
 * 
 * @author: Mr.Yang
 * 
 * @date: 2018年4月13日 下午9:46:46
 */
public class SysRolePrivilege {
    /**
     * 角色ID
     */
    private Long roleId;
    /**
     * 权限ID
     */
    private Long privilegeId;

    // 省略setter和getter

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

}

创建实体类的过程比较枯燥,后面可以通过 MyBatis官方提供的工具 MyBatis Generator( MyBatis代码生成器,简称MBG)根据数据库表的信息自动生成这些类,减少工作量。


XML方式概述及步骤

* MyBatis3.0比2.0一个最大的变化,就是支持使用接口来调用方法。*

以前使用SqlSession通过命名空间调用 MyBatis的方法时,首先需要用到命名空间和方法id组成的字符串来调用对应的方法。 当参数多于1个的时候,需要将参数放到一个Map对象中,通过Map传递多个参数,使用起来不方便,而且无法避免很多重复的代码。

使用接口调用方式就会方便很多, MyBatis使用Java的动态代理可以直接通过接口来调用相应的方法,不需要提供接口的实现类,更不需要在实现类中使用SqlSession以命名空间间接调用。 另外,当有个多个参数的时候,通过参数注解@Parma设置参数的名字省去了手工构造Map参数的过程。 尤其在Spring中使用的时候 ,可以配置为自动扫描所有的接口类,直接将接口注入到需要用到的地方。

我们来看下如何使用 MyBatis的XML方式

1. 首先在src/main/resources下com.artisan.mybatis.xml.mapper目录下创建5个表各自对应的XML文件

这里写图片描述

2. 然后在src/main/java先创建包com.artisan.mybatis.xml.mapper,接着在该包下面创建XML文件对应的接口类

这里写图片描述

3. Mapper.xml 如何编写,我们在 MyBatis-01 MyBatis入门篇中已经简单介绍过了,下面我们以用户表对应的Mapper接口 UserMapper.java为例来演示下接口的编写

package com.artisan.mybatis.xml.mapper;

public interface UserMapper {

}

到目前为止,Mapper接口和对应的XML文件都是空的,后续逐步完善接口方法。

4. 打开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接口和XML文件关联的时候, namespace的值就需要配置成接口的全限定名称 -->
<mapper namespace="com.artisan.mybatis.xml.mapper.UserMapper">

</mapper>

需要注意的是mapper标签的namespace属性。 当Mapper接口和XML文件关联的时候,命名空间namespace的值就需要配置成接口的全限定名称。

比如UserMapper接口对应的com.artisan.mybatis.xml.mapper.UserMapper , Mybatis内部就是通过这个值将接口和XML关联起来的。 具体原理后续分析。

按照相同的方式将其他4个Mapper.xml编写完成

5.准备好这几个XML映射文件后,需要在 MyBatis全局配置文件中的mapper元素配置所有的mapper

    <!-- 逐一配置,比较繁琐,容易遗漏,接口方式不推荐 -->
        <mapper resource="com/artisan/mybatis/xml/mapper/UserMapper.xml"/>
        <mapper resource="com/artisan/mybatis/xml/mapper/UserRoleMapper.xml"/>
        <mapper resource="com/artisan/mybatis/xml/mapper/RoleMapper.xml"/>
        <mapper resource="com/artisan/mybatis/xml/mapper/PrivilegeMapper.xml"/>
        <mapper resource="com/artisan/mybatis/xml/mapper/RolePrivilegeMapper.xml"/>

这种方式需要将所有的映射文件一一列举出来,如果增加了新的映射文件,还需要注意在此处进行配置,不推荐。

因为此处所有的XML映射文件都有对应的Mapper接口,所以有一种更加简单的配置方式

    <!-- 推荐:通过包的方式配置,mybatis会先查找对应包下的所有的接口 -->
        <package name="com.artisan.mybatis.xml.mapper"/>

这种配置方式会先查找com.artisan.mybatis.xml.mapper包下的所有接口,循环对接口进行如下操作:

1. 判断接口对应的命名空间是否已经存在,存在抛出异常,不存在就继续进行接下来的操作
2. 加载接口对应的XML映射文件,将接口全限定名转换为路径,比如将接口com.artisan.mybatis.xml.mapper.UserMapper转换为com/artisan/mybatis/xml/mapper/UserMapper.xml. 以.xml为后缀搜索xml资源,如果找到就解析xml
3. 处理接口中的注解方法

因为这里的接口和xml映射文件完全符合上面操作的第二点,因此直接配置包名就能够自动扫描包下的接口和XML映射文件,省去了很多麻烦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小工匠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值