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)
);
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]');
-- 真实开发中,version(乐观锁)、deleted(逻辑删除)、gmt_create、gmt_modified
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.0.5version>
dependency>
spring:
# 设置开发环境
profiles:
active: dev
# 数据源
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis_plus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
username: root
password: 123456
# Logger Config
logging:
level:
com.baomidou.mybatisplus.samples.quickstart: debug
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
public interface UserMapper extends BaseMapper<User> {}
@SpringBootApplication
@MapperScan("com.baomidou.mybatisplus.samples.quickstart.mapper")
public class QuickstartApplication {
public static void main(String[] args) {
SpringApplication.run(QuickstartApplication.class, args);
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class SampleTest {
@Resource
private UserMapper userMapper;
@Test
public void testSelect() {
System.out.println(("----- selectAll method test ------"));
List<User> userList = userMapper.selectList(null);
Assert.assertEquals(5, userList.size());
userList.forEach(System.out::println);
}
}
// 代码自动生成器
public class KuangCode {
public static void main(String[] args) {
// 需要构建一个 代码自动生成器 对象
AutoGenerator mpg = new AutoGenerator();
// 配置策略
// 1、全局配置
GlobalConfig gc = new GlobalConfig();
String projectPath = System.getProperty("user.dir");
gc.setOutputDir(projectPath+"/src/main/java");
gc.setAuthor("cl");
gc.setOpen(false);
gc.setFileOverride(false); // 是否覆盖
gc.setServiceName("%sService"); // 去Service的I前缀
gc.setIdType(IdType.ID_WORKER);
gc.setDateType(DateType.ONLY_DATE);
gc.setSwagger2(true);
mpg.setGlobalConfig(gc);
//2、设置数据源
DataSourceConfig dsc = new DataSourceConfig();
dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus?
useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("123456");
dsc.setDbType(DbType.MYSQL);
mpg.setDataSource(dsc);
//3、包的配置
PackageConfig pc = new PackageConfig();
pc.setModuleName("blog");
pc.setParent("com.cl");
pc.setEntity("entity");
pc.setMapper("mapper");
pc.setService("service");
pc.setController("controller");
mpg.setPackageInfo(pc);
//4、策略配置
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("blog_tags","course","links","sys_settings","user_record","
user_say"); // 设置要映射的表名
strategy.setNaming(NamingStrategy.underline_to_camel);
strategy.setColumnNaming(NamingStrategy.underline_to_camel);
strategy.setEntityLombokModel(true); // 自动lombok;
strategy.setLogicDeleteFieldName("deleted");
// 自动填充配置
TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);
TableFill gmtModified = new TableFill("gmt_modified",
FieldFill.INSERT_UPDATE);
ArrayList<TableFill> tableFills = new ArrayList<>();
tableFills.add(gmtCreate);
tableFills.add(gmtModified);
strategy.setTableFillList(tableFills);
// 乐观锁
strategy.setVersionFieldName("version");
strategy.setRestControllerStyle(true);
strategy.setControllerMappingHyphenStyle(true); //localhost:8080/hello_id_2
mpg.setStrategy(strategy);
mpg.execute(); //执行
}
}
@Test
public void aInsert() {
User user = new User();
user.setName("小羊");
user.setAge(3);
user.setEmail("[email protected]");
assertThat(mapper.insert(user)).isGreaterThan(0);
// 成功直接拿会回写的 ID
assertThat(user.getId()).isNotNull();
//active record
Assert.assertTrue(user.insert());
// 成功直接拿会写的 ID
System.err.println("\n插入成功 ID 为:" + user.getId());
}
@Test
public void bDelete() {
assertThat(mapper.deleteById(3L)).isGreaterThan(0);
// 删除名字为Sandy的User
assertThat(mapper.delete(new QueryWrapper<User>()
.lambda().eq(User::getName, "Sandy"))).isGreaterThan(0);
// 根据id批量删除
mapper.deleteBatchIds(Arrays.asList(1240620674645544961L,124062067464554496
2L));
// 通过Map删除
HashMap<String, Object> map = new HashMap<>();
map.put("name","Sandy");
mapper.deleteByMap(map);
// active record
Assert.assertTrue(new User().setId(3L).deleteById());
Assert.assertTrue(new User().delete(new QueryWrapper<User>()
.lambda().eq(User::getName, "Sandy")));
}
@Test
public void cUpdate() {
// 将id为1的用户邮箱更新
assertThat(mapper.updateById(new User().setId(1L).setEmail("[email protected]"))).isGreaterThan(0);
// 将id为2的用户名字更改为mp,年龄更改为3
assertThat(
mapper.update(
new User().setName("mp"),
Wrappers.<User>lambdaUpdate()
.set(User::getAge, 3)
.eq(User::getId, 2)
)
).isGreaterThan(0);
User user = mapper.selectById(2);
assertThat(user.getAge()).isEqualTo(3);
assertThat(user.getName()).isEqualTo("mp");
// 将id为2 的用户的邮箱置空
mapper.update(
null,
Wrappers.<User>lambdaUpdate().set(User::getEmail, null).eq(User::getId, 2)
);
assertThat(mapper.selectById(1).getEmail()).isEqualTo("[email protected]");
user = mapper.selectById(2);
assertThat(user.getEmail()).isNull();
assertThat(user.getName()).isEqualTo("mp");
// 将id为2 的用户邮箱更新
mapper.update(
new User().setEmail("[email protected]"),
new QueryWrapper<User>()
.lambda().eq(User::getId, 2)
);
user = mapper.selectById(2);
assertThat(user.getEmail()).isEqualTo("[email protected]");
// 将id为2的用户邮箱更新,年龄置空
mapper.update(
new User().setEmail("[email protected]"),
Wrappers.<User>lambdaUpdate()
.set(User::getAge, null)
.eq(User::getId, 2)
);
user = mapper.selectById(2);
assertThat(user.getEmail()).isEqualTo("[email protected]");
assertThat(user.getAge()).isNull();
// active record
Assert.assertTrue(new User().setId(1L).setEmail("[email protected]").updateById());
Assert.assertTrue(new User().update(new UpdateWrapper<User>().lambda()
.set(User::getAge, 3).eq(User::getId, 2)));
}
@Test
public void dSelect() {
// 插入一条数据
mapper.insert(
new User().setId(10086L)
.setName("miemie")
.setEmail("[email protected]")
.setAge(3));
assertThat(mapper.selectById(10086L).getEmail()).isEqualTo("[email protected]");
// 查询用户id为10086的数据
User user = mapper.selectOne(new QueryWrapper<User>().lambda().eq(User::getId, 10086));
assertThat(user.getName()).isEqualTo("miemie");
assertThat(user.getAge()).isEqualTo(3);
// 查询所有用户的id
mapper.selectList(Wrappers.<User>lambdaQuery().select(User::getId))
.forEach(x -> {
assertThat(x.getId()).isNotNull();
assertThat(x.getEmail()).isNull();
assertThat(x.getName()).isNull();
assertThat(x.getAge()).isNull();
});
// 查询所有用户的id和name
mapper.selectList(new QueryWrapper<User>().select("id", "name"))
.forEach(x -> {
assertThat(x.getId()).isNotNull();
assertThat(x.getEmail()).isNull();
assertThat(x.getName()).isNotNull();
assertThat(x.getAge()).isNull();
});
// 查询id为1、2、3的三个用户
mapper.selectBatchIds(Arrays.asList(1,2,3)).forEach(System.out::println);
// 自定义Map查询
HashMap<String, Object> map = new HashMap<>();
map.put("name","Sandy");
map.put("age",3);
List<User> users = mapper.selectByMap(map);
//active record
Assert.assertEquals("[email protected]", new User().setId(1L).selectById().getEmail());
User user = new User().selectOne(new QueryWrapper<User>().lambda().eq(User::getId, 2));
}
@Test
public void orderBy() {
List<User> users = mapper.selectList(Wrappers.<User>query().orderByAsc("age"));
List<User> users = mapper.selectList(Wrappers.<User>lambdaQuery().orderByAsc(User::getAge));
}
@Test
public void testSelectMaxId() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("max(id) as id");
User user = mapper.selectOne(wrapper);
}
@Test
public void testGroup() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("age, count(*)")
.groupBy("age");
List<Map<String, Object>> maplist = mapper.selectMaps(wrapper);
for (Map<String, Object> mp : maplist) {
System.out.println(mp);
}
/**
* lambdaQueryWrapper groupBy orderBy
*/
LambdaQueryWrapper<User> lambdaQueryWrapper = new QueryWrapper<User>().lambda()
.select(User::getAge)
.groupBy(User::getAge)
.orderByAsc(User::getAge);
for (User user : mapper.selectList(lambdaQueryWrapper)) {
System.out.println(user);
}
}
List<User> plainUsers = userMapper.selectList(new QueryWrapper<User>().eq("role_id", 2L));
List<User> lambdaUsers = userMapper.selectList(new QueryWrapper<User>().lambda().eq(User::getRoleId, 2L));
// select * from role where id in (select id from role where id = 2) ;
List<User> plainUsers2 = userMapper.selectList(new LambdaQueryWrapper<User>()
.inSql(User::getRoleId, "select id from role where id = 2"));
List<User> lambdaUsers2 = userMapper.selectList(new QueryWrapper<User>().lambda()
.inSql(User::getRoleId, "select id from role where id = 2"));
// select * from role where (id =2 or id =3) and age>=20;
List<User> plainUsers3 = userMapper.selectList(new LambdaQueryWrapper<User>()
.nested(i -> i.eq(User::getRoleId, 2L).or().eq(User::getRoleId, 3L))
.and(i -> i.ge(User::getAge, 20)));
List<User> lambdaUsers3 = userMapper.selectList(new QueryWrapper<User>().lambda()
.nested(i -> i.eq(User::getRoleId, 2L).or().eq(User::getRoleId, 3L))
.and(i -> i.ge(User::getAge, 20)));
/**
* SELECT id,name,age,email,role_id FROM user
* WHERE ( 1 = 1 ) AND ( ( name = ? AND age = ? ) OR ( name = ? AND age = ? ) )
*/
QueryWrapper<User> w = new QueryWrapper<>();
w.and(i -> i.eq("1", 1))
.nested(i ->
i.and(j -> j.eq("name", "a").eq("age", 2))
.or(j -> j.eq("name", "b").eq("age", 2)));
userMapper.selectList(w);
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper
.isNotNull("name")
.isNotNull("email")
.ge("age",12);
userMapper.selectList(wrapper).forEach(System.out::println);
// 查询年龄在 20 ~ 30 岁之间的用户
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.between("age",20,30);
// 查询结果数
Integer count = userMapper.selectCount(wrapper);
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 左和右 t%
wrapper
.notLike("name","e")
.likeRight("email","t");
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 通过id进行排序
wrapper.orderByAsc("id");
List<User> users = userMapper.selectList(wrapper);
@Configuration
@MapperScan("com.baomidou.mybatisplus.samples.pagination.mapper")
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
// 开启 count 的 join 优化,只针对 left join !!!
return new PaginationInterceptor().setCountSqlParser(new JsqlParserCountOptimize(true));
}
}
// select * from user where age=20 and name=jack limit 0,5
Page<User> page = new Page<>(1, 5);
page.addOrder(OrderItem.asc("age"));
Page<User> userIPage = mapper.selectPage(page, Wrappers.<User>lambdaQuery().eq(User::getAge, 20).like(User::getName, "Jack"));
assertThat(page).isSameAs(userIPage);
log.error("总条数 -------------> {}", userIPage.getTotal());
log.error("当前页数 -------------> {}", userIPage.getCurrent());
log.error("当前每页显示数 -------------> {}", userIPage.getSize());
List<User> records = userIPage.getRecords();
<dependency>
<groupId>p6spygroupId>
<artifactId>p6spyartifactId>
dependency>
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定义日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志输出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系统记录 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 设置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前缀
useprefix=true
# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 实际驱动可多个
#driverlist=org.h2.Driver
# 是否开启慢SQL记录
outagedetection=true
# 慢SQL记录标准 2 秒
outagedetectioninterval=2
@Configuration
public class MybatisPlusOptLockerConfig {
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
@Order(0)
@Test
public void testUpdateByIdSucc() {
User user = new User();
user.setAge(18);
user.setEmail("[email protected]");
user.setName("optlocker");
user.setVersion(1);
userMapper.insert(user);
Long id = user.getId();
User userUpdate = new User();
userUpdate.setId(id);
userUpdate.setAge(19);
userUpdate.setVersion(1);
assertThat(userMapper.updateById(userUpdate)).isEqualTo(1);
assertThat(userUpdate.getVersion()).isEqualTo(2);
}
@Order(1)
@Test
public void testUpdateByIdSuccFromDb() {
User user = userMapper.selectById(1);
int oldVersion = user.getVersion();
int i = userMapper.updateById(user);
assertThat(i).isEqualTo(1);
assertThat(oldVersion + 1).isEqualTo(user.getVersion());
}
@Order(2)
@Test
public void testUpdateByIdFail() {
User user = new User();
user.setAge(18);
user.setEmail("[email protected]");
user.setName("optlocker");
user.setVersion(1);
userMapper.insert(user);
Long id = user.getId();
User userUpdate = new User();
userUpdate.setId(id);
userUpdate.setAge(19);
userUpdate.setVersion(0);
Assert.assertEquals("Should update failed due to incorrect version(actually 1, but 0 passed in)", 0, userMapper.updateById(userUpdate));
}
@Order(3)
@Test
public void testUpdateByIdSuccWithNoVersion() {
User user = new User();
user.setAge(18);
user.setEmail("[email protected]");
user.setName("optlocker");
user.setVersion(1);
userMapper.insert(user);
Long id = user.getId();
User userUpdate = new User();
userUpdate.setId(id);
userUpdate.setAge(19);
userUpdate.setVersion(null);
Assert.assertEquals("Should update success as no version passed in", 1, userMapper.updateById(userUpdate));
User updated = userMapper.selectById(id);
Assert.assertEquals("Version not changed", 1, updated.getVersion().intValue());
Assert.assertEquals("Age updated", 19, updated.getAge().intValue());
}
/**
* 批量更新带乐观锁
*
* update(et,ew) et:必须带上version的值才会触发乐观锁
*/
@Order(4)
@Test
public void testUpdateByEntitySucc() {
QueryWrapper<User> ew = new QueryWrapper<>();
ew.eq("version", 1);
int count = userMapper.selectCount(ew);
User entity = new User();
entity.setAge(28);
entity.setVersion(1);
Assert.assertEquals("updated records should be same", count, userMapper.update(entity, null));
ew = new QueryWrapper<>();
ew.eq("version", 1);
Assert.assertEquals("No records found with version=1", 0, userMapper.selectCount(ew).intValue());
ew = new QueryWrapper<>();
ew.eq("version", 2);
Assert.assertEquals("All records with version=1 should be updated to version=2", count, userMapper.selectCount(ew).intValue());
}
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("start insert fill ....");
this.strictInsertFill(metaObject, "operator", String.class, "Jetty");
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("start update fill ....");
this.strictUpdateFill(metaObject, "operator", String.class, "Tom");
}
}
@Data
@Accessors(chain = true)
public class Common {
private Long id;
private String name;
/**
* 未删除1,删除0
*/
@TableLogic(delval = "0", value = "1")
private Integer deleted;
}
@Data
@Accessors(chain = true)
public class Null1 {
private Long id;
private String name;
/**
* 未删除1,删除null
*/
@TableLogic(delval = "null", value = "1")
private Integer deleted;
}
@Data
@Accessors(chain = true)
public class Null2 {
private Long id;
private String name;
/**
* 未删除null,删除now()
*/
@TableLogic(delval = "now()", value = "null")
private LocalDateTime delTime;
}
mybatis-plus:
type-enums-package: com.baomidou.mybatisplus.samples.enums.enums
configuration:
# 3.0.8之前版本问题默认将枚举注册为EnumOrdinalTypeHandler,这是错误的方式,默认是 org.apache.ibatis.type.EnumTypeHandler
# 如果项目之中实体统一使用IEnum或注解的方式,可配置成 com.baomidou.mybatisplus.extension.handlers.EnumTypeHandler,也可省略上面的type-enums-package配置
# 配置type-enums-package只对注解方式的枚举处理能提前加载缓存.
default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
public enum AgeEnum implements IEnum<Integer> {
ONE(1, "一岁"),
TWO(2, "二岁"),
THREE(3, "三岁");
private int value;
private String desc;
AgeEnum(final int value, final String desc) {
this.value = value;
this.desc = desc;
}
@Override
public Integer getValue() {
return value;
}
}
@Getter
public enum GradeEnum {
PRIMARY(1, "小学"),
SECONDORY(2, "中学"),
HIGH(3, "高中");
GradeEnum(int code, String descp) {
this.code = code;
this.descp = descp;
}
@EnumValue
private final int code;
private final String descp;
}