万江营销型网站建设,设计制作的一般流程是明确问题,哔哩哔哩网站建设分析,现在什么行业发展前景最好一、MybatisPlus简介
1、入门案例#xff08;重点#xff09;#xff1a;
1.SpringBoot整合MP1).创建新模块选择#xff0c;Spring项初始化。2).选择当前模块使用的技术#xff0c;只保留MySQL Driver就行#xff0c;不要选择mybatis避免与后面导入mybatisPlus的依赖发…一、MybatisPlus简介
1、入门案例重点
1.SpringBoot整合MP1).创建新模块选择Spring项初始化。2).选择当前模块使用的技术只保留MySQL Driver就行不要选择mybatis避免与后面导入mybatisPlus的依赖发生冲突。使用联网创建工程有两个弊端所以在以后工作中基本不使用1、必须联网2、只能选最近几个比较新的SpringBoot版本企业开发追求稳定一般不会用太新的版本企业工作中直接创建一个Maven工程就行自行指定继承的SpringBoot父工程3).企业中手动创建项目指定版本group: com.itheima项目名mp_demojdk使用8parentgroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-parent/artifactIdversion2.5.0/versionrelativePath/ !-- lookup parent from repository --
/parentdependencies!--注意事项1由于mybatisPlus并未被收录到idea的系统内置配置无法直接选择加入--dependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-boot-starter/artifactIdversion3.4.1/version/dependency!--数据源 --dependencygroupIdcom.alibaba/groupIdartifactIddruid/artifactIdversion1.1.16/version/dependencydependencygroupIdmysql/groupIdartifactIdmysql-connector-java/artifactId/dependencydependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdscopetest/scope/dependency
/dependencies4).制作实体类与表结构类名与表名对应属性名与字段名对应create database if not exists mybatisplus_db character set utf8;
use mybatisplus_db;
CREATE TABLE user (id bigint(20) primary key auto_increment,name varchar(32) not null,password varchar(32) not null,age int(3) not null ,tel varchar(32) not null
);
insert into user values(null,tom,123456,12,12345678910);
insert into user values(null,jack,123456,8,12345678910);
insert into user values(null,jerry,123456,15,12345678910);
insert into user values(null,tom,123456,9,12345678910);
insert into user values(null,snake,123456,28,12345678910);
insert into user values(null,张益达,123456,22,12345678910);
insert into user values(null,张大炮,123456,16,12345678910);package com.itheima.domain;
//pojo, entity, domainData
public class User {private Long id;private String name;private String password;private Integer age;private String tel;//可以使用lombok自动生成//自行添加getter、setter、toString()等方法
}5).设置Jdbc参数(application.yml)
spring:datasource:type: com.alibaba.druid.pool.DruidDataSource #可选如果使用必须引入Druid坐标driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezoneUTCusername: rootpassword: root6).定义数据接口继承BaseMapperMapper
public interface UserDao extends BaseMapperUser {//注意BaseMapper后边必须指定泛型User以此来确定操作的表
}7).测试类中注入dao接口测试功能SpringBoot引导类必须放到某一个包下SpringBootApplication
public class Mybatisplus01QuickstartApplication {public static void main(String[] args) {SpringApplication.run(Mybatisplus01QuickstartApplication.class, args);}
}
/************************************************************************************/打开自动生成的测试类编写单元测试SpringBootTest
public class Mybatisplus01QuickstartApplicationTests {Autowiredprivate UserDao userDao;Testvoid testGetAll() {ListUser userList userDao.selectList(null);System.out.println(userList);}Testvoid testFindById() {//业务层: get(list), remove, modify(update), save//数据层select, delete, update, insertUser user userDao.selectById(1);System.out.println(user);}
}2、MyBatisPlus概述
MyBatisPlus介绍- MyBatisPlus简称MP是基于MyBatis框架基础上开发的增强型工具旨在简化开发、提高效率。
- 官网https://mybatis.plus/ https://mp.baomidou.comMyBatisPlus特性:- 无侵入只做增强不做改变不会对现有工程产生影响
- 强大的 CRUD 操作内置通用 BaseMapper少量配置即可实现单表CRUD 操作
- 支持 Lambda编写查询条件无需担心字段写错
- 支持主键自动生成雪花算法
- 内置分页插件MyBatis分页需要用到Pagehelper通过拦截器给SQL追加limit 0,10
- ……二、标准数据层开发【重点】
1、CRUD操作
功能自定义接口MP接口新增boolean save(T t)int insert(T t)删除boolean delete(int id)int deleteById(Serializable id)修改boolean update(T t)int updateById(T t)根据id查询T getById(int id)T selectById(Serializable id)查询全部ListT getAllListT selectList()分页查询PageInfoT getAll(int page,int size)IPageT selectPage(IPageT page)按条件查询ListT getAll(Condition condition)IPageT selectPage(WrapperT queryWrapper)
编写单元测试完成对user表的增删查改
SpringBootTest
class Mybatisplus01QuickstartApplicationTests {Autowiredprivate UserDao userDao;Testvoid testSave() {User user new User();user.setName(程序员);user.setPassword(it);user.setAge(12);user.setTel(400000);userDao.insert(user);}Testvoid testDelete() {userDao.deleteById(2L);}Testvoid testUpdate() {User user new User();user.setId(1L);user.setName(Tom888);user.setPassword(tom888);userDao.updateById(user);}Testvoid testGetById() {User user userDao.selectById(2L);System.out.println(user);}Testvoid testGetAll() {ListUser userList userDao.selectList(null);System.out.println(userList);}
} 2、Lombok插件【常用】
Lombok一个Java类库提供了一组注解简化POJO实体类开发。!--自动生成get,set,toString等方法--
!--实体类上添加Data即可--
dependencygroupIdorg.projectlombok/groupIdartifactIdlombok/artifactId
/dependency常用注解Data为当前实体类在编译期设置对应的get/set方法无参/无参构造方法toString方法hashCode方法equals方法等package com.itheima.domain;import lombok.*;
/*1 生成getter和setter方法Getter、Setter生成toString方法ToString生成equals和hashcode方法EqualsAndHashCode2 统一成以上所有Data3 生成空参构造 NoArgsConstructor生成全参构造 AllArgsConstructor4 lombok还给我们提供了builder的方式创建对象,好处就是可以链式编程。 Builder【扩展】*/
Data
public class User {private Long id;private String name;private String password;private Integer age;private String tel;
}3、分页功能
1、引入Pagehelper坐标(通过拦截器给sql语句加limit 0,10)
2、Pagehelper.startPage(size, page)1).设置分页拦截器作为Spring管理的beanConfiguration
public class MybatisPlusConfig {Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor(){//1 创建MybatisPlusInterceptor拦截器对象MybatisPlusInterceptor mpInterceptornew MybatisPlusInterceptor();//2 添加分页拦截器当调用selectPage方法时自动在最后追加分页实现limit 0,10mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());return mpInterceptor;}
}2).执行分页查询//分页查询
Test
void testSelectPage(){//1 创建IPage分页对象,设置分页参数IPageUser pagenew Page(1,3);//2 执行分页查询userDao.selectPage(page,null);//框架底层会把查询到的数据放到page对象中//page.setRecords(new ArrayList());//page.setTotal(100);//3 获取分页结果System.out.println(当前页码值page.getCurrent());System.out.println(每页显示数page.getSize());System.out.println(总页数page.getPages());System.out.println(总条数page.getTotal());System.out.println(当前页数据page.getRecords());
}3).输出SQL到控制台spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezoneUTCusername: rootpassword: root
# 开启mp的日志输出到控制台
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImpl三、DQL编程控制【重点】
DQL:数据查询Query语言(select)
DML:数据操作语言(insert,update,delete)1、简化日志【了解】
SpringBoot底层是logback框架记录日志的
做法在resources下新建一个logback.xml文件名称固定内容如下?xml version1.0 encodingUTF-8?
configuration/configuration# 取消SpringBoot启动banner图标#spring:main:banner-mode: off # 关闭SpringBoot启动图标(banner)## 取消MybatisPlus启动banner图标# mybatis-plus日志控制台输出
mybatis-plus:configuration:log-impl: org.apache.ibatis.logging.stdout.StdOutImplglobal-config:banner: off # 关闭mybatisplus启动图标2、条件查询方式
1、条件查询方式MyBatisPlus将书写复杂的SQL查询条件进行了封装使用编程的形式完成查询条件的组合。//方式一按条件查询
QueryWrapperUser qw new QueryWrapper();
//lt小于less than; gt大于greater than
//le小于等于less than or equal
//ge大于等于:greater than or equal
qw.lt(age, 18); //where age 18
ListUser userList userDao.selectList(qw); //select * from user
System.out.println(userList);2、lambda格式按条件查询//方式二lambda格式按条件查询qw.lambda()
QueryWrapperUser qw new QueryWrapperUser();
qw.lambda().lt(User::getAge, 18);
ListUser userList userDao.selectList(qw);
System.out.println(userList);3、lambda格式按条件查询推荐//方式三lambda格式按条件查询
LambdaQueryWrapperUser lqw new LambdaQueryWrapper();lqw.lt(User::getAge, 18);
ListUser userList userDao.selectList(lqw);
System.out.println(userList);//方式三变种1通过Wrappers的静态方法获取
//LambdaQueryWrapperUser lqw Wrappers.lambdaQuery();
//lqw.lt(User::getAge, 18);
//ListUser userList userDao.selectList(lqw);
//System.out.println(userList);//方式三变种2链式编程
//ListUser users userDao.selectList(
// Wrappers.UserlambdaQuery() //产生查询条件对象
// .lt(User::getAge, 18));
//System.out.println(users);3、组合条件查询
1、并且关系and//并且关系:and
LambdaQueryWrapperUser lqw new LambdaQueryWrapperUser();
//并且关系10到30岁之间默认多个条件使用and连接
lqw.lt(User::getAge, 30).gt(User::getAge, 10);
ListUser userList userDao.selectList(lqw);
System.out.println(userList);2、或者关系or//或者关系
LambdaQueryWrapperUser lqw new LambdaQueryWrapperUser();
//或者关系小于18岁或者大于10岁
//where age 18 or age 10
lqw.lt(User::getAge, 18).or().gt(User::getAge, 10);
ListUser userList userDao.selectList(lqw);
System.out.println(userList);3、NULL值处理在多条件查询中有条件的值为空1).模拟用户查询条件类UserQuery 继承需要限制条件的类定义相同类型的属性限制需要被限制的字段。Data
public class UserQuery extends User {//此时对年龄进行限制private Integer age2; //最大年龄
}
/********************************************************************************************************/2).if语句控制条件追加//模拟页面传递过来的查询数据
UserQuery uq new UserQuery();
uq.setAge(10);
uq.setAge2(30);LambdaQueryWrapperUser lqw new LambdaQueryWrapperUser();
lqw.lt(User::getAge, uq.getAge2());//null判定
if (null ! uq.getAge()) {lqw.gt(User::getAge, uq.getAge());
}
ListUser userList userDao.selectList(lqw);
System.out.println(userList);
/*************************************************************************************************************/3).条件参数控制【常用】//null判断第二种条件参数控制
LambdaQueryWrapperUser lqw new LambdaQueryWrapperUser();
//先判定第一个参数是否为true如果为true连接当前条件
lqw.lt(null ! uq.getAge2(), User::getAge, uq.getAge2());
lqw.gt(null ! uq.getAge(), User::getAge, uq.getAge());
ListUser userList userDao.selectList(lqw);
System.out.println(userList);/**************************************************************************************************************/4).条件参数控制链式编程//先判定第一个参数是否为true如果为true连接当前条件
//lqw.lt(null ! uq.getAge2(), User::getAge, uq.getAge2());
//lqw.gt(null ! uq.getAge(), User::getAge, uq.getAge());
lqw.lt(null ! uq.getAge2(), User::getAge, uq.getAge2()).gt(null ! uq.getAge(), User::getAge, uq.getAge());4、查询投影
1.查询结果包含实体类中部分属性【常用】LambdaQueryWrapperUser lqw new LambdaQueryWrapperUser();
lqw.select(User::getId, User::getName, User::getAge);/*QueryWrapperUser lqw new QueryWrapperUser();
lqw.select(id, name, age, tel);*/ListUser userList userDao.selectList(lqw);
System.out.println(userList); 2 查询结果包含实体类中未定义的属性【了解】这个统计SQL在企业开发中一般会使用MyBatis在xml中编写sqlSELECT COUNT(*) count,tel FROM user GROUP BY telQueryWrapperUser lqw new QueryWrapperUser();
lqw.select(count(*) as count, tel); //统计lqw.groupBy(tel); //分组
//qw.lambda().groupBy(User::getTel);ListMapString, Object userList userDao.selectMaps(lqw);
System.out.println(userList);//System.out.println(userDao.selectCount(null)); //查询总记录数# 3、查询条件设置多条件查询有哪些组合- 范围匹配 、 、between
- 模糊匹配like
- 空判定null
- 包含性匹配in
- 分组group
- 排序order by
- ……- 用户登录eq匹配LambdaQueryWrapperUser lqw new LambdaQueryWrapperUser();
//eq()等同于
lqw.eq(User::getName, Jerry).eq(User::getPassword, jerry);
//如果查询返回的不是一条数据或者null如果有多条直接抛异常
User loginUser userDao.selectOne(lqw);
System.out.println(loginUser);- 购物设定价格区间、户籍设定年龄区间le ge匹配 或 between匹配LambdaQueryWrapperUser lqw new LambdaQueryWrapperUser();
//范围查询 lt le gt ge eq between
lqw.between(User::getAge, 10, 30);
ListUser userList userDao.selectList(lqw);
System.out.println(userList);- 查信息搜索新闻非全文检索版like匹配//模糊匹配
LambdaQueryWrapperUser lqw new LambdaQueryWrapperUser();
//%_必须是一个
//likeLeft() where name like %J
//likeRight() where name like J%
lqw.like(User::getName, J); //where name like %J%
ListUser userList userDao.selectList(lqw);
System.out.println(userList);
/*****************************************************************/
- 排序//排序
LambdaQueryWrapperUser lqw new LambdaQueryWrapperUser();
//lqw.orderByAsc(User::getAge); //升序
lqw.orderByDesc(User::getAge); //降序
ListUser userList userDao.selectList(lqw);
System.out.println(userList);
# 查询API- 更多查询条件设置参看https://baomidou.com/pages/10c804/5、映射匹配兼容【了解】
# 创建新的表tbl_user做测试USE mybatisplus_db;
CREATE TABLE tbl_user (id BIGINT ( 20 ) PRIMARY KEY auto_increment,name VARCHAR ( 32 ) NOT NULL,pwd VARCHAR ( 32 ) NOT NULL,age INT ( 3 ) NOT NULL,tel VARCHAR ( 32 ) NOT NULL,deleted INT(1) DEFAULT 0,version INT(11) DEFAULT 1
);insert into tbl_user(name,pwd,age,tel) values(snake,123456,28,12345678910);
insert into tbl_user(name,pwd,age,tel) values(张益达,123456,22,12345678910);
insert into tbl_user(name,pwd,age,tel) VALUES(张大炮,123456,16,12345678910);// 1.表字段与编码属性设计不同步在模型类属性上方使用TableField属性注解通过value属性设置当前属性对应的数据库表中的字段关系。TableField(value pwd)//给password定义了别名对应数据库中的字段
private String password;// 2.编码中添加了数据库中未定义的属性在模型类属性上方使用TableField注解通过exist属性设置属性在数据库表字段中是否存在默认为true。此属性无法与value合并使用。//select online from user;
TableField(exist false) //设置的属性在数据库表字段中是否存在默认为true存在
private Integer online;// 3.采用默认查询开放了更多的字段查看权限在模型类属性上方使用TableField注解通过select属性设置该属性是否参与查询。此属性与select()映射配置不冲突。
TableField(valuepwd,selectfalse) //将密码阶段设置不参与查询
private String password;//4.表名与编码开发设计不同步在模型类上方使用TableName注解通过value属性设置当前类对应的数据库表名称。Data
TableName(tbl_user)
public class User {/*id为Long类型因为数据库中id为bigint类型并且mybatis有自己的一套id生成方案生成出来的id必须是Long类型*/private Long id;private String name;TableField(value pwd,select false)private String password;private Integer age;private String tel;TableField(exist false) //表示online字段不参与CRUD操作private Boolean online;
}四、DML编程控制【重点】
DQL数据查询语言selectDML数据操作语言insert, update, delete1.ID生成策略控制(Insert)
不同的表应用不同的id生成策略- 日志自增1,2,3,4……
- 购物订单特殊规则FQ23948AK3843
- 外卖单关联地区日期等信息10 04 20200314 34 91
- 关系表可省略id
- ……- id生成策略控制
名称Tableld
类型属性注解
位置模型类中用于表示主键的属性定义上方
作用设置当前类中主键属性的生成策略
相关属性type设置主键属性的生成策略值参照IdType枚举值public class User{Tableld(type IdType.AUTO)/*** AUTO(0):使用数据库id自增策略控制id生成* NONE(1):不设置id生成策略* INPUT(2):用户手工输入id* ASSIGN_ID(3):雪花算法生成id(可兼容数值型与字符串型)* ASSIGN_UUID(4):以UUID生成算法作为id生成策略*/private Long id;
} ** 雪花(snowflake)算法Twitter开源的一个生成不重复ID的算法scala **- 其核心思想是第一个是符号位0代表是正数使用41bit作为毫秒数10bit作为机器的ID5个bit是数据中心5个bit的机器ID12bit作为毫秒内的流水号。0001001101110110101011000011010100110001101000010001000000000010占位符时间戳(41)数据中心5机器ID5流水号 计算机使用一个叫做实时时钟Real-Time Clock简称 RTC的硬件设备来跟踪时间。RTC一般以晶振的形式存在每秒钟产生一次脉冲。操作系统通过读取RTC的脉冲来确定时间的流逝从而计算出当前的日期和时间。当我们电脑中硬件设备受到外界影响就会导致时间的不准确过快或者过慢从而会使得时间校正而在这段或快或慢的时间段中可能出现由雪花算法生成的id但是矫正完之后又有可能生成新的雪花id和上一个id相同。- 时钟回拨可能导致生成重复的ID可以使用第三方成熟方案百度IdGenerator美团Leaf全局策略配置mybatis-plus:global-config:db-config:id-type: assign_id #雪花算法table-prefix: tbl_ # tbl_ User.java - select * from tbl_user# 设置前缀为tbl_的表的id 设置成雪花算法生成的id2.批量操作
1、按照主键删除多条记录//删除指定多条数据
ListLong list new ArrayList();
list.add(1402551342481838081L);
list.add(1402553134049501186L);
list.add(1402553619611430913L);//where id in (1,2,3)
userDao.deleteBatchIds(list);2、 根据主键查询多条记录//查询指定多条数据
ListLong list new ArrayList();
list.add(1L);
list.add(3L);
list.add(4L);
ListUser users userDao.selectBatchIds(list);
3.逻辑删除 - 删除操作业务问题业务数据从数据库中丢弃
- 物理删除将数据从硬盘数据库当中删除delete from user where id 1
- 逻辑删除为数据设置是否可用状态字段删除时设置状态字段为不可用状态
- 数据保留在数据库中update user set deleted1 where id 11、数据库表中添加逻辑删除标记字段deleted默认值为0- 注意不要使用SQL的关键字做为表名或者字段名容易出错所以订单order - orders是否删除字段delete - deleted2、实体类中添加对应字段并设定当前字段为逻辑删除标记字段Data
public class User {private Long id;//逻辑删除字段标记当前记录是否被删除//TableLogic(value 0, delval 1)private Integer deleted;}3、配置全局逻辑删除字面值2和3任选一种即可
mybatis-plus:global-config:db-config:table-prefix: tbl_# 逻辑删除字段名logic-delete-field: deleted# 逻辑删除字面值未删除为0logic-not-delete-value: 0# 逻辑删除字面值删除为1logic-delete-value: 1- 逻辑删除本质其实是修改操作。如果加了逻辑删除字段查询数据时也会自动带上逻辑删除字段。/删除一条数据观察字段deleted变化//deleted会由0 - 1userDao.deleteById(1450393635949465602L);说明当加入了逻辑删除之后后续查询或者更新时自动多一个条件(where deleted 0)4.乐观锁与悲观锁
乐观锁和悲观锁都是用于解决并发场景下的数据竞争问题但是却是两种完全不同的思想。- 它们的使用非常广泛也不局限于某种编程语言或数据库。数据库自身解决并发两种策略:- 悲观锁(Pessimistic Lock)很悲观每次去拿数据的时候都认为别人会修改所以每次在拿数据的时候都会上锁降低了性能适用于写多读少。三种常见的悲观锁解决方案的区别1. synchronized关键字- 线程访问资源时自动获取锁代码块执行完毕后自动释放锁。- 无法手动中断获取锁的线程只能等待锁的释放。- 只支持独占锁不支持公平性设置。- 隐式地进行锁的获取和释放使用相对较简单。2. ReentrantLock类- 可以手动地获取锁和释放锁更灵活地控制锁的粒度。- 可以设置是否公平获取锁即等待时间较长的线程优先获取锁。- 支持可中断获取锁即等待获取锁的线程可被中断。- 支持多个条件变量Condition可以精确地进行线程通信和等待。3. ReadWriteLock接口- 提供读写锁的支持可以允许多个线程同时读取共享数据但只允许一个线程写入数据。- 读锁是共享的可同时被多个线程持有但写锁是独占的只能被一个线程持有。- 读锁的并发性能好于独占锁适用于读操作频繁、写操作较少的场景。- 可以通过读写锁的方式提高并发性能减少对共享资源的争用。总的来说synchronized是最基本且简便的悲观锁实现方式ReentrantLock类提供了更高级的功能和灵活性而ReadWriteLock接口则适用于读多写少的场景。根据具体需求和场景可以选择合适的锁机制来保障线程安全性和性能。-- 关闭数据库自动提交-- 在查询语句后添加for update加行锁
select * from tb_user where id 1 for update;-- 更新数据
-- update xxx-- 事务提交或回滚后锁会释放
commit;
rollback;- 乐观锁(Optimistic Lock)很乐观每次去拿数据的时候都认为别人不会修改所以不会上锁它并非是真的锁但是在更新的时候会判断一下在此期间别人有没有去更新这个数据可以使用版本号等机制使用读多写少性能比悲观锁高。1.数据库表中添加锁标记字段 默认值为1
2.实体类中添加对应字段并设定当前字段为逻辑删除标记字段Data
public class User {private Long id;//省略其他属性Version //用这个字段实现乐观锁private Integer version;
}3、配置乐观锁拦截器实现锁机制对应的动态SQL语句拼装- 如果是常用的功能直接就能用逻辑删除
- 乐观锁并不是所有的更新都要用如果需要用得自己来添加拦截器//mybatis plus的配置类Configuration
public class MpConfig {Beanpublic MybatisPlusInterceptor mpInterceptor() {//1.定义Mp拦截器MybatisPlusInterceptor mpInterceptor new MybatisPlusInterceptor();//2.添加分页拦截器mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());//3.添加乐观锁拦截器: set version version1 where version ?mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return mpInterceptor;}
}4、使用乐观锁机制在修改前必须先获取到对应数据的verion方可正常进行Test
void testUpdate() throws InterruptedException {//1.先通过要修改的数据id将当前数据查询出来//目的在更新之前必须先知道当前的versionUser user userDao.selectById(222L);System.out.println(user);//2.将要修改的属性逐一设置进去user.setName(Jock888);Thread.sleep(15 * 1000); //在休眠期间使用MySQL客户端去修改version值//UPDATE tbl_user SET name?, age?, tel?, version?// WHERE id? AND version? AND deleted0int num userDao.updateById(user);if (num 0 ) { //在我查询 和 修改 之间有其他人线程修改了此数据导致版本号发生了变化//数据库受影响行数0说明修改失败有两种处理方案//1. 提示用户修改失败让用户自行决定是否再次修改System.err.println(修改失败需要再次修改);//2. TODO 重新调用查询修改自动重试(危险)} else {System.out.println(修改成功);}
}- 1、乐观锁实现必须先查询再更新- 2、乐观锁拦截器负责添加2个sql片段update user set version 原来的版本号1 where version原来查询出来的版本号 //UPDATE tbl_user SET name?, age?, tel?, version? WHERE id? AND version?五、代码生成器【了解】
1.MyBatisPlus提供模板
根据数据库中的表字段自动生成实体类、数据层、业务层、表现层代码。第一步添加代码生成器相关依赖
!--代码生成器--
dependencygroupIdcom.baomidou/groupIdartifactIdmybatis-plus-generator/artifactIdversion3.4.1/version
/dependency!--模板引擎:velocity, jsp, freemarker--
dependencygroupIdorg.apache.velocity/groupIdartifactIdvelocity-engine-core/artifactIdversion2.3/version
/dependency第二步编写代码生成器类public class Generator {public static void main(String[] args) {//1. 创建代码生成器对象执行生成代码操作AutoGenerator autoGenerator new AutoGenerator();//设置生成目录autoGenerator.setGlobalConfig(new GlobalConfig().setOutputDir(c:/work));//2. 数据源相关配置读取数据库中的信息根据数据库表结构生成代码DataSourceConfig dataSource new DataSourceConfig();dataSource.setDriverName(com.mysql.cj.jdbc.Driver);dataSource.setUrl(jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezoneUTC);dataSource.setUsername(root);dataSource.setPassword(root);autoGenerator.setDataSource(dataSource);//3. 执行生成操作autoGenerator.execute();}
}2.开发者自定义配置
//设置全局配置GlobalConfig globalConfig new GlobalConfig();
globalConfig.setOutputDir(System.getProperty(user.dir)/mybatisplus_04_generator/src/main/java); //设置代码生成位置globalConfig.setOpen(false); //设置生成完毕后是否打开生成代码所在的目录
globalConfig.setAuthor(Wen阿杜); //设置作者
globalConfig.setFileOverride(true); //设置是否覆盖原始生成的文件
globalConfig.setMapperName(%sDao); //设置数据层接口名%s为占位符指代模块名称
globalConfig.setIdType(IdType.ASSIGN_ID); //设置Id生成策略
autoGenerator.setGlobalConfig(globalConfig);//设置包名相关配置PackageConfig packageInfo new PackageConfig();
packageInfo.setParent(com.abc); //设置生成的包名与代码所在位置不冲突二者叠加组成完整路径
packageInfo.setEntity(pojo); //设置实体类包名:entity, domain
packageInfo.setMapper(dao); //设置数据层包名:mapper
autoGenerator.setPackageInfo(packageInfo);//策略设置StrategyConfig strategyConfig new StrategyConfig();
strategyConfig.setInclude(tbl_user); //设置当前参与生成的表名参数为可变参数
strategyConfig.setTablePrefix(tbl_);
//设置数据库表的前缀名称模块名 数据库表名 - 前缀名 例如 User tbl_user - tbl_strategyConfig.setRestControllerStyle(true); //设置是否启用Rest风格
strategyConfig.setVersionFieldName(version); //设置乐观锁字段名
strategyConfig.setLogicDeleteFieldName(deleted); //设置逻辑删除字段名
strategyConfig.setEntityLombokModel(true); //设置是否启用lombok
autoGenerator.setStrategy(strategyConfig);3、其他实现
- 使用MyBatisX插件
- 开源https://gitee.com/renrenio/renren-security/tree/master/renren-generator
- 公司自己实现的……MyBatis和MyBatisPlus的使用场景
单表操作使用MP不用写SQL语句多表关联查询使用MyBatis在xml中写SQL实现