package com.atguigu.mybatisplus;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@MapperScan("com.atguigu.mybatisplus.mapper")
@SpringBootApplication
public class MybatisApplication {
public static void main(String[] args) {
SpringApplication.run(MybatisApplication.class,args);
}
}
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.likejingroupId>
<artifactId>mybatis-plusartifactId>
<version>1.0-SNAPSHOTversion>
<parent>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-parentartifactId>
<version>1.4.2.RELEASEversion>
<relativePath />
parent>
<dependencies>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starterartifactId>
dependency>
<dependency>
<groupId>com.baomidougroupId>
<artifactId>mybatis-plus-boot-starterartifactId>
<version>3.4.1version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
<exclusions>
<exclusion>
<groupId>org.junit.vintagegroupId>
<artifactId>junit-vintage-engineartifactId>
exclusion>
exclusions>
dependency>
dependencies>
project>
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:13306/mytest?useUnicode=true&characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource.password=abc123
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
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]');
package com.atguigu.mybatisplus.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("user")
public class User {
@TableId(value = "id")//主键列
private Long id;
@TableField(value = "name")//mp 会自动将数据库中的下划线风格转换为驼峰风格
private String name;
private Integer age;
private String email;
}
package com.atguigu.mybatisplus.mapper;
import com.atguigu.mybatisplus.entity.User;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import java.util.List;
public interface UserMapper extends BaseMapper<User>{
List<User> selectAllByName(String name);
}
DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.mybatisplus.mapper.UserMapper">
<sql id="Base_Column_List">
id, name, age, email
sql>
<select id="selectAllByName" resultType="com.atguigu.mybatisplus.entity.User">
select
<include refid="Base_Column_List"/>
from user
where
name = #{name}
select>
mapper>
package com.atguigu.mybatisplus.service;
import com.atguigu.mybatisplus.entity.User;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
public interface UserService extends IService<User> {
List<User> listAllUserByName(String name);
}
package com.atguigu.mybatisplus.service.impl;
import com.atguigu.mybatisplus.entity.User;
import com.atguigu.mybatisplus.mapper.UserMapper;
import com.atguigu.mybatisplus.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
@Resource
UserMapper userMapper;
@Override
public List<User> listAllUserByName(String name) {
return userMapper.selectAllByName(name);
}
}
package com.atguigu.mybatisplus;
import com.atguigu.mybatisplus.entity.User;
import com.atguigu.mybatisplus.mapper.UserMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MapperTest {
@Resource//按名称注入(autowired按类型注入)
UserMapper userMapper;
@Test
public void testSelcetList(){
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
}
package com.atguigu.mybatisplus;
import com.atguigu.mybatisplus.entity.User;
import com.atguigu.mybatisplus.mapper.UserMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class MyMapperTest {
@Resource//按名称注入(autowired按类型注入)
UserMapper userMapper;
@Test
public void testSelcetList(){
List<User> jone = userMapper.selectAllByName("Jone");
jone.forEach(System.out::println);
}
}
#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto
//插入时填充
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;
//更新时填充
@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
package com.atguigu.mybatisplus.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
@Component
@Slf4j
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
//注意此方法只要在填充时就回调用,效率不高,因为多个表需要填充,但是每次可能执行填充一个,但是全部都执行
log.info("填充插入");
//实现填充业务逻辑
this.strictInsertFill(metaObject,"createTime",LocalDateTime.class, LocalDateTime.now());
this.strictInsertFill(metaObject,"updateTime",LocalDateTime.class, LocalDateTime.now());
//判断当前对象的自动填充是否包含属性
boolean author = metaObject.hasSetter("author");
if(author) {
log.info("插入其他表");
this.strictInsertFill(metaObject, "author", LocalDateTime.class, LocalDateTime.now());
}
//判断当前对象的自动填充是否已经赋值
Object age = this.getFieldValByName("age", metaObject);
if(age==null) {
this.strictInsertFill(metaObject, "age", Integer.class, 3);
}
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("填充修改");
this.strictInsertFill(metaObject,"updateTime",LocalDateTime.class, LocalDateTime.now());
}
}
@TableLogic
@TableField(value = "is_deleted")
//字段为0表示没删(false),1表示删除了(true)
private Boolean deleted;
userMapper.deleteById(2L);
package com.atguigu.mybatisplus.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MybatisPlusConfig {
//注入分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
package com.atguigu.mybatisplus;
import com.atguigu.mybatisplus.entity.User;
import com.atguigu.mybatisplus.mapper.UserMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class InterceptorTest {
@Resource
UserMapper userMapper;
@Test
public void testSelectPage(){
//分页插件填充了userPage的属性值
//然后执行sql语句也填充了userPage的分页查询
Page<User> userPage = new Page<>(2, 5);
userMapper.selectPage(userPage, null);
List<User> records = userPage.getRecords();
records.forEach(System.out::println);
}
}
IPage<User> selectPageByPage(Page<?> page, Integer age);
<select id="selectPageByPage" resultType="com.atguigu.mybatisplus.entity.User">
SELECT <include refid="Base_Column_List"/> FROM user WHERE age > #{age}
select>
@Test
public void testSelectPageVo(){
Page<User> pageParam = new Page<>(1,5);
userMapper.selectPageByPage(pageParam, 18);
List<User> users = pageParam.getRecords();
users.forEach(System.out::println);
}
CREATE TABLE product
(
id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID',
name VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名称',
price INT(11) DEFAULT 0 COMMENT '价格',
version INT(11) DEFAULT 0 COMMENT '乐观锁版本号',
PRIMARY KEY (id)
);
INSERT INTO product (id, NAME, price) VALUES (1, '笔记本', 100);
package com.atguigu.mybatisplus.entity;
import lombok.Data;
@Data
public class Product {
private Long id;
private String name;
private Integer price;
private Integer version;
}
package com.atguigu.mybatisplus.mapper;
import com.atguigu.mybatisplus.entity.Product;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
public interface ProductMapper extends BaseMapper<Product> {
}
package com.atguigu.mybatisplus;
import com.atguigu.mybatisplus.entity.Product;
import com.atguigu.mybatisplus.mapper.ProductMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestConcurrentUpdate {
@Resource
ProductMapper productMapper;
@Test
public void test(){
//小李取数据
Product product = productMapper.selectById(1L);
//小王取数据
Product product1 = productMapper.selectById(1L);
//小李修改+50
product.setPrice(product.getPrice()+50);
productMapper.updateById(product);
//小王修改-30
product1.setPrice(product1.getPrice()-30);
productMapper.updateById(product1);
//老板看价格
Product product2 = productMapper.selectById(1L);
System.out.println("老板看价格"+product2);
}
}
package com.atguigu.mybatisplus.config;
import com.baomidou.mybatisplus.annotation.DbType;
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.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
@MapperScan("com.atguigu.mybatisplus.mapper")
public class MybatisPlusConfig {
//注入分页插件
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
//分页插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
//乐观锁插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
return interceptor;
}
}
package com.atguigu.mybatisplus.entity;
import com.baomidou.mybatisplus.annotation.Version;
import lombok.Data;
@Data
public class Product {
private Long id;
private String name;
private Integer price;
@Version
private Integer version;
}
package com.atguigu.mybatisplus;
import com.atguigu.mybatisplus.entity.Product;
import com.atguigu.mybatisplus.mapper.ProductMapper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
@RunWith(SpringRunner.class)
@SpringBootTest
public class TestConcurrentUpdate {
@Resource
ProductMapper productMapper;
@Test
public void test(){
//小李取数据
Product product = productMapper.selectById(1L);
//小王取数据
Product product1 = productMapper.selectById(1L);
//小李修改+50
product.setPrice(product.getPrice()+50);
productMapper.updateById(product);
//小王修改-30
product1.setPrice(product1.getPrice()-30);
int i = productMapper.updateById(product1);
if(i==0){
product1 = productMapper.selectById(1L);
product1.setPrice(product1.getPrice()-30);
productMapper.updateById(product1);
}
//老板看价格
Product product2 = productMapper.selectById(1L);
System.out.println("老板看价格"+product2);
}
}
package com.atguigu.mybatisplus;
import com.atguigu.mybatisplus.entity.User;
import com.atguigu.mybatisplus.mapper.UserMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RunWith(SpringRunner.class)
@SpringBootTest
public class WrapperTest {
@Resource
UserMapper userMapper;
@Test
public void testMapSelect(){
//map只能用and连接查询条件
//自定义sql语句
//SELECT id,name,age,email,create_time,update_time,is_deleted AS deleted FROM user
// WHERE name = ? AND age = ? AND is_deleted=0
HashMap<String, Object> map = new HashMap<>();
map.put("name","Jone");
map.put("age",18);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
//查询名字中包含n,年龄大于等于10且小于等于20,email不为空的用户
@Test
public void testWrapper1(){
//SELECT id,name,age,email,create_time,update_time,is_deleted AS deleted FROM user
// WHERE is_deleted=0
// AND (name LIKE ? AND age BETWEEN ? AND ?)
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.like("name","n");//name Like %n%
queryWrapper.between("age",10,20);//age BETWEEN 10 AND 20
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
//按年龄降序查询用户,如果年龄相同则按id升序排列
@Test
public void testWrapper2(){
//SELECT id,name,age,email,create_time,update_time,is_deleted AS deleted FROM user
// WHERE is_deleted=0
// ORDER BY age DESC,id ASC
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("age");
queryWrapper.orderByAsc("id");
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
//删除email为空的用户
@Test
public void testWrapper3(){
//UPDATE user SET is_deleted=1
// WHERE is_deleted=0 AND (email IS NULL)
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.isNull("email");
int delete = userMapper.delete(queryWrapper);
}
//查询名字中包含n,且(年龄小于18或email为空的用户),并将这些用户的年龄设置为18,邮箱设置为 [email protected]
@Test
public void testWrapper4(){
//UPDATE user SET age=?, email=?, update_time=?
// WHERE is_deleted=0 AND
// (name LIKE ? AND (age < ? OR email IS NULL))
//组装查询条件注意:不加连接就是and
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
.like("name","n")
.and(i ->i.lt("age",18)
.or().isNull("email"));
//组装更新条件
User user = new User();
user.setAge(18);
user.setEmail("[email protected]");
//执行更新
userMapper.update(user,queryWrapper);
}
//查询所有用户的用户名和年龄
@Test
public void testWrapper5(){
//SELECT name,age FROM user
// WHERE is_deleted=0
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//组装select语句,通常会和selectMaps一起出现
queryWrapper.select("name","age");
List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);
maps.forEach(System.out::println);
}
//查询id不大于3的所有用户的id列表
@Test
public void testWrapper6(){
//SELECT id,name,age,email,create_time,update_time,is_deleted AS deleted
// FROM user
// WHERE is_deleted=0 AND
// (id IN (select id from user where id <= 3))
//不推荐,不如直接写sql语句。
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.inSql("id","select id from user where id <= 3");
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
//查询名字中包含n,且(年龄小于18或email为空的用户),并将这些用户的年龄设置为18,邮箱设置为 [email protected]
@Test
public void testWrapper7(){
//UPDATE user SET age=?,email=?
// WHERE is_deleted=0 AND
// (name LIKE ? AND (age < ? OR email IS NULL))
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper
.set("age",18)
.set("email","[email protected]")
.like("name","n")
.and(i ->i.lt("age",18)
.or().isNull("email"));
//执行更新
//前面为null,没有自动填充功能,为user,有自动填充功能
userMapper.update(new User(),wrapper);
}
//查询名字中包含n,年龄大于10且小于20的用户,查询条件来源于用户输入,是可选的
@Test
public void testWrapper8(){
// SELECT id,name,age,email,create_time,update_time,is_deleted AS deleted FROM user
// WHERE is_deleted=0
// AND (name LIKE ? AND age >= ? AND age <= ?)
String name = "n";
Integer ageBegin = 10;
Integer ageEnd = 20;
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//如果用户没有输入则不进行查询
if(StringUtils.isNotBlank(name)){
queryWrapper.like("name",name);
}
//简化开发,直接将判断条件写入
queryWrapper.ge(ageBegin != null,"age",ageBegin);
if(ageEnd != null){
queryWrapper.le("age",ageEnd);
}
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
//lambda就是可以直接利用User::getName可以直接获得在数据库表中的名称
@Test
public void testWrapper9(){
String name = "n";
Integer ageBegin = 10;
Integer ageEnd = 20;
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
if(StringUtils.isNotBlank(name)){
//User::getName可以获得user类的name属性在数据库user表中对应的字段名称(即前面写的@TableField)
queryWrapper.like(User::getName,name);
}
//简化开发
queryWrapper.ge(ageBegin != null,User::getAge,ageBegin);
if(ageEnd != null){
queryWrapper.le(User::getAge,ageEnd);
}
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
}
区别:resource是按优先名称注入,autowired是优先按类型注入。前者不是spring框架里的,后者是spring框架里的。
使用:在注入时,利用autowired注入会报红色,因为autowired是根据类型注入,而resource是根据名称注入,故用resource不会报红
可以在Resources中创建mapper包下的xml文件,默认扫描mapper包下的xml文件为sql。类似于mybatis中的Resource。(默认配置)
可以在Resources中创建对应的mapper接口的全类名的包,在mapperScan的时候就会扫描到并且绑定mapper接口和mapper.xml文件。类似于mybatis中的Package。(mapperscan)
<sql id="Base_Column_List">
id, name, age, email
sql>
<include refid="Base_Column_List"/>
不需要注入mapper,因为serviceImpl继承的ServiceImpl
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper,User> implements UserService {
@Resource
UserMapper userMapper;
@Override
public List<User> listAllUserByName(String name) {
//等价于return userMapper.selectAllByName(name);
return baseMapper.selectAllByName(name);
}
}
插入时(不显式声明uid的值),会报错,即uid不会有值(不会用默认的雪花算法),mybatis-plus只会对字段名为id使用雪花算法然后带入默认值
解决:在uid字段上写@TabledId 就指明该uid为具体主键。
注意使用时@TabledId可以显式指明为自增策略,但是如果数据库不指明自增,则会报错。(数据库和业务都没有指明id,id是主键不为空,报错)
如果所有的字段的id都是自增,可以设置
#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto