Springboot作为业界最为流行的微服务架构框架,对数据的操作是最基本的需求。
1. 数据操作方案对比
传统JDBC方式操作数据库,配置参数,获取执行结果,然后将结果填充到接口bean,及其繁琐耗时,早已满足不了解放程序员生产力的要求。
JDBCTemplate则是JDBC的一个改进版,像基本的
而Hibernate使得程序员可以像开发业务模块一样,直接写代码来操作数据库,理论上可以完全不懂SQL,因为这部分工作它替我们做了。但是,最强大的之处也往往是最薄弱之处。正因为转化成SQL这个工作hibernate替我们做了,这是个黑箱,我们写代码的时候,往往不知道它会转成什么样子,感觉不可控,尤其是出了问题调试的时候。用Hibernate学习成本也高,要学习HQL(Hibernate Query Language)。
Mybatis就不一样了。它一款优秀的持久层框架,支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集, 可以使用简单的 Xml 或注解来配置。灵活而不是强大,所以得到了越来越多互联网公司的青睐。
2. Springboot集成Mybatis步骤
2.1 maven pom文件引入配置
1.8
5.1.45
1.3.2
1.1.17
mysql
mysql-connector-java
${mysql.version}
org.mybatis.spring.boot
mybatis-spring-boot-starter
${mybatis.version}
com.alibaba
druid-spring-boot-starter
${druid.version}
2.2 配置数据库连接
设置application.yml文件,添加数据库连接池配置和mybatis配置。这里采用的阿里的druid连接池,更新详细的配置可以参考阿里的github,里面介绍了更详细的属性含义,以及多数据源的配置方式。
spring:
datasource:
url: jdbc:mysql://192.168.245.101:3306/studyDB?useUnicode=true&characterEncoding=utf-8&useSSL=false
username: root
password: 921230
driver-class-name: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
druid:
initial-size: 8
min-idle: 1
max-active: 20
max-wait: 60000
time-between-eviction-runsMillis: 60000
min-evictable-idle-timeMillis: 300000
validation-query: select 'x' FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true
max-open-prepared-statements: 20
max-pool-prepared-statement-per-connection-size: 20
filters: stat
connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
use-global-data-source-stat: true
#mybatis
mybatis:
mapper-locations: classpath:/mapper/*Mapper.xml
#实体扫描,多个package用逗号或者分号分隔
typeAliasesPackage: com.qinghaihu.springbootmybatis.entity
2.3 核心代码编写
数据源为一张系统用户信息表sys_user,其定义如下,我们要通过mybatis实现对sys_user的增删改查。
/*
Navicat Premium Data Transfer
Source Server : studyDb
Source Server Type : MySQL
Source Server Version : 50725
Source Host : 192.168.245.101:3306
Source Schema : studyDB
Target Server Type : MySQL
Target Server Version : 50725
File Encoding : 65001
Date: 28/03/2020 15:20:01
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for sys_user
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
`id` varchar(50) NOT NULL COMMENT '主键',
`userName` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(50) NOT NULL COMMENT '密码',
`userState` int(2) NOT NULL DEFAULT '1' COMMENT '用户状态,1-启用,-1禁用',
`createTime` datetime DEFAULT NULL COMMENT '创建时间',
`userDesc` varchar(300) DEFAULT NULL COMMENT '描述',
`userImg` varchar(300) DEFAULT '/app/img/user2-160x160.jpg' COMMENT '头像',
`deptId` varchar(50) DEFAULT NULL COMMENT '部门主键',
PRIMARY KEY (`id`),
UNIQUE KEY `username_unique_index` (`userName`(5)) USING BTREE COMMENT '用户名唯一索引'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';
-- ----------------------------
-- Records of sys_user
-- ----------------------------
BEGIN;
INSERT INTO `sys_user` VALUES ('1', 'admin', '999999', 1, '2019-11-03 11:08:28', '超级管理员,具有最高权限', '/app/img/user2-160x160.jpg', '111');
INSERT INTO `sys_user` VALUES ('2', 'tenant', '000000', 1, '2019-11-03 11:51:36', '租客公用账户', '/app/img/user2-160x160.jpg', '222');
INSERT INTO `sys_user` VALUES ('3', 'zhanglianzhong', '222222', 1, '2019-11-03 11:43:36', '系统运维人员', '/app/img/user2-160x160.jpg', '333');
INSERT INTO `sys_user` VALUES ('4', 'guoyunping', '333333', 1, '2019-11-03 11:09:43', '二房东管理用户', '/app/img/user2-160x160.jpg', '444');
COMMIT;
SET FOREIGN_KEY_CHECKS = 1;
2.3.1 entity实体类
编写操作表对应的实体bean类,字段命名建议采用驼峰形式。bean字段的set和get方法可以使用lombok来简化编码。
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.Date;
@Data
@NoArgsConstructor
public class SysUser {
//用户id
private String id;
//用户名
private String username;
//密码
private String password;
//用户状态
private Integer userstate;
//创建时间
private Date createtime;
//用户描述
private String userdesc;
//用户图像
private String userimg;
//所属部门id
private String deptid;
}
2.3.2 dao接口类
需要编写一个dao接口类,用于描述dao层对外提供的接口方法。用mybatis的@Mapper进行注解。
import com.qinghaihu.springbootmybatis.entity.SysUser;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;
@Mapper
@Repository
public interface SysUserDao {
int insert(SysUser record);
SysUser selectByPrimaryKey(String id);
int updateByPrimaryKey(SysUser record);
int deleteByPrimaryKey(String id);
}
2.3.3 编写数据操作xml文件
delete from sys_user
where id = #{id,jdbcType=VARCHAR}
insert into sys_user (id, userName, password,
userState, createTime, userDesc,
userImg, deptId)
values (#{id,jdbcType=VARCHAR}, #{username,jdbcType=VARCHAR}, #{password,jdbcType=VARCHAR},
#{userstate,jdbcType=INTEGER}, #{createtime,jdbcType=TIMESTAMP}, #{userdesc,jdbcType=VARCHAR},
#{userimg,jdbcType=VARCHAR}, #{deptid,jdbcType=VARCHAR})
update sys_user
set userName = #{username,jdbcType=VARCHAR},
password = #{password,jdbcType=VARCHAR},
userState = #{userstate,jdbcType=INTEGER},
createTime = #{createtime,jdbcType=TIMESTAMP},
userDesc = #{userdesc,jdbcType=VARCHAR},
userImg = #{userimg,jdbcType=VARCHAR},
deptId = #{deptid,jdbcType=VARCHAR}
where id = #{id,jdbcType=VARCHAR}
用insert、delete、update和select表征增删改查基本操作,reslutMap描述了JDBC数据类型和JAVA类型映射关系。parameterType为输入参数类型,#{xxxx}用于引用输入参数值。
mapper.xml文件与dao接口文件是相互绑定文件,为了实现关系绑定,mybatis有如下约定:
1 xml文件中的namespace为完整的dao全路径接口名
2 dao接口的方法名对应mapper.xml中的sql id
3 dao接口方法入参和出参与mapper.xml须一致
service类
服务层使用@Autowired注解自动注入dao接口,对外提供增删改查的数据操作服务。
@Service
public class SysUserService {
@Autowired
SysUserDao sysUserDao;
public SysUser selectById(String id){
return sysUserDao.selectByPrimaryKey(id);
}
public boolean updateUserInfo(SysUser sysUser){
int count = sysUserDao.updateByPrimaryKey(sysUser);
if(count>0){
return true;
}else {
return false;
}
}
public boolean deleteById(String id){
int count = sysUserDao.deleteByPrimaryKey(id);
if(count>0){
return true;
}else {
return false;
}
}
public boolean insertUserInfo(SysUser sysUser){
int count = sysUserDao.insert(sysUser);
if(count>0){
return true;
}else {
return false;
}
}
}
3 单元测试
编写Service层的单元测试案例,测试服务正确性。
package com.qinghaihu.springbootmybatis;
import com.qinghaihu.springbootmybatis.entity.SysUser;
import com.qinghaihu.springbootmybatis.service.SysUserService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Date;
@SpringBootTest
class SpringbootMybatisApplicationTests {
@Autowired
SysUserService sysUserService;
@Test
public void testInsert(){
SysUser sysUser = new SysUser();
sysUser.setId("5");
sysUser.setUsername("qinghaihu");
sysUser.setPassword("88888888");
sysUser.setCreatetime(new Date());
sysUser.setUserdesc("奔跑吧程序猿");
sysUser.setUserimg("/user/images/qinghaihu.jpg");
sysUser.setUserstate(0);
boolean insertResult = sysUserService.insertUserInfo(sysUser);
if(insertResult){
System.out.println("成功插入用户记录!");
}else {
System.out.println("插入用户记录失败");
}
}
@Test
public void testSelect(){
String id = "5";
SysUser sysUser = sysUserService.selectById(id);
System.out.println(sysUser);
}
@Test
public void testUpdate() {
SysUser sysUser = new SysUser();
sysUser.setId("5");
sysUser.setUsername("qinghaihu");
sysUser.setPassword("88889999");
sysUser.setCreatetime(new Date());
sysUser.setUserdesc("奔跑吧程序猿");
sysUser.setUserimg("/user/images/qinghaihu.jpg");
sysUser.setUserstate(0);
boolean updateResult = sysUserService.updateUserInfo(sysUser);
if (updateResult) {
System.out.println("成功修改用户信息!");
} else {
System.out.println("修改用户信息失败");
}
}
@Test
public void testdelete() {
String id = "5";
boolean deleteResult = sysUserService.deleteById(id);
if (deleteResult) {
System.out.println("成功删除用户信息!");
} else {
System.out.println("删除用户信息失败");
}
}
}
执行单元测试后的结果
4 项目源码
https://github.com/zhanglianzhong/sprinboot-tech.git