热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Mybatis基本查询准备

之前我们说过,MyBatis是一款优秀的支持自定义SQL查询、存储过程和高级映射的持久层框架,而且,与JDBC相比,MyBa

之前我们说过,MyBatis是一款优秀的支持自定义SQL查询、存储过程和高级映射的持久层框架,而且,与JDBC相比,MyBatis简化了相关的代码,使得代码更加简洁。所以,MyBatis最常用的地方就是结合数据库一起进行相关CRUD操作。在正式进行增删改查操作前,我们需要准备一下需要的数据库和其他文件。

我们假设一个场景,来设定一个简单的权限控制需求,采用RBAC(Role-Based Access Control,基于角色的访问控制方式),这个简单的权限管理将会是我后续文章的基础示例。那么这个权限管理都有哪些需求呢?我们结合现实考虑一下,一个用户通常拥有若干个角色,一个角色通常也拥有若干个权限(即对某种资源的某种基于但不限于增删改查的操作),于是就构成了“用户-角色-权限”的模型。在这种模型中,用户与角色之间是一对多的关系,即一个用户对应拥有多种角色,角色与权限之间也是一对多的关系。在现实中也常有这样的场景,普通用户一般拥有登录和查询等基础权限,而管理员除了拥有普通用户拥有的登录和查询等基础权限外,它还可以对普通用户进行管理,即有权决定谁是普通用户,或是可以对普通用户进行增删操作。

根据我们描述的需求,显而易见会有五张数据表产生,即用户表、角色表和权限表,以及用户角色联系表和角色权限联系表。那么接下来我们就在数据库中创建这五张表,创建代码如下:

//创建数据库study
CREATE DATABASE study;
USE study;//创建用户表t_user
CREATE TABLE t_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 t_user COMMENT '用户表';//创建角色表t_role
CREATE TABLE t_role(
id BIGINT NOT NULL auto_increment COMMENT '角色ID',
role_name VARCHAR(50) COMMENT '角色名',
enabled INT COMMENT '有效标志',
create_author BIGINT COMMENT '创建者',
create_time datetime COMMENT '创建时间',
PRIMARY KEY(id)
);
ALTER TABLE t_role COMMENT '角色表';//创建权限表t_privilege
CREATE TABLE t_privilege(
id BIGINT NOT NULL auto_increment COMMENT '权限ID',
privilege_name VARCHAR(50) COMMENT '权限名称',
privilege_url VARCHAR(50) COMMENT '权限url',
PRIMARY KEY(id)
);
ALTER TABLE t_privilege COMMENT '权限表';//创建用户角色联系表t_user_role
CREATE TABLE t_user_role(
user_id BIGINT COMMENT '用户ID',
role_id BIGINT COMMENT '角色ID'
);
ALTER TABLE t_user_role COMMENT '用户角色关联表';//创建角色权限联系表t_role_privilege
CREATE TABLE t_role_privilege(
role_id BIGINT COMMENT '角色ID',
privilege_id BIGINT COMMENT '权限ID'
);
ALTER TABLE t_role_privilege COMMENT '角色权限关联表';

我们要习惯使用SQL语句来进行数据库表的创建,尽量减少那种直接在数据库中创建表的方式。我们看到,上面创建数据库表的代码中,很明显有COMMENT,其实COMMENT就相当于注释、备注的意思,即对数据库表中的各个字段进行解释,我们以后在创建数据库表的时候也要多多使用这种有好的创建数据库表方式。

创建完成后的数据库中的五张表的结构是这样的:

以上这五张表示的字段可以根据自身情况自行决定,包括表明,各字段的命名都可自行改变。本人的这五张表的结构完全参考自刘增辉老师的《MyBatis从入门到精通》一书。

接下来我们给这五张表插入一些数据,为了后续程序运行需要,每张表插入一两条数据即可,不必过多。当然如果有自己的想法,则可以根据需要多多插入几条数据。

//给t_user用户表插入数据
INSERT INTO t_user VALUES
('1001','张三','123123','123456@study','我是张三',NULL,NOW());
INSERT INTO t_user VALUES
('1002','李四','123456','456456@study','我是李四',NULL,NOW());//给t_role角色表插入数据
INSERT INTO t_role VALUES('1','管理员','1','1',NOW());
INSERT INTO t_role VALUES('2','普通用户','1','1',NOW());//给t_privilege权限表插入数据
INSERT INTO t_privilege VALUES('1','用户管理','/users');
INSERT INTO t_privilege VALUES('2','角色管理','/roles');
INSERT INTO t_privilege VALUES('3','系统日志','/logs');
INSERT INTO t_privilege VALUES('4','人员维护','/persons');
INSERT INTO t_privilege VALUES('5','单位维护','/companiess');//给t_user_role用户角色关联表插入数据
INSERT INTO t_user_role VALUES('1001','1');
INSERT INTO t_user_role VALUES('1001','2');
INSERT INTO t_user_role VALUES('1002','2');//给t_role_privilege角色权限关联表插入数据
INSERT INTO t_role_privilege VALUES('1','1');
INSERT INTO t_role_privilege VALUES('1','3');
INSERT INTO t_role_privilege VALUES('1','2');
INSERT INTO t_role_privilege VALUES('2','4');
INSERT INTO t_role_privilege VALUES('2','5');

插入若干条数据之后的五张表展示如下:

                    

上述插入数据的方法在后续工作中也是用得到的,之前说过,要习惯使用SQL语句!!!结合插入的数据,我们有以下信息:


  • 用户ID为1001的张三,既是管理员,也是普通用户,所以拥有用户管理、角色管理、系统日志、人员维护、单位维护的所有权限;
  • 用户ID为1002的李四,只是普通用户,所以只拥有人员维护和单位维护两个权限。

以上数据仅为后续工作工作,并不具有实际意义,请不要对号入座。

接下来,我们在IDEA中新建一个maven项目,命名方式自选,本人在这里命名为Mybatis-CRUD。然后,先在pom.xml文件中导入相关依赖。完整的pom.xml文件如下:

4.0.0org.exampleMybatis-CRUD1.0-SNAPSHOTmysqlmysql-connector-java8.0.21org.mybatismybatis3.5.5junitjunit4.13test

然后,我们还需要完成上面说过的五个数据库表的实体类。为便于管理,我们在src/main/java目录下先创建一个包,命名为pojo,然后将五个数据库表的实体类(分别命名为User、Role、Privileg、UserRole、RolePrivilege)放在这个pojo包下。需要说明的是,MyBatis默认是遵循“下划线转驼峰”的命名方式的。怎么说呢,就是如果我们在数据库中创建表的时候各字段的命名是以下划线的方式来命名的,那么在MyBatis中,我们应该遵循MyBatis的命名方式,使用驼峰命名的方法。举个例子,我们在t_user表中对于用户名的命名方式是user_name的下划线方式的,那么在实体类中,我们使用userName小驼峰的命名方式。其实,为了方便和统一,我们也可以将数据库表中的字段以小驼峰的方式命名,避免在后续工作中混淆。

User实体类的代码如下,包含了User的属性和各属性的get()和set()方法,以及toString()方法。写toString()方法是为了将查询结果成功输出到控制台。

package pojo;import java.util.Arrays;
import java.util.Date;public class User {private Long id; //用户IDprivate String userName; //用户名private String userPassword; //密码private String userEmail; //Emailprivate String userInfo; //简介private byte[] headImg; //头像private Date createTime; //创建时间public User() {}public User(Long id, String userName, String userPassword,String userEmail, String userInfo, byte[] headImg, Date createTime) {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;}@Overridepublic String toString() {return "User{" +"id=" + id +", userName='" + userName + '\'' +", userPassword='" + userPassword + '\'' +", userEmail='" + userEmail + '\'' +", userInfo='" + userInfo + '\'' +", headImg=" + Arrays.toString(headImg) +", createTime=" + createTime +'}';}
}

Role实体类的代码如下:

package pojo;import java.util.Date;public class Role {private Long id; //角色IDprivate String roleName; //角色名private int enabled; //有效标志private Long createAuthor; //创建者private Date createTime; //创建时间public Role() {}public Role(Long id, String roleName, int enabled,Long createAuthor, Date createTime) {this.id = id;this.roleName = roleName;this.enabled = enabled;this.createAuthor = createAuthor;this.createTime = createTime;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getRoleName() {return roleName;}public void setRoleName(String roleName) {this.roleName = roleName;}public int getEnabled() {return enabled;}public void setEnabled(int enabled) {this.enabled = enabled;}public Long getCreateAuthor() {return createAuthor;}public void setCreateAuthor(Long createAuthor) {this.createAuthor = createAuthor;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}@Overridepublic String toString() {return "Role{" +"id=" + id +", roleName='" + roleName + '\'' +", enabled=" + enabled +", createAuthor=" + createAuthor +", createTime=" + createTime +'}';}
}

Privilege实体类代码如下:

package pojo;public class Privilege {private Long id; //权限IDprivate String privilegeName; //权限名称private String privilegeUrl; //权限urlpublic Privilege() {}public Privilege(Long id, String privilegeName, String privilegeUrl) {this.id = id;this.privilegeName = privilegeName;this.privilegeUrl = privilegeUrl;}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getPrivilegeName() {return privilegeName;}public void setPrivilegeName(String privilegeName) {this.privilegeName = privilegeName;}public String getPrivilegeUrl() {return privilegeUrl;}public void setPrivilegeUrl(String privilegeUrl) {this.privilegeUrl = privilegeUrl;}@Overridepublic String toString() {return "Privilege{" +"id=" + id +", privilegeName='" + privilegeName + '\'' +", privilegeUrl='" + privilegeUrl + '\'' +'}';}
}

UserRole实体类代码如下:

package pojo;public class UserRole {private Long userId; //用户IDprivate Long roleId; //角色IDpublic UserRole() {}public UserRole(Long userId, Long roleId) {this.userId = userId;this.roleId = roleId;}public Long getUserId() {return userId;}public void setUserId(Long userId) {this.userId = userId;}public Long getRoleId() {return roleId;}public void setRoleId(Long roleId) {this.roleId = roleId;}@Overridepublic String toString() {return "UserRole{" +"userId=" + userId +", roleId=" + roleId +'}';}
}

RolePrivilege实体类代码如下:

package pojo;public class RolePrivilege {private Long roleId; //角色IDprivate Long privilegeId; //权限IDpublic RolePrivilege() {}public RolePrivilege(Long roleId, Long privilegeId) {this.roleId = roleId;this.privilegeId = privilegeId;}public Long getRoleId() {return roleId;}public void setRoleId(Long roleId) {this.roleId = roleId;}public Long getPrivilegeId() {return privilegeId;}public void setPrivilegeId(Long privilegeId) {this.privilegeId = privilegeId;}@Overridepublic String toString() {return "RolePrivilege{" +"roleId=" + roleId +", privilegeId=" + privilegeId +'}';}
}

创建实体类的过程很枯燥,只是简单的工作重复做的过程。但是为了节省时间,我们可以使用Alt+Insert快捷键来快速选择我们要生成的构造函数以及get()和set()方法,以及toString()方法。具体操作方法为:在实体类中先写完各个属性,之后在实体类中(注意一定要在实体类中)鼠标右击选择Generate或者直接使用Alt+Insert快捷键进入选择界面,之后选择我们需要生成的函数类型就行。

当五个实体类都创建完成之后,我们来讨论一下MyBatis的映射语句,为后续程序编写做好准备。MyBatis的真正强大之处就在于它的映射语句,这也是MyBatis的魔力所在。由于它的映射语句异常强大,映射器的XML文件就显得相对简单。如果将其与具有相同功能的JDBC代码进行对比,就会发现,使用这种方法可节省大约95%的代码量。后续我们会使用到更多的xxxMapper文件和xxxMapper.xml文件。MyBatis通常使用接口配合XML文件使用,后续我们会体会到这种方式的工作流程的顺畅。不过在此之前呢,我们需要先配置一下MyBatis的核心配置文件,通常给它命名为Mybatis-config.xml,并放在src/main/resources文件下。其核心配置文件的内容如下:



其实我们不难发现,Mybatis核心配置文件中主要就是连接数据库的内容,什么连接数据库的驱动、用户名和密码之类的。

接下来,我们创建与数据库中的五个表相对应的各自的XML文件,分别命名为UserMapper.xml、RoleMapper.xml、PrivilegeMapper.xml、UserRoleMapper.xml、RolePrivilegeMapper.xml。同样,为了便于管理,我们选择将这五个xml文件放在一个Mapper包下统一管理,Mapper包需要我们自己创建,我们选择让其位于src/main/resources文件夹下。然后我们还需要这五个XML文件的对应的接口类,还是和上面一样,为了便于管理,我们将其放在新建包Interface下,位于src/main/java下,分别命名为UserMapper、RoleMapper、PrivilegeMapper、UserRoleMapper、RolePrivilegeMapper,全部都是接口类文件,.java类型的。可能这样命名为xxxMapper的命名方式不是很规范,放在名为Interface的包下也显得不是很规范,其实正确的应该放在dao文件夹下,但是由于我目前还未接触到数据持久层Dao层,所以暂时就命名一个不太规范的包吧。

那么此时这五个接口类的内容都是空的,后续我们会写一些增删改查的方法在里边。

//接口类UserMapper
package Interface;public interface UserMapper{}//接口类RoleMapper
package Interface;public interface RoleMapper{}//接口类PrivilegeMapper
package Interface;public interface PrivilegeMapper{}//接口类UserRoleMapper
package Interface;public interface UserRoleMapper{}//接口类RolePrivilegeMapper
package Interface;public interface RolePrivilegeMapper {}

接下来,我们再看看五个XML文件。其实此时我们还没有进行相关的查询呢,所以此时XML文件其实也是空的。

//UserMapper.xml

//RoleMapper.xml

//PrivilegeMapper.xml

//UserRoleMapper.xml

//RolePrivilegeMapper

我们需要注意的是根标签的namespace属性。当Mapper接口和XML文件关联的时候,命名空间namespace的值就需要配置成接口的全限定名称,例如UserMapper对应的Interface.UserMapper,Mybatis内部就是通过这个值将接口和XML关联起来的。

接下来,我们需要在Mybatis的配置文件Mybatis-config.xml中的mappers元素中配置所有的刚才写了的XML文件。


注意将写在里边,但写在外边。以上两种书写方式都能让XML文件和接口对应。但是第一种方式需要将所有映射文件一一列举出来,操作起来比较麻烦。第二种书写方式就看起来挺简单的,这种配置方式会先查找mapper包下所有的接口,并循环对接口以下操作:(1)判断接口对应的命名空间是否已经配置过,如果配置过就抛出异常,没有配置过就继续;(2)加载接口对应的XML文件,将接口的全限定名称转换为路径,即将接口Interface/UserMapper转换为mapper.UserMapper.xml,以.xml为后缀搜索XML资源,如果找到就解析XML。

增加内容之后的Mybatis-config.xml的全部内容为:



此时,我们对于正式的增删改查的准备工作已经完成。接下来,我们开始着手进行正式的增删改查工作。

需要注意的,本人在进行后续博文更新的时候,参照的内容和代码完全来自于刘增辉老师的《MyBatis从入门到精通》一书,书上的关于数据库的操作是非常连贯的,所以需要及时做好记录和注释,避免代码过多之后容易混乱。

 


推荐阅读
  • 本文介绍了一种轻巧方便的工具——集算器,通过使用集算器可以将文本日志变成结构化数据,然后可以使用SQL式查询。集算器利用集算语言的优点,将日志内容结构化为数据表结构,SPL支持直接对结构化的文件进行SQL查询,不再需要安装配置第三方数据库软件。本文还详细介绍了具体的实施过程。 ... [详细]
  • Windows7 64位系统安装PLSQL Developer的步骤和注意事项
    本文介绍了在Windows7 64位系统上安装PLSQL Developer的步骤和注意事项。首先下载并安装PLSQL Developer,注意不要安装在默认目录下。然后下载Windows 32位的oracle instant client,并解压到指定路径。最后,按照自己的喜好对解压后的文件进行命名和压缩。 ... [详细]
  • 在Oracle11g以前版本中的的DataGuard物理备用数据库,可以以只读的方式打开数据库,但此时MediaRecovery利用日志进行数据同步的过 ... [详细]
  • 解决.net项目中未注册“microsoft.ACE.oledb.12.0”提供程序的方法
    在开发.net项目中,通过microsoft.ACE.oledb读取excel文件信息时,报错“未在本地计算机上注册“microsoft.ACE.oledb.12.0”提供程序”。本文提供了解决这个问题的方法,包括错误描述和代码示例。通过注册提供程序和修改连接字符串,可以成功读取excel文件信息。 ... [详细]
  • 本文介绍了在使用Laravel和sqlsrv连接到SQL Server 2016时,如何在插入查询中使用输出子句,并返回所需的值。同时讨论了使用CreatedOn字段返回最近创建的行的解决方法以及使用Eloquent模型创建后,值正确插入数据库但没有返回uniqueidentifier字段的问题。最后给出了一个示例代码。 ... [详细]
  • mysql自动打开文件_让docker中的mysql启动时自动执行sql文件
    本文提要本文目的不仅仅是创建一个MySQL的镜像,而是在其基础上再实现启动过程中自动导入数据及数据库用户的权限设置,并且在新创建出来的容器里自动启动My ... [详细]
  • MySQL修改表结构操作命令总结【MySQL】
    数据库|mysql教程MySQL,修改表结构命令数据库-mysql教程表的结构如下:错误页面源码,ubuntu电脑自动休眠,爬虫造景视频,rapapiphp,廊坊seo开发lzwm ... [详细]
  •   《WindowsAzurePlatform系列文章目录》  本文将介绍如何在AzureSQLDatabase创建只读用户。  请先按照笔者之前的文章:AzureSQLDatabas ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • Oracle10g备份导入的方法及注意事项
    本文介绍了使用Oracle10g进行备份导入的方法及相关注意事项,同时还介绍了2019年独角兽企业重金招聘Python工程师的标准。内容包括导出exp命令、删用户、创建数据库、授权等操作,以及导入imp命令的使用。详细介绍了导入时的参数设置,如full、ignore、buffer、commit、feedback等。转载来源于https://my.oschina.net/u/1767754/blog/377593。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了sqlserver云存储和本地存储的区别,云存储是将数据存储在网络上,方便查看和调用;本地存储是将数据存储在电脑磁盘上,只能在存储的电脑上查看。同时提供了几种启动sqlserver的方法。此外,还介绍了如何导出数据库的步骤和工具。 ... [详细]
  • 本文主要复习了数据库的一些知识点,包括环境变量设置、表之间的引用关系等。同时介绍了一些常用的数据库命令及其使用方法,如创建数据库、查看已存在的数据库、切换数据库、创建表等操作。通过本文的学习,可以加深对数据库的理解和应用能力。 ... [详细]
  • destoon会员注册提示“数据校验失败(2)”解决方法【PHP】
    后端开发|php教程destoon,会员注册,数据校验失败,后端开发-php教程很多人在使用destoon建立一个B2B系统的时候,会在企业站注册企业用户的时候出现:“数据校验失败 ... [详细]
author-avatar
天生好客2602916983_826
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有