建表sql
CREATE DATABASE mybatisplus_db;
USE mybatisplus_db;
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(1,'Tom','tom',3,'18866668888');
INSERT INTO USER VALUES(2,'Jerry','jerry',4,'16688886666');
INSERT INTO USER VALUES(3,'Jock','123456',41,'18812345678');
INSERT INTO USER VALUES(4,'传智播客','itcast',15,'4006184000');
实验步骤
① 创建SpringBoot项目,勾选MySQL Driver
② 添加依赖坐标
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.1version>
dependency>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>druidartifactId>
<version>1.1.16version>
dependency>
注意事项:由于mp未被收录到idea的系统内置配置,无法直接选择加入
③ 配置数据库参数
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://192.168.1.224:3306/mybatisplus_db
username: root
password: 123456
④ 创建domain.User对象
package com.example.domain;
public class User {
private Long id;
private String name;
private String password;
private Integer age;
private String tel;
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", password='" + password + '\'' +
", age=" + age +
", tel='" + tel + '\'' +
'}';
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getTel() {
return tel;
}
public void setTel(String tel) {
this.tel = tel;
}
}
⑤ 定义数据接口,继承BaseMapper
package com.example.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.domain.User;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserDao extends BaseMapper<User> {
}
⑥ 测试类中注入dao接口,测试功能
package com.example;
import com.example.dao.UserDao;
import com.example.domain.User;
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
class SpringbootMybatisplusApplicationTests {
@Autowired
private UserDao userDao;
@Test
void testGetAll() {
List<User> userList = userDao.selectList(null);
System.out.println(userList);
}
}
MyBatisPlus是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率
官网:https://baomidou.com/
MyBatisPlus特性
标准数据层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) |
查询全部 | List getAll() | List selectList() |
分页查询 | pageInfo getAll(int page,int size) | IPage selectPage(IPage page) |
按条件查询 | List getAll(Condition condition) | IPage selectPage(Wrapper queryWrapper) |
测试MP接口
package com.example;
import com.example.dao.UserDao;
import com.example.domain.User;
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
class SpringbootMybatisplusApplicationTests {
@Autowired
private UserDao userDao;
@Test
void testSave(){
User user = new User();
user.setAge(11);
user.setName("小王");
user.setPassword("xiaowang");
user.setTel("123456");
userDao.insert(user);
}
@Test
void testDelete(){
userDao.deleteById(1530454523057905666L);
}
@Test
void testGetById(){
User user = userDao.selectById(1L);
System.out.println(user);
}
@Test
void testUpdate(){
User user = new User();
user.setId(1L);
user.setName("Tom666");
userDao.updateById(user);
}
@Test
void testGetAll() {
List<User> userList = userDao.selectList(null);
System.out.println(userList);
}
}
lombok
导入依赖坐标
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<scope>providedscope>
dependency>
使用lombok注解创建实体类
package com.example.domain;
import lombok.*;
//@Setter
//@Getter
//@ToString
//@NoArgsConstructor
//@AllArgsConstructor
//@EqualsAndHashCode
@Data
public class User {
private Long id;
private String name;
private String password;
private Integer age;
private String tel;
}
@Data可以代替get/set方法,有参/无参构造器方法,toString方法,hashCoded方法,equals方法等
① 设置分页拦截器作为Spring管理的bean
package com.example.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MpConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//1.定义Mp拦截器
MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
//2.在Mp拦截器中添加具体的拦截器
mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return mpInterceptor;
}
}
② 测试分页功能
@Test
void testGetByPage(){
IPage page = new Page(1,2);
userDao.selectPage(page,null);
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());
}
开启日志
# 开启mp的日志(输出到控制台的日志)
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
MyBatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合
关闭系统日志显示
resources包下创建logback.xml文件
<configuration>
configuration>
修改配置文件
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://192.168.1.224:3306/mybatisplus_db
username: root
password: 123456
main:
banner-mode: off
# 开启mp的日志(输出到控制台的日志)
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
banner: false
条件查询示例
@Test
void testGetAll(){
//方式一:按条件查询
// QueryWrapper qw = new QueryWrapper();
// qw.lt("age",18);
// List userList = userDao.selectList(qw);
// System.out.println(userList);
//方式二:lambda格式按条件查询
// QueryWrapper qw = new QueryWrapper<>();
// qw.lambda().lt(User::getAge,18);
// List userList = userDao.selectList(qw);
// System.out.println(userList);
//方式三:lambda格式按条件查询
// LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
// lqw.lt(User::getAge,18);
// List userList = userDao.selectList(lqw);
// System.out.println(userList);
//多条件
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
//18到50之间
// lqw.lt(User::getAge,50);
// lqw.gt(User::getAge,18);
//链式编程
// lqw.lt(User::getAge,50).gt(User::getAge,18);
//小于10岁或者大于18岁
lqw.lt(User::getAge,10).or().gt(User::getAge,18);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
用于限定age的上限
package com.example.domain.query;
import com.example.domain.User;
import lombok.Data;
@Data
public class UserQuery extends User {
private Integer age2;
}
测试
@Test
void testGetAll2() {
//模拟页面传递过来的查询数据
UserQuery uq = new UserQuery();
uq.setAge(10);
// uq.setAge2(30);
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
//先判定第一个条件是否为true,如果为true连接当前条件
lqw.lt(null != uq.getAge2(),User::getAge,uq.getAge2())
.gt(null != uq.getAge(),User::getAge,uq.getAge());
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
@Test
void testGetAll3() {
//查询投影
// LambdaQueryWrapper lqw = new LambdaQueryWrapper<>();
// lqw.select(User::getId,User::getName,User::getAge);
QueryWrapper lqw = new QueryWrapper<>();
lqw.select("id","name","age");
// List userList = userDao.selectList(lqw);
// System.out.println(userList);
QueryWrapper<User> lqw = new QueryWrapper<>();
lqw.select("count(*) as count,tel")
.groupBy("tel");
List<Map<String,Object>> userList = userDao.selectMaps(lqw);
System.out.println(userList);
}
https://baomidou.com/pages/10c804/
查询条件在 核心功能 的 条件构造器 中查找
@Test
void testGetAll4() {
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<>();
//等同于=
// lqw.eq(User::getName,"Jerry")
// .eq(User::getPassword,"jerry");
// User user = userDao.selectOne(lqw);
// System.out.println(user);
//范围发查询lt le gt ge between
// lqw.between(User::getAge,10,30);
// List userList = userDao.selectList(lqw);
// System.out.println(userList);
//模糊匹配
lqw.like(User::getName,"J");
// lqw.likeRight(User::getName,"J");
// lqw.likeLeft(User::getName,"J");
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
1.问题一:表字段与编码属性设计不同步
@TableField:设置当前属性对应的数据库表中的字段关系
public class User {
@TableField(value = "pwd")
private String password;
}
2.问题二:编码中添加了数据库中未定义的属性
public class User {
@TableField(exist = "false")
private Integer online;
}
3.问题三:采用默认查询开放了更多的字段查询权限
public class User {
@TableField(value = "pwd",select = false)
private String password;
}
4.问题四:表名与编码开发设计不同步
@TableName:设置当前类对应于数据库表关系
@TableName("tbl_user")
public class User {
@TableField(value = "pwd",select = false)
private String password;
}
不同的表应用不同的id生成策略
1.日志:自增(1,2,3,4,……)
2.购物订单:特殊规则(FQ23948AK3843)
3.外卖单:关联地区日期等信息(10 04 20200314 34 91)
4.关系表:可省略id
…
@TableId:设置当前类中主键属性的生成策略
public class User {
@TableId(type = IdType.AUTO)
private Long id;
}
全局配置
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
global-config:
banner: false
db-config:
#id自增策略
id-type: assign_id
#表名前缀
table-prefix: tbl_
添加和多数据删除
@Test
void testInsert(){
User user = new User();
user.setAge(11);
user.setName("小王");
user.setPassword("xiaowang");
user.setTel("123456");
User user1 = new User();
user1.setAge(12);
user1.setName("小华");
user1.setPassword("xiaohua");
user1.setTel("1234568");
userDao.insert(user);
userDao.insert(user1);
}
@Test
void testDelete(){
List<Long> list = new ArrayList<>();
list.add(1530525838229913601L);
list.add(1530525929594437633L);
userDao.deleteBatchIds(list);
// List list = new ArrayList<>();
// list.add(1L);
// list.add(2L);
// userDao.selectBatchIds(list);
}
逻辑删除
删除业务问题:业务数据从数据库中丢弃
逻辑删除:为数据设置是否可用状态字段,删除时设置状态字段为不可用状态,数据保留在数据库中。
mysql的user表添加一个delete字段(int,长度为1,默认值为0)
User中添加逻辑删除字段的属性
package com.example.domain;
import com.baomidou.mybatisplus.annotation.TableLogic;
import lombok.*;
@Data
public class User {
// @TableId(type = IdType.AUTO)
private Long id;
private String name;
private String password;
private Integer age;
private String tel;
//逻辑删除字段,标记当前是否被删除
@TableLogic(value = "0",delval = "1")
private Integer deleted;
}
进行逻辑删除
@Test
void testDelete(){
userDao.deleteById(1L);
}
全局配置代替注解
mybatis-plus:
global-config:
db-config:
logic-delete-field: deleted
logic-delete-value: 1
logic-not-delete-value: 0
① 给user添加字段version(int,长度11,默认值1)
② 在实体类中添加属性和注解
package com.example.domain;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.*;
@Data
public class User {
// @TableId(type = IdType.AUTO)
private Long id;
private String name;
private String password;
private Integer age;
private String tel;
//逻辑删除字段,标记当前是否被删除
// @TableLogic(value = "0",delval = "1")
private Integer deleted;
@Version
private Integer version;
}
③ 添加乐观锁的拦截器
package com.example.config;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MpConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//1.定义Mp拦截器
MybatisPlusInterceptor mpInterceptor = new MybatisPlusInterceptor();
//2.在Mp拦截器中添加具体的拦截器
mpInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
//3.添加乐观锁的拦截器
mpInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return mpInterceptor;
}
}
④ 测试
@Test
void testUpdate(){
// User user = new User();
// user.setId(3L);
// user.setName("Jock666");
// user.setVersion(1);
// userDao.updateById(user);
//1.先通过要修改的数据id将当前数据查询出来
User user = userDao.selectById(3L); //version=3
User user2 = userDao.selectById(3L);//version=3
//2.将要修改的属性逐一设置进去
user2.setName("Jock999");
userDao.updateById(user2);//version=4
user.setName("Jock888");
userDao.updateById(user);//version不等于3,失效
}
模板:MyBatisPlus提供
数据库相关配置:读取数据库获取信息
开发者自定义配置:手工配置
① 添加依赖坐标
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-generatorartifactId>
<version>3.4.1version>
dependency>
<dependency>
<groupId>org.apache.velocitygroupId>
<artifactId>velocity-engine-coreartifactId>
<version>2.3version>
dependency>
② 代码生成器
package com.example;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
public class Generator {
public static void main(String[] args) {
//1.获取代码生成器的对象
AutoGenerator autoGenerator = new AutoGenerator();
//设置数据库相关配置
DataSourceConfig datasource = new DataSourceConfig();
datasource.setDriverName("com.mysql.cj.jdbc.Driver");
datasource.setUrl("jdbc:mysql://192.168.1.224:3306/mybatisplus_db");
datasource.setUsername("root");
datasource.setPassword("123456");
autoGenerator.setDataSource(datasource);
//设置全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir(System.getProperty("user.dir")+"/src/main/java"); //设置代码生成位置
globalConfig.setOpen(false); //设置生成完毕后是否打开生成代码所在的目录
globalConfig.setAuthor("www"); //设置作者
globalConfig.setFileOverride(true); //设置是否覆盖原始生成的文件
globalConfig.setMapperName("%sDao"); //设置数据层接口名,%s为占位符,指代模块名称
globalConfig.setIdType(IdType.ASSIGN_ID); //设置Id生成策略
autoGenerator.setGlobalConfig(globalConfig);
//设置包名相关配置
PackageConfig packageInfo = new PackageConfig();
packageInfo.setParent("com.test"); //设置生成的包名,与代码所在位置不冲突,二者叠加组成完整路径
packageInfo.setEntity("domain"); //设置实体类包名
packageInfo.setMapper("dao"); //设置数据层包名
autoGenerator.setPackageInfo(packageInfo);
//策略设置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setInclude("user"); //设置当前参与生成的表名,参数为可变参数
strategyConfig.setTablePrefix(""); //设置数据库表的前缀名称,模块名 = 数据库表名 - 前缀名 例如: User = tbl_user - tbl_
strategyConfig.setRestControllerStyle(true); //设置是否启用Rest风格
strategyConfig.setVersionFieldName("version"); //设置乐观锁字段名
strategyConfig.setLogicDeleteFieldName("deleted"); //设置逻辑删除字段名
strategyConfig.setEntityLombokModel(true); //设置是否启用lombok
autoGenerator.setStrategy(strategyConfig);
//2.执行生成操作
autoGenerator.execute();
}
}