免费建设音乐网站,做网站招商需要具备什么,合肥网站seo整站优化,做家教中介网站赚钱吗MyBatis-Plus入门学习简介特性快速开始MyBatis-Plus的注解详解Tableld主键生成策略1、数据库自动增长 AUTO2、UUID3、Redis生成id4、MP主键自动生成TableNameTableField自动填充测试方法#xff1a;update乐观锁select查所有根据id查多个id批量查询简单条件查询#xff08;通…
MyBatis-Plus入门学习简介特性快速开始MyBatis-Plus的注解详解Tableld主键生成策略1、数据库自动增长 AUTO2、UUID3、Redis生成id4、MP主键自动生成TableNameTableField自动填充测试方法update乐观锁select查所有根据id查多个id批量查询简单条件查询通过map封装条件分页delete根据id删除批量删除简单的条件查询删除逻辑删除性能分析Wrapperwrapper条件构造器测试1、ge、gt、le、lt、isNull、isNotNull2、eq、ne3、between、notBetween4、allEq5、like、notLike、likeLeft、likeRight6、in、notIn、inSql、notInSql、exists、notExists7、or、and8、嵌套or、嵌套and9、orderBy、orderByDesc、orderByAsc10、last11、set、setSql简介
MyBatis-Plus是MyBatis的增强工具在MyBatis的基础上做出增强改变简化开发,提高效率
mybatis-plus的官网链接
特性 快速开始
第一步创建一张表
CREATE TABLE user
(id BIGINT(20) NOT NULL COMMENT 主键ID,name VARCHAR(30) NULL DEFAULT NULL COMMENT 姓名,age INT(11) NULL DEFAULT NULL COMMENT 年龄,email VARCHAR(50) NULL DEFAULT NULL COMMENT 邮箱,PRIMARY KEY (id)
);第二步插入对应数据
INSERT INTO user (id, name, age, email) VALUES
(1, Jone, 18, test1baomidou.com),
(2, Jack, 20, test2baomidou.com),
(3, Tom, 28, test3baomidou.com),
(4, Sandy, 21, test4baomidou.com),
(5, Billie, 24, test5baomidou.com);第三步初始化一个项目工程 第四步引入依赖
parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.0 版本/versionrelativePath/
/parentdependenciesdependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependencydependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion最新版本/version/dependencydependencygroupIdcom.h2database/groupIdartifactIdh2/artifactIdscoperuntime/scope/dependency
/dependencies第五步配置数据库连接信息
spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver
spring.datasource.urljdbc:mysql://localhost:3306/mybatis-plus?
serverTimezoneGMT%2B8
spring.datasource.usernameroot
spring.datasource.passwordroot第五步在SpringBoot项目的启动类中添加**MapperScan注解**用于对mapper的扫描
package com.example.mpdemo001;import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;SpringBootApplication
MapperScan(com.example.mpdemo001.mapper)
public class Mpdemo001Application {public static void main(String[] args) {SpringApplication.run(Mpdemo001Application.class, args);}}第六步编码
实体类
package com.example.mpdemo001.bean;import lombok.Data;/*** Title: User* Package com.example.mpdemo001.bean* Author: CXY* Copyright CXY* CreateTime: 2023/3/9 12:35*/
Data
public class User {private Long id;private String name;private Integer age;private String email;
}mapper接口MyBatis-Plus不需要在接口中写很多方法只需要继承 BaseMapper T即可T表示泛型
package com.example.mpdemo001.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mpdemo001.bean.User;
import org.apache.ibatis.annotations.Mapper;Mapper
public interface UserMapper extends BaseMapperUser {
}**注意**在mapper接口上面需要添加一个Mapper的注解用于将Mapper接口加入Spring管理
第七步测试
package com.example.mpdemo001;import com.example.mpdemo001.bean.User;
import com.example.mpdemo001.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.List;SpringBootTest
public class Mpdemo001ApplicationTests {Autowiredprivate UserMapper userMapper;Testpublic void contextLoads() {ListUser users userMapper.selectList(null);for (User user:users) {System.out.println(user);}}}UserMapper 中的 selectList() 方法的参数为 MP 内置的条件封装器 Wrapper所以不填写就是无任何条件
测试结果
User(id1, nameJone, age18, emailtest1baomidou.com)
User(id2, nameJack, age20, emailtest2baomidou.com)
User(id3, nameTom, age28, emailtest3baomidou.com)
User(id4, nameSandy, age21, emailtest4baomidou.com)
User(id5, nameBillie, age24, emailtest5baomidou.com)可以配置MyBatis-Plus的日志文件这样可以看到详细的SQL语句实现过程
日志文件的配置如下
#mybatis日志
mybatis-plus.configuration.log-implorg.apache.ibatis.logging.stdout.StdOutImplMyBatis-Plus的注解详解
Tableld
IdType:顾名思义即表示主键的类型
主键生成策略
参考资料分布式系统唯一ID生成方案汇总https://www.cnblogs.com/haoxinyue/p/5208136.htm
1、数据库自动增长 AUTO
这个是指在建表的时候可以直接设置id自增这样的话idType即为AUTO
**缺点**这样id自增的主键不利于数据库的分表实现因为id是按顺序递增的所以每一次分表的时候都需要知道前一张表的最后一个id的值再那个基础上进行id加一的操作
2、UUID
每次生成随机唯一的值
**优点**每次分表的时候不需要知道上一张表的最后一个元素的id值
**缺点**id无法进行排序
3、Redis生成id
Redis是单线程的所以也可以用来生成全局唯一的id可以用Redis的原子操作INCR和INCRBY来实现
但是使用这个来进行id生成的时候需要指定初始值和步长
使用Redis集群可以防止单点故障的问题
单点故障英语single point of failure缩写SPOF是指系统中一点失效就会让整个系统无法运作的部件换句话说单点故障即会整体故障。
**优点**不依赖于数据库灵活方便且性能优于数据库数字id天然排序对分页或者需要排序的结果很有帮助
**缺点**如果系统中没有Redis还需引入新的主键增加系统的复杂度需要编码和配置的工作量比较大
4、MP主键自动生成
mp可以通过雪花算法自动生成一个19位数字的id
TableName
描述表名注解标识实体类对应的表使用位置实体类 TableField
描述字段注解非主键
自动填充
将数据自动填充进去
项目中经常会遇到一些数据每次都使用相同的方式填充例如记录的创建时间更新时间等。 我们可以使用MyBatis Plus的自动填充功能完成这些字段的赋值工作
具体实现过程
在实体类中需要自动进行自动填充的对象上面添加注解**TableFieldfillFieldFill.Xxx**FieldFill的取值 然后创建一个类用于实现MetaObjectHandler接口实现接口中的方法
注意需要在这个类上面添加注解让Spring进行管理
package com.example.mpdemo001.bean;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;import java.util.Date;/*** Title: MyBatisMeta* Package com.example.mpdemo001.bean* Author: CXY* Copyright CXY* CreateTime: 2023/3/10 14:02*/
Component
//这个不能忘忘了就无法进行了
public class MyBatisMeta implements MetaObjectHandler {Overridepublic void insertFill(MetaObject metaObject) {//插入时间第一次创建的时候需要插入创建时间和更新时间this.setFieldValByName(createTime,new Date(),metaObject);this.setFieldValByName(updateTime,new Date(),metaObject);}Overridepublic void updateFill(MetaObject metaObject) {//每一次更新数据的时候插入时间this.setFieldValByName(updateTime,new Date(),metaObject);}
}测试结果 测试方法
update
Test
public void testUpdateById(){User usernew User();user.setId(1L);user.setName(战三);int i userMapper.updateById(user);System.out.println(i);}结果
注意update生成的是动态sql
乐观锁
针对一种特定问题的解决方案主要解决的是丢失更新的问题
主要适用场景当要更新一条记录的时候希望这条记录没有被别人更新也就是说实现线程安全的数 据更新
如果不考虑事务的隔离性的话会产生的问题有
1、产生读问题脏读不可重复读幻读
2、产生写问题丢失更新就是指多个人同时修改同一条数据最后提交的把之前提交的数据覆盖了
解决丢失更新问题
悲观锁串行只有一个人能在当前情况下进行操作
乐观锁添加了一个version版本号当一个人在进行数据操作的时候提交数据时会比较当前数据版本号和数据库中的版本号是否一直如果一致则可以进行修改修改后版本号进行加一的操作。反之不能进行修改。
**乐观锁的使用例子有**12306抢票系统当别人把最后一张票抢走之后另外的人就不能再进行抢票了
乐观锁的使用流程
取出记录时获取当前version更新时带上这个version执行更新时 set version newVersion where version oldVersion如果version不对就更新失败
当有很多配置的时候建议新建一个配置类将所有配置写在配置类中
package com.example.mpdemo001.config;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** Title: MyBatisConfigurations* Package com.example.mpdemo001.config* Author: CXY* Copyright CXY* CreateTime: 2023/3/10 15:12*/
Configuration
MapperScan(com.example.mpdemo001.mapper)
public class MyBatisConfigurations {/*** 乐观锁插件** 新版*/Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return mybatisPlusInterceptor;}}测试成功代码
Test
public void testOptimisticLockerFail() {User user userMapper.selectById(1l);user.setName(死亡法师);user.setAge(10000);int i userMapper.updateById(user);System.out.println(i);
}测试成功的结果 测试失败代码
Test
public void testOptimisticLockerFail() {User user userMapper.selectById(2l);user.setName(哈利波特);user.setAge(300);//模拟取出数据后数据库中version实际数据比取出的值大即已被其它线程修改并更新了versionuser.setVersion(user.getVersion()-1);int i userMapper.updateById(user);System.out.println(i);
}结果 select
查所有
Test
public void testSelect(){ListUser users userMapper.selectList(null);users.forEach(System.out::println);
}结果 根据id查 多个id批量查询 简单条件查询通过map封装条件 注意map中的key对应的是数据库中的列名。例如数据库user_id实体类是userId这时map的key需 要填写user_id
分页
MyBatis Plus自带分页插件只要简单的配置即可实现分页功能
添加插件
/*** 分页插件官网最新*/
Bean
public MybatisPlusInterceptor mybatisPlusInterceptor1() {MybatisPlusInterceptor interceptor new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;
}测试分页实现
Test
public void testPageSelect(){Page pagenew Page(1,3);userMapper.selectPage(page, null);page.getRecords().forEach(System.out::println);System.out.println(page.getCurrent());System.out.println(page.getPages());System.out.println(page.getSize());System.out.println(page.getTotal());System.out.println(page.getRecords());}测试结果 分页的各个属性 delete
根据id删除
Test
public void testDeletedById(){int i userMapper.deleteById(4l);System.out.println(i);
}批量删除
Test
public void testDeletedByIds(){int i userMapper.deleteBatchIds(Arrays.asList(1, 2, 3));System.out.println(i);
}简单的条件查询删除
Test
public void testDeleteByMap(){HashMapString,Object hashMapnew HashMap();hashMap.put(name,Tom);hashMap.put(age,28);int i userMapper.deleteByMap(hashMap);System.out.println(i);
}逻辑删除
逻辑删除就是指在数据中多加一个标志属性删除的时候只对该属性进行修改而不是真正的删除数据逻辑删除有利于数据的恢复
物理删除真实删除将对应数据从数据库中删除之后查询不到此条被删除数据逻辑删除假删除将对应数据中代表是否被删除字段状态修改为“被删除状态”之后在数据库中仍 旧能看到此条数据记录 在实体类上添加deleted属性
TableLogic
TableField(fill FieldFill.INSERT)
private Integer deleted;如果想修改默认属性值则可在application.properties中进行配置
默认0表示未被删除1表示被删除 在配置类中注册bean
Bean
public ISqlInjector sqlInjector() {return new LogicSqlInjector();
}高版本不用配置插件了上述java代码无需编写。
测试删除
Test
public void testLogicDelete() {int result userMapper.deleteById(1L);System.out.println(result);
}被删除数据的deleted 字段的值必须是 0才能被选取出来执行逻辑删除的操做
性能分析
在配置类中添加性能优化插件
Profile{“dev”“test”}表示对什么环境起作用
dev开发环境
test测试环境
prod生产环境项目部署好之后的环境 最好不要在这里使用性能优化插件
环境配置在配置文件中设置
spring.profile.activexxx(dev,test,prod)
**参数**maxTime SQL 执行最大时长超过自动停止运行有助于发现问题。
**参数**format SQL是否格式化默认false
Wrapper Wrapper 条件构造抽象类最顶端父类AbstractWrapper 用于查询条件封装生成 sql 的 where 条件QueryWrapper Entity 对象封装操作类不是用lambda语法使用较多UpdateWrapper Update 条件封装用于Entity对象更新操作AbstractLambdaWrapper Lambda 语法使用 Wrapper统一处理解析 lambda 获取 column。LambdaQueryWrapper 看名称也能明白就是用于Lambda语法使用的查询WrapperLambdaUpdateWrapper Lambda 更新封装Wrapper
wrapper条件构造器测试
1、ge、gt、le、lt、isNull、isNotNull
Test
public void testQueryWrapper(){QueryWrapperUser queryWrappernew QueryWrapper();queryWrapper.isNull(email).ge(age,30).isNotNull(name);//上面代码可以表示多个条件int delete userMapper.delete(queryWrapper);System.out.println(delete);
}gt大于ge大于等于le小于lt小于等于
2、eq、ne
eq表示等于
ne表示不等于
Test
public void testSelectOne() {QueryWrapperUser queryWrapper new QueryWrapper();queryWrapper.eq(name, Tom);User user userMapper.selectOne(queryWrapper);System.out.println(user);
}注意selectOne方法返回的是一条实体记录如果返回多条时会报错
3、between、notBetween
是包含边界值的查询条件
需要注意小值在前大值在后
Test
public void testSelectCount() {QueryWrapperUser queryWrapper new QueryWrapper();queryWrapper.between(age, 20, 30);Long count userMapper.selectCount(queryWrapper);System.out.println(count);
}4、allEq
多条件均相等
Test
public void testSelectList() {QueryWrapperUser queryWrapper new QueryWrapper();MapString, Object map new HashMap();map.put(id, 2);map.put(name, Jack);map.put(age, 20);queryWrapper.allEq(map);ListUser users userMapper.selectList(queryWrapper);users.forEach(System.out::println);
}5、like、notLike、likeLeft、likeRight
like模糊查询表示like %内容%
notLike不包含
likeLeft表示like %内容
likeRight表示 like 内容%
Test
public void testQuerrySelectMaps() {QueryWrapperUser queryWrapper new QueryWrapper();queryWrapper.notLike(name,san).likeRight(email,test1);ListMapString, Object maps userMapper.selectMaps(queryWrapper);maps.forEach(System.out::println);}6、in、notIn、inSql、notInSql、exists、notExists
in notIn用法如下:
notIn(“age”,{1,2,3})—age not in (1,2,3)
notIn(“age”, 1, 2, 3)—age not in (1,2,3)
inSql、notInSql可以实现子查询
Testpublic void testSelectObjs() {QueryWrapperUser queryWrapper new QueryWrapper();
//queryWrapper.in(id, 1, 2, 3);queryWrapper.inSql(id, select id from user where id 3);ListObject objects userMapper.selectObjs(queryWrapper);//返回值是Object列表objects.forEach(System.out::println);}7、or、and
不调用or则默认为使用 and 连
8、嵌套or、嵌套and
这里使用了lambda表达式or中的表达式最后翻译成sql时会被加上圆括号 Testpublic void testUpdate2() {
//修改值User user new User();user.setAge(99);user.setName(Andy);
//修改条件UpdateWrapperUser userUpdateWrapper new UpdateWrapper();userUpdateWrapper.like(name, h).or(i - i.eq(name, 李白).ne(age, 20));
// i - i.eq(name, 李白).ne(age, 20)这一段是lambda表达式int result userMapper.update(user, userUpdateWrapper);System.out.println(result);}最后的sql语句为
UPDATE user SET name?, age?, update_time? WHERE deleted0 AND name LIKE ?
OR ( name ? AND age ?)
9、orderBy、orderByDesc、orderByAsc
**orderBy:**默认是升序
**orderByDesc**表示升序排列该方法可以有多个条件参与排列
**orderByAsc**表示降序排列该方法可以有多个条件参与排列
10、last
直接拼接到 sql 的最后
注意只能调用一次,多次调用以最后一次为准 有sql注入的风险,请谨慎使用
Test
public void testSelectListLast() {QueryWrapperUser queryWrapper new QueryWrapper();queryWrapper.last(limit 1);ListUser users userMapper.selectList(queryWrapper);users.forEach(System.out::println);
}sql语句SELECT id,name,age,email,create_time,update_time,deleted,version FROM user WHERE deleted0 limit 1
11、set、setSql
最终的sql会合并 user.setAge()以及 userUpdateWrapper.set() 和 setSql() 中 的字段
Testpublic void testUpdateSet() {
//修改值User user new User();user.setAge(99);
//修改条件UpdateWrapperUser userUpdateWrapper new UpdateWrapper();userUpdateWrapper.like(name, h).set(name, 老李头)//除了可以查询还可以使用set设置修改的字段.setSql( email 123qq.com);//可以有子查询int result userMapper.update(user, userUpdateWrapper);}sql语句
UPDATE user SET age?, update_time?, name?, email ‘123qq.com’ WHERE deleted0 AND name LIKE
b站教学视频 尚硅谷