当前位置: 首页 > news >正文

SpringBoot第24讲:SpringBoot集成MySQL - MyBatis XML方式

SpringBoot第24讲:SpringBoot集成MySQL - MyBatis XML方式

上文介绍了用JPA方式的集成MySQL数据库,JPA方式在中国以外地区开发而言基本是标配,在国内MyBatis及其延伸框架较为主流。本文是SpringBoot第24讲,主要介绍MyBatis技栈的演化以及SpringBoot集成基础的MyBatis XML实现方式的实例。

文章目录

  • SpringBoot第24讲:SpringBoot集成MySQL - MyBatis XML方式
    • 1、准备知识
      • 1.1、什么是MyBatis?
      • 1.2、为什么说MyBatis是半自动ORM?
      • 1.3、MyBatis栈技术演进
        • 1、JDBC,自行封装 JDBCUtil
        • 2、IBatis
        • 3、MyBatis(目前我们项目处于这个阶段)
        • 4、MyBatis衍生:代码生成工具等
        • 5、Spring+MyBatis 基于注解的配置集成
        • 6、MyBatis-Plus
    • 2、简单示例
      • 2.1、准备DB和依赖配置
      • 2.2、Mapper文件
      • 2.3、定义dao
      • 2.4、定义Service接口和实现类
      • 2.5、controller
    • 3、示例源码

1、准备知识

需要了解MyBatis及MyBatis技术栈的演进,这对开发新手可以很好的构筑其知识体系。

1.1、什么是MyBatis?

MyBatis是一款优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。

  • MyBatis是一个优秀的基于java的持久层框架,它内部封装了jdbc,使开发者只需要关注sql语句本身,而不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。
  • MyBatis通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由MyBatis框架执行sql并将结果映射为java对象并返回。

MyBatis的主要设计目的就是让我们对执行SQL语句时对输入输出的数据管理更加方便,所以方便地写出SQL和方便地获取SQL的执行结果才是MyBatis的核心竞争力。

Mybatis的功能架构分为三层

  • API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
  • 数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作
  • 基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。

更多介绍可以参考:MyBatis3 官方网站

1.2、为什么说MyBatis是半自动ORM?

为什么说MyBatis是半自动ORM?

  • 什么是ORM

JDBC,ORM知识点可以参考SpringBoot第6讲:SpringBoot入门 - 添加内存数据库H2

  • 什么是全自动ORM

ORM框架可以根据对象关系模型直接获取,查询关联对象或者关联集合对象,简单而言使用全自动的ORM框架查询时可以不再写SQL。典型的框架如Hibernate; 因为Spring-data-jpa很多代码也是Hibernate团队贡献的,所以spring-data-jpa也是全自动ORM框架。

  • MyBatis是半自动ORM

Mybatis 在查询关联对象或关联集合对象时,需要手动编写 sql 来完成,所以,称之为半自动ORM 映射工具。

(PS: 正是由于MyBatis是半自动框架,基于MyBatis技术栈的框架开始考虑兼容MyBatis开发框架的基础上提供自动化的能力,比如MyBatis-plus等框架)

1.3、MyBatis栈技术演进

了解MyBatis技术栈的演进,对你构建基于MyBatis的知识体系极为重要。

1、JDBC,自行封装 JDBCUtil

Java5的时代,通常的开发中会自行封装JDBC的Util,比如创建 Connection,以及确保关闭 Connection等。

2、IBatis

MyBatis的前身,它封装了绝大多数的 JDBC 样板代码,使得开发者只需关注 SQL 本身,而不需要花费精力去处理例如注册驱动,创建 Connection,以及确保关闭 Connection 这样繁杂的代码。

3、MyBatis(目前我们项目处于这个阶段)

伴随着JDK5+ 泛型和注解特性开始流行,IBatis在3.0变更为MyBatis,对泛型和注解等特性开始全面支持,同时支持了很多新的特性,比如:

  1. MyBatis实现了接口绑定,通过Dao接口和xml映射文件的绑定,自动生成接口的具体实现
  2. MyBatis支持 ognl表达式,比如 <if>, <else>使用ognl进行解析
  3. MyBatis插件机制等,(PageHelper分页插件应用而生,解决了数据库层的分页封装问题)

所以这个时期,MyBatis XML 配置方式 + PageHelper 成为重要的开发方式。

4、MyBatis衍生:代码生成工具等

MyBatis提供了开发上的便捷,但是依然需要写大量的xml配置,并且很多都是CRUD级别的(这便有了很多重复性的工作),所以为了减少重复编码,衍生出了MyBatis代码生成工具, 比如 CodeGenerator 等。

其它开发IDE也开始出现封装一些工具和插件来生成代码生成工具等。

由于后端视图解析引擎多样性(比如freemarker, volicty, thymeleaf等),以及前后端分离前端独立等,为了进一步减少重复代码的编写(包括视图层),自动生成的代码工具也开始演化为自动生成前端视图代码。

5、Spring+MyBatis 基于注解的配置集成

与此同时,Spring 2.5 开始完全支持基于注解的配置并且也支持JSR250 注解。在Spring后续的版本发展倾向于通过注解和Java配置结合使用。基于Spring+MyBatis开发技术栈开始有xml配置方式往注解和java配置方式反向发展

Spring Boot的出现便是要解决配置过多的问题,它实际上通过约定大于配置的方式大大简化了用户的配置,对于三方组件使用xx-starter统一的对Bean进行默认初始化,用户只需要很少的配置就可以进行开发了。所以出现了mybatis-spring-boot-starter的封装等。

这个阶段,主要的开发技术栈是 Spring + mybatis-spring-boot-starter 自动化配置 + PageHelper,并且很多数据库实体mapper还是通过xml方式配置的(伴随着使用一些自动化生成工具)。

6、MyBatis-Plus

为了更高的效率,出现了MyBatis-Plus这类工具,对MyBatis进行增强。

  1. 考虑到MyBatis是半自动化ORM,MyBatis-Plus 启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作; 并且内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求;总体上让其支持全自动化的使用方式(本质上借鉴了Hibernate思路)。
  2. 考虑到Java8 Lambda(函数式编程)开始流行,MyBatis-Plus支持 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  3. 考虑到MyBatis还需要独立引入PageHelper分页插件,MyBatis-Plus支持了内置分页插件,同PageHelper一样基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  4. 考虑到自动化代码生成方式,MyBatis-Plus也支持了内置代码生成器,采用代码或者 Maven 插件可快速生成 Mapper 、Model 、Service 、Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  5. 考虑到SQL性能优化等问题,MyBatis-Plus内置性能分析插件, 可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  6. 其它还有解决一些常见开发问题,比如支持主键自动生成,支持4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题;以及内置全局拦截插件,提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

顶层思维能力

用这种思路去理解,你便能很快了解MyBatis技术栈的演化(能够快速维护老一些的技术框架),以及理解新的中小项目中MyBatis-Plus被大量使用的原因(新项目的技术选型参考);所以java全栈知识体系的目标是帮助你构建知识体系,甚至是辅助你培养顶层思维能力。

2、简单示例

尽管MyBatis-Plus大行其道,MyBatis XML 配置方式 + PageHelper依然是基础使用方式。本例依然向你展示MyBatis XML 配置方式,考虑到和spring-data-jpa方式对比,这里沿用上一篇文章的数据库。后续的案例中将具体介绍MyBatis分页,以及MyBatis-Plus的使用等。

2.1、准备DB和依赖配置

创建MySQL的schema test_db, 导入SQL 文件如下

-- MySQL dump 10.13  Distrib 5.7.12, for Win64 (x86_64)
--
-- Host: localhost    Database: test_db
-- ------------------------------------------------------
-- Server version	5.7.17-log/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;--
-- Table structure for table `tb_role`
--DROP TABLE IF EXISTS `tb_role`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `tb_role` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(255) NOT NULL,`role_key` varchar(255) NOT NULL,`description` varchar(255) DEFAULT NULL,`create_time` datetime DEFAULT NULL,`update_time` datetime DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;--
-- Dumping data for table `tb_role`
--LOCK TABLES `tb_role` WRITE;
/*!40000 ALTER TABLE `tb_role` DISABLE KEYS */;
INSERT INTO `tb_role` VALUES (1,'admin','admin','admin','2021-09-08 17:09:15','2021-09-08 17:09:15');
/*!40000 ALTER TABLE `tb_role` ENABLE KEYS */;
UNLOCK TABLES;--
-- Table structure for table `tb_user`
--DROP TABLE IF EXISTS `tb_user`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `tb_user` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_name` varchar(45) NOT NULL,`password` varchar(45) NOT NULL,`email` varchar(45) DEFAULT NULL,`phone_number` int(11) DEFAULT NULL,`description` varchar(255) DEFAULT NULL,`create_time` datetime DEFAULT NULL,`update_time` datetime DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;--
-- Dumping data for table `tb_user`
--LOCK TABLES `tb_user` WRITE;
/*!40000 ALTER TABLE `tb_user` DISABLE KEYS */;
INSERT INTO `tb_user` VALUES (1,'pdai','dfasdf','suzhou.daipeng@gmail.com',1212121213,'afsdfsaf','2021-09-08 17:09:15','2021-09-08 17:09:15');
/*!40000 ALTER TABLE `tb_user` ENABLE KEYS */;
UNLOCK TABLES;--
-- Table structure for table `tb_user_role`
--DROP TABLE IF EXISTS `tb_user_role`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `tb_user_role` (`user_id` int(11) NOT NULL,`role_id` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
/*!40101 SET character_set_client = @saved_cs_client */;--
-- Dumping data for table `tb_user_role`
--LOCK TABLES `tb_user_role` WRITE;
/*!40000 ALTER TABLE `tb_user_role` DISABLE KEYS */;
INSERT INTO `tb_user_role` VALUES (1,1);
/*!40000 ALTER TABLE `tb_user_role` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;-- Dump completed on 2021-09-08 17:12:11

引入maven依赖

<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.47</version>
</dependency>
<dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.1.0</version>
</dependency>
<!--pagehelper分页 -->
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.2.10</version>
</dependency>

增加yml配置

  • 在代码中没有找到
spring:datasource:url: jdbc:mysql://localhost:3306/test_db?useSSL=false&autoReconnect=true&characterEncoding=utf8driver-class-name: com.mysql.jdbc.Driverusername: rootpassword: adminmybatis:# Mapper 所对应的 XML 文件位置mapper-locations: classpath:mybatis/mapper/*.xml# 实体类根路径type-aliases-package: springboot.mysq.xml.entityconfiguration:# 开启二级缓存cache-enabled: trueuse-generated-keys: truedefault-executor-type: REUSEuse-actual-param-name: true

classpath:mybatis/mapper/*.xml 是mapper的位置。

2.2、Mapper文件

mapper 文件定义在配置的路径中(classpath:mybatis/mapper/*.xml

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 namespace="springboot.mysql.mybatis.dao.IUserDao"><resultMap type="springboot.mysql.mybatis.entity.User" id="UserResult"><id     property="id"       	column="id"      		/><result property="userName"     column="user_name"    	/><result property="password"     column="password"    	/><result property="email"        column="email"        	/><result property="phoneNumber"  column="phone_number"  	/><result property="description"  column="description"  	/><result property="createTime"   column="create_time"  	/><result property="updateTime"   column="update_time"  	/><collection property="roles" ofType="springboot.mysql.mybatis.entity.Role"><result property="id" column="rid"  /><result property="name" column="rname"  /><result property="roleKey" column="role_key"  /><result property="description" column="rdescription"  /><result property="createTime"   column="rcreate_time"  	/><result property="updateTime"   column="rupdate_time"  	/></collection></resultMap><sql id="selectUserSql">select u.id, u.password, u.user_name, u.email, u.phone_number, u.description, u.create_time, u.update_time, r.id rid, r.name rname, r.role_key, r.description rdescription, r.create_time rcreate_time, r.update_time rupdate_timefrom tb_user uleft join tb_user_role ur on u.id=ur.user_idinner join tb_role r on ur.role_id=r.id</sql><select id="findList" parameterType="springboot.mysql.mybatis.entity.query.UserQueryBean" resultMap="UserResult"><include refid="selectUserSql"/>where u.id != 0<if test="userName != null and userName != ''">AND u.user_name like concat('%', #{user_name}, '%')</if><if test="description != null and description != ''">AND u.description like concat('%', #{description}, '%')</if><if test="phoneNumber != null and phoneNumber != ''">AND u.phone_number like concat('%', #{phoneNumber}, '%')</if><if test="email != null and email != ''">AND u.email like concat('%', #{email}, '%')</if></select><select id="findById" parameterType="Long" resultMap="UserResult"><include refid="selectUserSql"/>where u.id = #{id}</select><delete id="deleteById" parameterType="Long">delete from tb_user where id = #{id}</delete><delete id="deleteByIds" parameterType="Long">delete from tb_user where id in<foreach collection="array" item="id" open="(" separator="," close=")">#{id}</foreach> </delete><update id="update" parameterType="springboot.mysql.mybatis.entity.User">update tb_user<set><if test="userName != null and userName != ''">user_name = #{userName},</if><if test="email != null and email != ''">email = #{email},</if><if test="phoneNumber != null and phoneNumber != ''">phone_number = #{phoneNumber},</if><if test="description != null and description != ''">description = #{description},</if>update_time = sysdate()</set>where id = #{id}</update><update id="updatePassword" parameterType="springboot.mysql.mybatis.entity.User">update tb_user<set>password = #{password}, update_time = sysdate()</set>where id = #{id}</update><insert id="save" parameterType="springboot.mysql.mybatis.entity.User" useGeneratedKeys="true" keyProperty="id">insert into tb_user(<if test="userName != null and userName != ''">user_name,</if><if test="password != null and password != ''">password,</if><if test="email != null and email != ''">email,</if><if test="phoneNumber != null and phoneNumber != ''">phone_number,</if><if test="description != null and description != ''">description,</if>create_time,update_time)values(<if test="userName != null and userName != ''">#{userName},</if><if test="password != null and password != ''">#{password},</if><if test="email != null and email != ''">#{email},</if><if test="phoneNumber != null and phoneNumber != ''">#{phoneNumber},</if><if test="description != null and description != ''">#{description},</if>sysdate(),sysdate())</insert>
</mapper> 

RoleMapper.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 namespace="springboot.mysql.mybatis.dao.IRoleDao"><resultMap type="springboot.mysql.mybatis.entity.Role" id="RoleResult"><id     property="id"       	column="id"      		/><result property="name" 		column="name"  /><result property="roleKey" 		column="role_key"  /><result property="description" 	column="description"  /><result property="createTime"   column="create_time"  	/><result property="updateTime"   column="update_time"  	/></resultMap><sql id="selectRoleSql">select  r.id, r.name, r.role_key, r.description, r.create_time, r.update_timefrom tb_role r</sql><select id="findList" parameterType="springboot.mysql.mybatis.entity.query.RoleQueryBean" resultMap="RoleResult"><include refid="selectRoleSql"/>where r.id != 0<if test="name != null and name != ''">AND r.name like concat('%', #{name}, '%')</if><if test="roleKey != null and roleKey != ''">AND r.role_key = #{roleKey}</if><if test="description != null and description != ''">AND r.description like concat('%', #{description}, '%')</if></select>
</mapper> 

2.3、定义dao

与Mapper文件中方法对应

UserDao

import java.util.List;
import springboot.mysql.mybatis.entity.User;
import springboot.mysql.mybatis.entity.query.UserQueryBean;/*** @author qiwenjie*/
public interface IUserService {List<User> findList(UserQueryBean userQueryBean);User findById(Long id);int deleteById(Long id);int deleteByIds(Long[] ids);int update(User user);int save(User user);int updatePassword(User user);
}

RoleDao

import java.util.List;
import springboot.mysql.mybatis.entity.Role;
import springboot.mysql.mybatis.entity.query.RoleQueryBean;public interface IRoleService {List<Role> findList(RoleQueryBean roleQueryBean);
}

2.4、定义Service接口和实现类

UserService接口

import java.util.List;
import springboot.mysql.mybatis.entity.User;
import springboot.mysql.mybatis.entity.query.UserQueryBean;/*** @author qiwenjie*/
public interface IUserService {List<User> findList(UserQueryBean userQueryBean);User findById(Long id);int deleteById(Long id);int deleteByIds(Long[] ids);int update(User user);int save(User user);int updatePassword(User user);
}

User Service的实现类

import java.util.List;
import org.springframework.stereotype.Service;
import springboot.mysql.mybatis.dao.IUserDao;
import springboot.mysql.mybatis.entity.User;
import springboot.mysql.mybatis.entity.query.UserQueryBean;
import springboot.mysql.mybatis.service.IUserService;@Service
public class UserDoServiceImpl implements IUserService {/*** userDao.*/private final IUserDao userDao;/*** init.** @param userDao2 user dao*/public UserDoServiceImpl(final IUserDao userDao2) {this.userDao = userDao2;}@Overridepublic List<User> findList(UserQueryBean userQueryBean) {return userDao.findList(userQueryBean);}@Overridepublic User findById(Long id) {return userDao.findById(id);}@Overridepublic int deleteById(Long id) {return userDao.deleteById(id);}@Overridepublic int deleteByIds(Long[] ids) {return userDao.deleteByIds(ids);}@Overridepublic int update(User user) {return userDao.update(user);}@Overridepublic int save(User user) {return userDao.save(user);}@Overridepublic int updatePassword(User user) {return userDao.updatePassword(user);}
}

Role Service 接口

import java.util.List;
import springboot.mysql.mybatis.entity.Role;
import springboot.mysql.mybatis.entity.query.RoleQueryBean;public interface IRoleService {List<Role> findList(RoleQueryBean roleQueryBean);
}

Role Service 实现类

import java.util.List;
import org.springframework.stereotype.Service;
import springboot.mysql.mybatis.service.IRoleService;
import springboot.mysql.mybatis.dao.IRoleDao;
import springboot.mysql.mybatis.entity.Role;
import springboot.mysql.mybatis.entity.query.RoleQueryBean;@Service
public class RoleDoServiceImpl implements IRoleService {/*** roleDao.*/private final IRoleDao roleDao;/*** init.** @param roleDao2 role dao*/public RoleDoServiceImpl(final IRoleDao roleDao2) {this.roleDao = roleDao2;}@Overridepublic List<Role> findList(RoleQueryBean roleQueryBean) {return roleDao.findList(roleQueryBean);}
}

2.5、controller

User Controller

import java.time.LocalDateTime;
import java.util.List;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springboot.mysql.mybatis.entity.User;
import springboot.mysql.mybatis.entity.query.UserQueryBean;
import springboot.mysql.mybatis.entity.response.ResponseResult;
import springboot.mysql.mybatis.service.IUserService;/*** @author qiwenjie*/
@RestController
@RequestMapping("/user")
public class UserController {@Autowiredprivate IUserService userService;/*** @param user user param* @return user*/@ApiOperation("Add/Edit User")@PostMapping("add")public ResponseResult<User> add(User user) {if (user.getId()==null) {user.setCreateTime(LocalDateTime.now());user.setUpdateTime(LocalDateTime.now());userService.save(user);} else {user.setUpdateTime(LocalDateTime.now());userService.update(user);}return ResponseResult.success(userService.findById(user.getId()));}/*** @return user list*/@ApiOperation("Query User One")@GetMapping("edit/{userId}")public ResponseResult<User> edit(@PathVariable("userId") Long userId) {return ResponseResult.success(userService.findById(userId));}/*** @return user list*/@ApiOperation("Query User List")@GetMapping("list")public ResponseResult<List<User>> list(UserQueryBean userQueryBean) {return ResponseResult.success(userService.findList(userQueryBean));}
}

Role Controller

import java.util.List;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import springboot.mysql.mybatis.entity.Role;
import springboot.mysql.mybatis.entity.query.RoleQueryBean;
import springboot.mysql.mybatis.entity.response.ResponseResult;
import springboot.mysql.mybatis.service.IRoleService;/*** @author qiwenjie*/
@RestController
@RequestMapping("/role")
public class RoleController {@Autowiredprivate IRoleService roleService;/*** @return user list*/@ApiOperation("Query Role List")@GetMapping("list")public ResponseResult<List<Role>> list(RoleQueryBean roleQueryBean) {return ResponseResult.success(roleService.findList(roleQueryBean));}
}

3、示例源码

完整示例可以看github源码

todo

相关文章:

SpringBoot第24讲:SpringBoot集成MySQL - MyBatis XML方式

SpringBoot第24讲&#xff1a;SpringBoot集成MySQL - MyBatis XML方式 上文介绍了用JPA方式的集成MySQL数据库&#xff0c;JPA方式在中国以外地区开发而言基本是标配&#xff0c;在国内MyBatis及其延伸框架较为主流。本文是SpringBoot第24讲&#xff0c;主要介绍MyBatis技栈的演…...

linux 查看网卡,网络情况

1&#xff0c;使用nload命令查看 #yum -y install nload 2&#xff0c; 查看eth0网卡网络情况 #nload eth0 Incoming也就是进入网卡的流量&#xff0c;Outgoing&#xff0c;也就是从这块网卡出去的流量&#xff0c;每一部分都有下面几个。 – Curr&#xff1a;当前流量 – Avg…...

在Mac上搭建Gradle环境

在Mac上搭建Gradle环境&#xff1a; 步骤1&#xff1a;下载并安装Java开发工具包&#xff08;JDK&#xff09; Gradle运行需要Java开发工具包&#xff08;JDK&#xff09;。您可以从Oracle官网下载适合您的操作系统版本的JDK。请按照以下步骤进行操作&#xff1a; 打开浏览器…...

Docker网络与Docker Compose服务编排

docker网络 docker是以镜像一层一层构建的&#xff0c;而基础镜像是linux内核&#xff0c;因此docker之间也需要通讯&#xff0c;那么就需要有自己的网络。就像windows都有自己的内网地址一样&#xff0c;每个docker容器也是有自己的私有地址的。 docker inspect [docker_ID]…...

opencv+ffmpeg环境(ubuntu)搭建全面详解

一.先讲讲opencv和ffmpeg之间的关系 1.1它们之间的联系 我们知道opencv主要是用来做图像处理的&#xff0c;但也包含视频解码的功能&#xff0c;而在视频解码部分的功能opencv是使用了ffmpeg。所以它们都是可以处理图像和视频的编解码&#xff0c;我个人感觉两个的侧重点不一…...

开发基于 LoRaWAN 的设备须知--最大兼容性

最大兼容性配置简介 LoRaWAN开放协议的建立前提是每个制造的设备都可以被唯一且安全地识别。配置是创建唯一标识和相应秘密的过程。虽然配置过程是常规的,但存在一些可能并不明显的陷阱。本章尝试描述配置基于 LoRa 的设备的一些最佳实践。 配置概念 基于 LoRa 的设备配置与银…...

一、SpringBoot基础[日志]

一、日志 解释&#xff1a;SpringBoot使用logback作为默认的日志框架&#xff0c;其中还可以导入log4j2等优秀的日志框架 1.修改日志内容 修改整个日志格式&#xff1a;logging.pattern.console%d{yyyy-MM-dd HH:mm:ss} %-5level [%thread] %logger{15} 你好 %msg%n %d{yyy…...

libuv库学习笔记-networking

Networking 在 libuv 中&#xff0c;网络编程与直接使用 BSD socket 区别不大&#xff0c;有些地方还更简单&#xff0c;概念保持不变的同时&#xff0c;libuv 上所有接口都是非阻塞的。它还提供了很多工具函数&#xff0c;抽象了恼人、啰嗦的底层任务&#xff0c;如使用 BSD …...

C++多线程编程(第三章 案例1,使用互斥锁+ list模拟线程通信)

主线程和子线程进行list通信&#xff0c;要用到互斥锁&#xff0c;避免同时操作 1、封装线程基类XThread控制线程启动和停止&#xff1b; 2、模拟消息服务器线程&#xff0c;接收字符串消息&#xff0c;并模拟处理&#xff1b; 3、通过Unique_lock和mutex互斥方位list 消息队列…...

IOS UICollectionView 设置cell大小不生效问题

代码设置flowLayout.itemSize 单元格并没有改变布局大小&#xff0c; 解决办法如下图&#xff1a;把View flow layout 的estimate size 设置为None&#xff0c;上面设置的itemSize 生效了。...

浅谈3D隐式表示(SDF,Occupancy field,NeRF)

本篇文章介绍了符号距离函数Signed Distance Funciton(SDF)&#xff0c;占用场Occupancy Field&#xff0c;神经辐射场Neural Radiance Field&#xff08;NeRF&#xff09;的概念、联系与区别。 显式表示与隐式表示 三维空间的表示形式可以分为显式和隐式。 比较常用的显式表…...

软件测试技能大赛任务二单元测试试题

任务二 单元测试 执行代码测试 本部分按照要求&#xff0c;执行单元测试&#xff0c;编写java应用程序&#xff0c;按照要求的覆盖方法设计测试数据&#xff0c;使用JUnit框架编写测试类对程序代码进行测试&#xff0c;对测试执行结果进行截图&#xff0c;将相关代码和相关截…...

MybatisPlus拓展篇

文章目录 逻辑删除通用枚举字段类型处理器自动填充功能防全表更新与删除插件MybatisX快速开发插件插件安装逆向工程常见需求代码生成 乐观锁问题引入乐观锁的使用效果测试 代码生成器执行SQL分析打印多数据源 逻辑删除 逻辑删除的操作就是增加一个字段表示这个数据的状态&…...

设置k8s中节点node的ROLES值,K8S集群怎么修改node1的集群ROLES

设置k8s中节点node的ROLES值 1.查看集群 [rootk8s-master ~]# kubectl get nodes NAME STATUS ROLES AGE VERSION k8s-master Ready control-plane,master 54d v1.23.8 k8s-node1 Ready <none> 54d v1.…...

【*1900 图论】CF1328 E

Problem - E - Codeforces 题意&#xff1a; 思路&#xff1a; 注意到题目的性质&#xff1a;满足条件的路径个数是极少的&#xff0c;因为每个点离路径的距离<1 先考虑一条链&#xff0c;那么直接就选最深那个点作为端点即可 为什么&#xff0c;因为我们需要遍历所有点…...

微信开发者工具 miniprogram_npm 未找到

背景 微信开发者工具中&#xff0c;打开集成了vant-weapp的项目&#xff0c;构建npm时&#xff0c;报错\miniprogram_npm\ 未找到。 问题 微信开发者工具&#xff0c;工具----->构建npm时&#xff0c;提示 message&#xff1a;发生错误 Error: D:\some\path\miniprogram…...

计算机视觉(三)未有深度学习之前

文章目录 图像分割基于阈值、基于边缘基于区域、基于图论 人脸检测Haar-like特征级联分类器 行人检测HOGSVMDPM 图像分割 把图像划分成若干互不相交的区域。经典的数字图像分割算法一般是基于灰度值的两个基本特征之一&#xff1a;不连续性和相似性。 基于阈值、基于边缘 基于…...

二十六、媒体查询2

目录&#xff1a; 媒体查询介绍网页常用分界点 一、媒体查询介绍 媒体特性&#xff1a; width 视口的宽度 height 视口的高度 一般设计的时候&#xff0c;高度不考虑&#xff0c;只考虑宽度 //当视口的宽度是500像素的时候,变颜色media (width: 500px) {body{background-colo…...

Themis 国库建设计划启动,开启去中心化新征程

在未来的金融领域&#xff0c;去中心化金融&#xff08;DeFi&#xff09;正在成为一种重要的趋势。在这股DeFi热潮中&#xff0c;作为Filecoin 生态下的一颗璀璨明珠&#xff0c;Themis 上线仅2个月&#xff0c;多项数据便稳居Filecoin-FVM榜首&#xff0c;TVL更是牢牢处于File…...

uni-app:模态框的实现(弹窗实现)

效果图 代码 标签 <template><view><!-- 按钮用于触发模态框的显示 --><button click"showModal true">显示模态框</button><!-- 模态框组件 --><view class"modal" v-if"showModal"><view cla…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

2025年能源电力系统与流体力学国际会议 (EPSFD 2025)

2025年能源电力系统与流体力学国际会议&#xff08;EPSFD 2025&#xff09;将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会&#xff0c;EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

全球首个30米分辨率湿地数据集(2000—2022)

数据简介 今天我们分享的数据是全球30米分辨率湿地数据集&#xff0c;包含8种湿地亚类&#xff0c;该数据以0.5X0.5的瓦片存储&#xff0c;我们整理了所有属于中国的瓦片名称与其对应省份&#xff0c;方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

微服务商城-商品微服务

数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...