所有的crud的代码都可以自动完成
JAP、tk -mapper、mybatis-plus
地址:官网地址
使用第三方插件
导入依赖
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.1version>
dependency>
写入配置
编写代码
步骤
创建数据库 mybatis-plus
创建表
DROP TABLE IF EXISTS user;
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)
);
-- 真实开发中 version(乐观锁)、deleted(逻辑删除) gmt_create、gmt_modified
插入数据
INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, '[email protected]'),
(2, 'Jack', 20, '[email protected]'),
(3, 'Tom', 28, '[email protected]'),
(4, 'Sandy', 21, '[email protected]'),
(5, 'Billie', 24, '[email protected]');
添加依赖
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.0.5version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.37version>
dependency>
连接数据库
mysql 5 和,mysql8有区别,但是可以先前兼容,但不同版本最好写成不一样的
# mysql5 com.mysql.jdbc.Driver
# mysql8 com.mysql.cj.jdbc.Driver 需要增加时区配置 serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis-plus?useSSL=false&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#运行错误
#1、就是mysql版本不能太高
#2、单元测试少包
#配置日志,输出到控制台
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
逻辑代码
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Lf9T3tq-1607589902913)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1607155042072.png)]
@Repository
public interface UserMapper extends BaseMapper<User> {
}
@MapperScan("com.yanghao.mybatis_plus.mapper")
@SpringBootApplication
public class MybatisPlusApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisPlusApplication.class, args);
}
}
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
//对应数据库中主键(uuid、自增id、雪花算法、redis、zookeeper)
@TableId(type = IdType.ID_WORKER)
private Long id;//这要用大写的Long
private String name;
private Integer age;
private String email;
}
思考问题?
测试插入
@SpringBootTest
class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
// 查询所有
@Test
void contextLoads() {
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
// 插入
@Test
void contextLoads2() {
User user = new User();
user.setAge(12);
user.setName("zhangsan");
user.setEmail("[email protected]");//帮我们自动生成id
int insert = userMapper.insert(user);
System.out.println(insert);
}
//更新,通过字符串进行拼接,传入的是一个对象
@Test
void contextLoads3() {
User user = new User();
user.setId(0L);
user.setName("lisi");
int insert = userMapper.updateById(user);
System.out.println(user);
System.out.println(insert);
}
}
主键自增
//自增,但是数据库必须成设置自增,否则报错
@TableId(type = IdType.AUTO)
private Long id;//这要用大写的Long
//其他源码解释
public enum IdType {
AUTO(0),//自增
NONE(1),//未设置
INPUT(2),//需要手动设置id
ASSIGN_ID(3),
ASSIGN_UUID(4),//uuid
ID_WORKER(3),//默认全局唯一
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5yprtXjC-1607589902917)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1607156182834.png)]
自动填充
创建时间、修改时间。这些操作自动完成。
数据库界级别
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NUwJO3kY-1607589902919)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1607158676929.png)]
代码级别的自动填充时间
//实体类中的配置
@TableField(fill = FieldFill.INSERT)//插入的时候起作用
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)//更新和插入的时候都起作用
private Date updateTime;
//需要配置类中说明
//@Slf4j是用作日志输出的,一般会在项目每个类的开头加入该注解,如果不写下面这段代码,并且想用log
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
// 插入时填充策略
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill");
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
//更新时填充策略
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill");
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
乐观锁:顾名思义,认为不会出现问题,出了问题,再更新测试
悲观锁:干什么都会上锁。
乐观锁实现方式:
取出记录时,获取版本version
更新时带上这个版本
执行更新时 set version=new version where version =oldversion
如果version不对,就更新失效
乐观锁 1、先查询,获取版本号 version=1
A---
set name='张三' ,version=version+1 where version=1 and id=2
B---线程强先完成,会导致A更新失败
set name='李四' ,version=version+1 where version=1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TO0fSqVe-1607589902926)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1607232089902.png)]
1、添加字段
@Version //乐观锁version注解
private Integer version;
2、注册组件
@MapperScan("com.yanghao.mybatis_plus.mapper")//可以把启动类中的注解移到这
@EnableTransactionManagement //开启事务
@Configuration//配置类
public class MybatisPlusConfig {
//注册乐观锁组件
@Bean
public OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor(){
return new OptimisticLockerInnerInterceptor();
}
}
//上面那个拦截器用不了,需要包装一层MybatisPlusInterceptor
@MapperScan("com.yanghao.mybatis_plus.mapper")//可以把启动类中的注解移到这
@EnableTransactionManagement //开启事务
@Configuration//配置类
public class MybatisPlusConfig {
//注册乐观锁组件
@Bean
public MybatisPlusInterceptor optimisticLockerInnerInterceptor() {
// return new OptimisticLockerInnerInterceptor();
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
3、测试
//测试乐观锁,第一个user没更改成功
@Test
void contextLoads4() {
User user = userMapper.selectById(0L);
user.setName("yanghao");
//模拟另一个线程插队
User user2 = userMapper.selectById(0L);
user2.setName("lihao");
userMapper.updateById(user2);
//可以尝试使用自旋锁。
userMapper.updateById(user);
}
//根据id查询多个用户
@Test
void contextLoads5() {
// List users = userMapper.selectList();
List<User> users = userMapper.selectBatchIds(Arrays.asList(0, 1, 2));
users.forEach(System.out::println);
} //按条件查询之一使用map,就是存储的where条件
@Test
void contextLoads6() {
HashMap<String, Object> map = new HashMap<>();
map.put("name","lihao");
map.put("age",18);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
网站分页技术非常多!
如何使用
配置拦截器插件即可
@Bean
public PaginationInnerInterceptor paginationInnerInterceptor(){
return new PaginationInnerInterceptor();
}
//上面这个不好使啦
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
直接使用page对象即可
@Test
void contextLoads7() {
/**
* @Param 1 当前页
* @Param 2 当前页大小
*/
Page<User> page = new Page<>(1,5);
Page<User> userPage = userMapper.selectPage(page, null);
userPage.getRecords().forEach(System.out::println);
System.out.println(page.getTotal());
}
@Test
void contextLoads9() {
int i = userMapper.deleteBatchIds(Arrays.asList(0,1));
}
//通过map删除,map代表where后面的条件
@Test
void contextLoads10() {
HashMap<String, Object> map = new HashMap<>();
map.put("name","Tom");
int i = userMapper.deleteByMap(map);
}
物理删除:从数据库总删除
逻辑删除:用一个变量表示他删除,其实没删除,类似于垃圾箱。delete
管理员可以查看
@TableLogic //逻辑删除
private Integer deleted;
配置文件
mybatis-plus.global-config.db-config.logic-delete-value=1 #表示逻辑删除
mybatis-plus.global-config.db-config.logic-not-delete-value=0 #表示未删除
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YywRKYYE-1607589902926)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1607250796786.png)]
//是一个更新操作,并不删除
int i = userMapper.deleteBatchIds(Arrays.asList(2));
#配置开发环境
spring.profiles.active=dev
作用:拦截慢sql,用于输出每条sql运行时间
导入插件
这个性能分析插件早,3.2以上就没有啦
@Bean
@Profile({
"dev", "test"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {
return new PerformanceInterceptor();
}
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>
测试使用
@Test
void contextLoads() {
// 查询 name 不为空的用户,并且邮箱不为空的用户,年龄大于等于12
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.isNotNull("name")
.isNotNull("email")
.ge("age","12");//ge表示大于
userMapper.selectList(wrapper).forEach(System.out::println);// 和我们学习的 Map 对于以下
}
@Test
void contextLoads2() {
// 查询 name 不为空的用户,并且邮箱不为空的用户,年龄大于等于12
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.eq("name","yanghao");//name等于yanghao
userMapper.selectOne(wrapper).forEach(System.out::println);// 和我们学习的 Map 对于以下
}
@Test
void contextLoads13() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.between("age",20,24);
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
//左右模糊查询
@Test
void contextLoads14() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.notLike("name","e")
.likeRight("email","t");
//Preparing: SELECT id,name,age,email,create_time,update_time,version,deleted //FROM user WHERE deleted=0 AND (name NOT LIKE ? AND email LIKE ?)
//==> Parameters: %e%(String), t%(String)
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
maps.forEach(System.out::println);
}
//嵌套查询
@Test
void contextLoads15() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.inSql("id","select id from user where id<5");
userMapper.selectList(wrapper).forEach(System.out::println);
}
//排序查询
@Test
void contextLoads16() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.orderByDesc("id");//按id降序查询
wrapper.orderByAsc("id");//升序排列
userMapper.selectList(wrapper).forEach(System.out::println);
}
AutoGenerator是mybatis-plus的自动生成器,可以快速生成Entity、Mapper、Mapper.xml、service
等各种模块,提高效率。
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-generatorartifactId>
<version>${mybatisPlus.version}version>
dependency>
<dependency>
<groupId>org.apache.velocitygroupId>
<artifactId>velocity-engine-coreartifactId>
<version>2.0version>
dependency>
自动生成代码
public class GenerateCode {
public static void main(String[] args) {
//构建代码生成器对象
AutoGenerator generator = new AutoGenerator();
GlobalConfig gc = new GlobalConfig();//全局配置
String property = System.getProperty("user.dir");//项目目录
gc.setOutputDir(property+"/src/main/java");
gc.setAuthor("yanghao");
gc.setOpen(false);
gc.setFileOverride(false);//是否覆盖
gc.setServiceName("%sService");//去掉Service的I前缀
gc.setIdType(IdType.ID_WORKER);
gc.setDateType(DateType.ONLY_DATE);
gc.setSwagger2(true);
generator.setGlobalConfig(gc);
//设置数据源
DataSourceConfig config = new DataSourceConfig();
config.setUrl("jdbc:mysql://localhost:3306/mybatis-plus?useSSL=false&useUnicode=true&characterEncoding=utf-8");
config.setUsername("root");
config.setPassword("root");
config.setDriverName("com.mysql.jdbc.Driver");
config.setDbType(DbType.MYSQL);
generator.setDataSource(config);
//包的配置
PackageConfig packageConfig = new PackageConfig();
packageConfig.setModuleName("com.yanghao.mybatis_plus");
packageConfig.setParent("com.yanghao.mybatis_plus");
packageConfig.setEntity("entity");
packageConfig.setMapper("mapper");
packageConfig.setService("service");
packageConfig.setController("controller");
generator.setPackageInfo(packageConfig);
//策略配置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setInclude("user");//设置映射的表名
strategyConfig.setNaming(NamingStrategy.underline_to_camel);//驼峰命名法
strategyConfig.setColumnNaming(NamingStrategy.underline_to_camel);
//strategyConfig.setSuperEntityClass("自己的父类实体,没有就不用设置");
strategyConfig.setEntityLombokModel(true);
strategyConfig.setRestControllerStyle(true);
strategyConfig.setLogicDeleteFieldName("deleted");
//自动填充配置
TableFill gmt_createTime = new TableFill("gmt_create", FieldFill.INSERT);
TableFill gmt_updateTime = new TableFill("gmt_update",FieldFill.INSERT_UPDATE);
ArrayList<TableFill> tableFill = new ArrayList<>();
tableFill.add(gmt_createTime);
tableFill.add(gmt_updateTime);
strategyConfig.setTableFillList(tableFill);
//乐观锁配置
strategyConfig.setVersionFieldName("version");
strategyConfig.setControllerMappingHyphenStyle(true);
generator.setStrategy(strategyConfig);
generator.execute();
}
}
特此说明:
本文章来自狂神,可以bilibili搜索狂神说。