mybatis-plus的快速入门笔记

基础入门

      • 简单使用
        • 基本配置
        • ORM映射关系
        • target作用范围
        • 快速开始
        • mybatis-plus的字段映射关系
        • 配置日志
        • 缓存测试
        • curd
          • 插入
          • 主键生成策
          • 更新
          • 自动填充
          • 乐观锁
          • 查询操作
          • 分页查询
          • 删除操作
          • 逻辑删除
          • 性能分析插件
          • 多表 分页 模糊 自定义SQL

各种各样的sql需要写,什么分页啊,条件查询啊,真的太难了,之后发现有个mp,自动帮我们写sql,挺好用的,可能其他人喜欢jpa,可以都去了解一下。

官网https://mp.baomidou.com/

简单使用

基本配置

# 配置日志 默认控制台 
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 配置逻辑删除 
# 逻辑已删除值(默认为 1)
mybatis-plus.global-config.db-config.logic-delete-value=1 
# 逻辑未删除值(默认为 0)
mybatis-plus.global-config.db-config.logic-not-delete-value=0 
mybatis-plus.mapper-locations=classpath:mybatis/mapper/*Mapper.xml
#是否使用 驼峰 默认使用
# mybatis-plus.configuration.map-underscore-to-camel-case=false
# 取别名
mybatis-plus.type-aliases-package=com.myh.pojo

ORM映射关系

java类	 	          								mysql数据库
java.lang.Byte	           byte	                    TINYINT
java.lang.Short	           short					SMALLINT
java.lang.Integer	       integer				    INGEGER
java.lang.Long			   long						BIGINT
java.lang.Float			   float					FLOAT
java.lang.Double	       double				    DOUBLE
java.lang.BigDecimal	   big_decimal	            NUMERIC
java.lang.Boolean	       boolean	                BIT
java.lang.String	       string	                VARCHAR
java.lang.Boolean	       yes_no	                CHAR(1)('Y''N')
java.lang.Boolean	       true_false	            CHAR(1)(‘Y’或'N')
java.uitl.Date             date	    				DATE
java.sql.Date			   date	    				DATE
java.sql.Time			  time	                   TIME
java.sql.Timestamp		  timestamp	           	   TIMESTAMP
java.uitl.Calendar		  celendar	               TIMESTAMP
java.uitl.Calendar		  calendar	               TIMESTAMP
java.io.Serializable	  serializable	           VARBINARY/BLOB
java.sql.Clob	          clob	                   CLOB
java.sql.Blob			  blob	                   BLOB
java.lang.Class			  class	                   VARCHAR
java.uitl.Locale		  locale	               VARCHAR
java.uitl.TimeZone		  timezone	               VARCHAR
java.uitl.Currency		  currency	               VARCHAR

target作用范围

@Target(ElementType.TYPE)——接口、类、枚举、注解
@Target(ElementType.FIELD)——字段、枚举的常量
@Target(ElementType.METHOD)——方法
@Target(ElementType.PARAMETER)——方法参数
@Target(ElementType.CONSTRUCTOR) ——构造函数
@Target(ElementType.LOCAL_VARIABLE)——局部变量
@Target(ElementType.ANNOTATION_TYPE)——注解
@Target(ElementType.PACKAGE)——包

@Retention:注解的保留位置

RetentionPolicy.SOURCE:这种类型的Annotations
只在源代码级别保留,编译时就会被忽略,class字节码文件中不包含。
RetentionPolicy.CLASS:这种类型的Annotations编译时被保留,默认的保留策略,class文件中存在,但JVM将会忽略,运行时无法获得。

RetentionPolicy.RUNTIME:这种类型的Annotations将被JVM保留,
所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用。

@Document:说明该注解将被包含在javadoc中
@Inherited:说明子类可以继承父类中的该注解

快速开始

创建springboot的链接 eclipse有时候超时 可以用下面这个
https://start.aliyun.com/

1.创建数据库

create database mybats_plus charactor set utf8

2.创建user表

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 乐观锁
//delete 逻辑删除
//gmt_create
//gmt_modified
DELETE FROM user;

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.springframework.bootgroupId>
		<artifactId>spring-boot-starter-webartifactId>
	dependency>

	
	<dependency>
		<groupId>mysqlgroupId>
		<artifactId>mysql-connector-javaartifactId>
	dependency>
	
	
	<dependency>
		<groupId>com.baomidougroupId>
		<artifactId>mybatis-plus-boot-starterartifactId>
		<version>3.0.5version>
	dependency>

	<dependency>
		<groupId>org.springframework.bootgroupId>
		<artifactId>spring-boot-devtoolsartifactId>
		<scope>runtimescope>
		<optional>trueoptional>
	dependency>
	<dependency>
		<groupId>org.projectlombokgroupId>
		<artifactId>lombokartifactId>
		<optional>trueoptional>
	dependency>

mybatis和mybatisplus不要同时导入 会有依赖版本问题 导入mybatisplus就行了
配置文件

58有区别  8需要时区 5驱动不同
server.port=8080
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?
	serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=utf8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

传统方式pojo -dao(连接mybatispuls ,配置mapper.xml文件) -service -controller
现在方式:pojo mapper 使用

@Repository
@Mapper //在启动类中取扫描
public interface UserMapper extends BaseMapper<User> {
	//所有的crud操作都已经完成编写了
	//你不需要像以前配置一大堆文件了
}

Test

@SpringBootTest
class Mybatisplus01QuickstartApplicationTests {	
	@Autowired
	private UserMapper userMapper;	
	@Test
	void contextLoads() {
		//参数是一个wapper 条件构造器 
		//查询全部用户
		List<User> list= userMapper.selectList(null);
		list.forEach(System.out::println);
	}
}

mybatis-plus的字段映射关系

在mybatis-plus中,默认开启驼峰命名

@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "user")
public class User {
	//对应数据库的主件 uuid 自增id 雪花算法 redis zookeeper
	//默认  全局唯一id  ID_WORKER
	//自增AUTO 数据库也有变成自增
	@TableId(type = IdType.AUTO)
    private Long id;
//  private String name;
    private String userName;
    private Integer age;
    private String email;
    
    @TableField(fill = FieldFill.INSERT)
    private Date gmtCreate;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date gmt_modified;
}
//  如果你的字段类型为userName,那么在数据库查询的时候映射的时候
//  默认映射为user_name 如果此时你的数据库字段为userName就会报错
//  也就是他自动将userName转化为 user_name 
//  所以此时你的数据库字段应该为 user_name
//  也就是只在俩种情况会映射成功
//1.字段名和数据库一样 映射成功
//2.驼峰命名规则也会成功

关闭驼峰命名

mybatis-plus:
  configuration:
    map-underscore-to-camel-case: false
# 是否开启自动驼峰命名规则(camel case)映射,
即从经典数据库列名 A_COLUMN(下划线命名) 
到经典 Java 属性名 aColumn(驼峰命名) 的类似映射

spring中


<bean id="globalConfig" class="com.baomidou.mybatisplus.entity.GlobalConfiguration">
    
    <property name="idType" value="0"/>
    
    <property name="dbColumnUnderline" value="flase"/>
bean>

配置日志

# 配置日志 默认控制台
mybatis-plus.configuration.log-impl=
	org.apache.ibatis.logging.stdout.StdOutImpl

缓存测试

List<User> list= userMapper.selectList(null);
List<User> list1= userMapper.selectList(null);
//没有缓存
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@655a01d8] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@935599808 wrapping com.mysql.cj.jdbc.ConnectionImpl@35a0e495] will not be managed by Spring
==>  Preparing: SELECT id,name,age,email FROM user 
==> Parameters: 
<==    Columns: id, name, age, email
<==        Row: 1, Jone, 18, [email protected]
<==        Row: 2, Jack, 20, [email protected]
<==        Row: 3, Tom, 28, [email protected]
<==        Row: 4, Sandy, 21, [email protected]
<==        Row: 5, Billie, 24, [email protected]
<==      Total: 5
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@655a01d8]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@770beef5] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@1842476600 wrapping com.mysql.cj.jdbc.ConnectionImpl@35a0e495] will not be managed by Spring
==>  Preparing: SELECT id,name,age,email FROM user 
==> Parameters: 
<==    Columns: id, name, age, email
<==        Row: 1, Jone, 18, [email protected]
<==        Row: 2, Jack, 20, [email protected]
<==        Row: 3, Tom, 28, [email protected]
<==        Row: 4, Sandy, 21, [email protected]
<==        Row: 5, Billie, 24, [email protected]
<==      Total: 5
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@770beef5]
User(id=1, name=Jone, age=18, [email protected])
User(id=2, name=Jack, age=20, [email protected])
User(id=3, name=Tom, age=28, [email protected])
User(id=4, name=Sandy, age=21, [email protected])
User(id=5, name=Billie, age=24, [email protected])

开启二级缓存后,MP的baseMapper中提供的一系列Select方法不能命中二级缓存,只有自定义的方法才能命中二级缓存。
官方:我们建议缓存放到 service 层,你可以自定义自己的 BaseServiceImpl 重写注解父类方法,继承自己的实现。

curd

插入
@Test
void contextLoads1() {
	//查询全部用户
	User user=new User(); //自动生成id
	user.setAge(3);
	user.setEmail("[email protected]");
	user.setName("A");
	userMapper.insert(user); //返回会影响的行数  id会自动回填 默认学号算法
}
//Creating a new SqlSession
//SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@c269425] was not registered for //synchronization because synchronization is not active
//JDBC Connection [HikariProxyConnection@1818236857 wrapping com.mysql.cj.jdbc.ConnectionImpl@4730e0f0] will not be managed by Spring
//==>  Preparing: INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? ) 
//==> Parameters: 1264024876485070849(Long), A(String), 3(Integer), [email protected](String)
//<==    Updates: 1
//Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@c269425]

主键生成策略
@TableId(type = IdType.AUTO)

public enum IdType {
    /**
     * 数据库ID自增
     */
    AUTO(0),
    /**
     * 该类型为未设置主键类型
     */
    NONE(1),
    /**
     * 用户输入ID
     * 该类型可以通过自己注册自动填充插件进行填充
     */
    INPUT(2),

    /* 以下3种类型、只有当插入对象ID 为空,才自动填充。 */
    /**
     * 全局唯一ID (idWorker)
     */
    ID_WORKER(3),
    /**
     * 全局唯一ID (UUID)
     */
    UUID(4),
    /**
     * 字符串全局唯一ID (idWorker 的字符串表示)
     */
    ID_WORKER_STR(5);
    private int key;
    IdType(int key) {
        this.key = key;
    }
}
主键生成策

默认 ID_WORKER 全局唯一id

分布式系统唯一id生成:https://www.cnblogs.com/haoxinyue/p/5208136.html

雪花算法

snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使
用41bit作为 毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作
为毫秒内的流水号(意味 着每个节点在每毫秒可以产生 4096 个 ID),后还有一个符号位,
永远是0。可以保证几乎全球唯 一!

主键自增
1、实体类字段上 @TableId(type = IdType.AUTO)
2、数据库字段一定要是自增!不然报错!
3、再次测试插入即可!

更新
	@Test
	void contextLoads2() {
		//参数是一个wapper 条件构造器 
		//查询全部用户
		User user=new User();
		user.setId(1L);
		user.setAge(30);
		user.setEmail("[email protected]");
		user.setName("3");
		userMapper.updateById(user);
	}
// 在插入时 如果对象的字段的属性为null 那么在插入时不会出现在插入语句中
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6614bd4b] was not registered for synchronization because synchronization is not active
JDBC Connection [HikariProxyConnection@282812721 wrapping com.mysql.cj.jdbc.ConnectionImpl@6c6017b9] will not be managed by Spring
==>  Preparing: UPDATE user SET name=?, age=?, email=? WHERE id=? 
==> Parameters: 3(String), 30(Integer), 3@qq.com(String), 1(Long)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6614bd4b]
自动填充

创建时间 修改时间 !这些操作一遍都是自动化完成的,不希望手动更新

阿里巴巴开发手册:所有的数据库表:gmt_create gmt_modified几乎所有的表都要配置上,查看数据修改时间

新字段
gmt_create
gmt_modified
//CURRENT_TIMESTAMP 默认值 当前时间

@TableField(fill = FieldFill.UPDATE)
private Data gmtCreate;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Data gmtModified;
public enum FieldFill {
    /**
     * 默认不处理
     */
    DEFAULT,
    /**
     * 插入填充字段
     */
    INSERT,
    /**
     * 更新填充字段
     */
    UPDATE,
    /**
     * 插入和更新填充字段
     */
    INSERT_UPDATE
}

编写处理器

@Component //要把处理器加入到ioc容器中
public class Myhander implements MetaObjectHandler{
	@Override
	public void insertFill(MetaObject metaObject) {
		log.info("start insert insertFill");
		this.setFieldValByName("gmtCreate", new Date(), metaObject);
		this.setFieldValByName("gmtModified", new Date(), metaObject);
	}

	@Override
	public void updateFill(MetaObject metaObject) {
		// TODO Auto-generated method stub
		log.info("start insert updateFill");
		this.setFieldValByName("gmtModified", new Date(), metaObject);
	}
}
乐观锁

乐观锁 : 故名思意十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题, 再次更新值测试
悲观锁:故名思意十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!

我们这里主要讲解 乐观锁机制!
乐观锁实现方式:

  • 取出记录时,获取当前 version
  • 更新时,带上这个version
  • 执行更新时, set version = newVersion where version = oldVersion
  • 如果version不对,就更新失
乐观锁:1、先查询,获得版本号 version = 1 

-- A update user set name = "kuangshen", version = version + 1 
where id = 2 and version = 1

-- B 线程抢先完成,这个时候 version = 2,会导致 A 修改失败! 
update user set name = "kuangshen", version = version + 1 
where id = 2 and version = 1

1、给数据库中增加version字段!
2、我们实体类加对应的字段

//乐观锁
@Version //乐观锁Version注解 
private Integer version;

3、注册组件

//扫描我们的 mapper 文件夹 
@MapperScan("com.myh.mapper")
@EnableTransactionManagement 
//Spring Boot 使用事务非常简单,首先使用注解 @EnableTransactionManagement
// 开启事务支持后,然后在访问数据库的Service方法上添加注解 @Transactional 便可
@Configuration // 配置
public class MyMybatisPlusConfig {

	// 注册乐观锁插件    
	@Bean
	public OptimisticLockerInterceptor optimisticLockerInterceptor() {
		return new OptimisticLockerInterceptor();
	}
}

4、测试一下!

//更新一个用户  测试乐观锁
@Test
void contextLoads3() {
    //参数是一个wapper 条件构造器 
    //查询全部用户
    User user = userMapper.selectById(1L);
    user.setName("1L");
    userMapper.updateById(user);
}
==>  Preparing: UPDATE user SET name=?, age=?, email=?, gmt_create=?, gmt_modified=?, version=? WHERE id=? AND version=? 
==> Parameters: 1L(String), 301(Integer), 3@qq.com(String), 2020-05-23 19:12:05.0(Timestamp), 2020-06-12 09:53:10.931(Timestamp), 2(Integer), 1(Long), 1(Integer)
<==    Updates: 1

失败的

//更新一个用户  测试乐观锁  失败
@Test
void contextLoads4() {
    // 线程 1 
    User user = userMapper.selectById(1L);
    user.setName("1L");
    // 模拟另外一个线程执行了插队操作 
    User user2 = userMapper.selectById(1L);
    user2.setName("2L");
    userMapper.updateById(user2);
    userMapper.updateById(user);
}
==>  Preparing: UPDATE user SET name=?, age=?, email=?, gmt_create=?, gmt_modified=?, version=? WHERE id=? AND version=? 
==> Parameters: 111(String), 301(Integer), 3@qq.com(String), 2020-05-23 19:12:05.0(Timestamp), 2020-06-12 09:56:11.94(Timestamp), 3(Integer), 1(Long), 2(Integer)
<==    Updates: 1

==>  Preparing: UPDATE user SET name=?, age=?, email=?, gmt_create=?, gmt_modified=?, version=? WHERE id=? AND version=? 
==> Parameters: 2L(String), 301(Integer), 3@qq.com(String), 2020-05-23 19:12:05.0(Timestamp), 2020-06-12 09:56:12.032(Timestamp), 3(Integer), 1(Long), 2(Integer)
<==    Updates: 0
查询操作
//查询操作
// 测试查询  查询一个
@Test  
public void testSelectById(){ 
    User user = userMapper.selectById(1L);
    System.out.println(user); 
//==>  Preparing: SELECT id,name,age,email,gmt_create,gmt_modified,version FROM user WHERE id=? 
//==> Parameters: 1(Long)
//<==    Columns: id, name, age, email, gmt_create, gmt_modified, version
//<==        Row: 1, 2L1, 301, [email protected], 2020-05-23 11:12:05, 2020-06-12 02:07:07, 6
//<==      Total: 1
}

//批量查询
@Test  
public void testSelectByBatchId(){ 
    List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3)); 
    users.forEach(System.out::println);
//==> Parameters: 1(Integer), 2(Integer), 3(Integer)
//<==    Columns: id, name, age, email, gmt_create, gmt_modified, version
//<==        Row: 1, 2L1, 301, [email protected], 2020-05-23 11:12:05, 2020-06-12 02:07:07, 6
//<==        Row: 2, 3, 301, [email protected], 2020-05-23 11:12:05, 2020-06-12 01:38:36, 1
//<==        Row: 3, Tom, 28, [email protected], 2020-05-23 11:12:05, 2020-05-23 11:12:38, 1
//<==      Total: 3
}

// 按条件查询之一使用map操作
@Test
public void testSelectByBatchIds() {
    HashMap<String, Object> map = new HashMap<>();// 自定义要查询  
    map.put("name", "Billie");
    map.put("age", 24);
    userMapper.selectByMap(map);
//==>  Preparing: SELECT id,name,age,email,gmt_create,gmt_modified,version FROM user WHERE name = ? AND age = ? 
//==> Parameters: Billie(String), 24(Integer)
//<==    Columns: id, name, age, email, gmt_create, gmt_modified, version
//<==        Row: 5, Billie, 24, [email protected], 2020-05-23 11:12:05, 2020-05-23 11:12:38, 1
//<==      Total: 1
}
分页查询

1、原始的 limit 进行分页

2、pageHelper 第三方插件

3、MP 其实也内置了分页插件!

如何使用?

1、配置拦截器组件即可

// 分页插件 
@Bean 
public PaginationInterceptor paginationInterceptor() {    
    return  new PaginationInterceptor(); 
}
// 测试分页查询
// 1.注册插件
// 2.new Page
// 3.开始查询

// 按条件查询之一使用map操作
// 测试分页查询
@Test 
public void testPage(){
    //  参数一:当前页    
    //  参数二:页面大小    
    //  使用了分页插件之后,所有的分页操作也变得简单的!    
    Page<User> page = new Page<>(2,5);
    IPage<User> selectPage = userMapper.selectPage(page,null);
    System.out.println(selectPage.getCurrent());  
    System.out.println(selectPage.getPages());
    System.out.println(selectPage.getSize());
    System.out.println(selectPage.getTotal());
    page.getRecords().forEach(System.out::println);
    //	 	System.out.println(page.getTotal()); 
}
==>  Preparing: SELECT COUNT(1) FROM user 
==> Parameters: 
<==    Columns: COUNT(1)
<==        Row: 9
==>  Preparing: SELECT id,name,age,email,gmt_create,gmt_modified,version FROM user LIMIT 5,5 
==> Parameters: 
<==    Columns: id, name, age, email, gmt_create, gmt_modified, version
<==        Row: 1264024876485070849, A, 3, 1@qq.com, 2020-05-23 11:12:05, 2020-05-23 11:12:38, 1
<==        Row: 1264024876485070850, A, 3, 1@qq.com, 2020-05-23 11:12:05, 2020-05-23 11:12:38, 1
<==        Row: 1264024876485070851, 3, 30, 3@qq.com, 2020-06-10 09:02:20, 2020-05-23 03:33:16, 1
<==        Row: 1264024876485070852, 3, 301, 3@qq.com, 2020-05-23 03:33:34, 2020-06-12 01:30:40, 1
<==      Total: 4
删除操作

1、根据 id 删除记录

// 测试删除 
	@Test 
	public void testDeleteById(){
		
		int deleteById = userMapper.deleteById(1240620674645544965L);
		System.out.println(deleteById);
//==>  Preparing: DELETE FROM user WHERE id=? 
//==> Parameters: 1240620674645544965(Long)
//<==    Updates: 0	
	}
	
	// 通过id批量删除 
	@Test 
	public void testDeleteBatchId(){
		int deleteBatchIds = userMapper.deleteBatchIds(Arrays.asList(1264024876485070852L,1240620674645544962L)); 
		System.out.println(deleteBatchIds);
//==>  Preparing: DELETE FROM user WHERE id IN ( ? , ? ) 
//==> Parameters: 1264024876485070852(Long), 1240620674645544962(Long)
//<==    Updates: 1
	}
	// 通过map删除  动态sql
	@Test 
	public void testDeleteMap() {
		HashMap<String, Object> map = new HashMap<>(); 
		map.put("name","1");
		map.put("age","1");
		userMapper.deleteByMap(map);
	}
//==>  Preparing: DELETE FROM user WHERE name = ? AND age = ? 
//==> Parameters: 1(String), 1(String)
//<==    Updates: 0
逻辑删除

物理删除 :从数据库中直接移除
逻辑删除 :再数据库中没有被移除,而是通过一个变量来让他失效! deleted = 0 => deleted = 1

1、在数据表中增加一个 deleted 字段
2、实体类中增加属性

@TableLogic //逻辑删除 
private Integer deleted;

3、配置插件!

# 配置逻辑删除 
# 逻辑已删除值(默认为 1)
mybatis-plus.global-config.db-config.logic-delete-value=1 
# 逻辑未删除值(默认为 0)
mybatis-plus.global-config.db-config.logic-not-delete-value=0 

4.注册插件

// 逻辑删除组件!
@Bean
public ISqlInjector sqlInjector() {
    return new LogicSqlInjector();
}

附件说明:

  • 逻辑删除是为了方便数据恢复和保护数据本身价值等等的一种方案,但实际就是删除。
  • 如果你需要再查出来就不应使用逻辑删除,而是以一个状态去表示。

如: 员工离职,账号被锁定等都应该是一个状态字段,此种场景不应使用逻辑删除。

  • 若确需查找删除数据,如老板需要查看历史所有数据的统计汇总信息,请单独手写sql。
性能分析插件

性能分析拦截器,用于输出每条 SQL 语句及其执行时间

该插件 3.2.0 以上版本移除推荐使用第三方扩展 执行SQL分析打印 功能

我们在平时的开发中,会遇到一些慢sql。测试! druid,

作用:性能分析拦截器,用于输出每条 SQL 语句及其执行时间

MP也提供性能分析插件,如果超过这个时间就停止运行!

/**     * SQL执行效率插件     */ 
// 设置 dev test 环境开启,保证我们的效率 
@Bean 
@Profile({"dev","test"})
public PerformanceInterceptor performanceInterceptor() { 
    PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
    // ms设置sql执行的最大时间,如果超过了则不 执行1000ms   
    performanceInterceptor.setMaxTime(10); 
    //		performanceInterceptor.setWriteInLog(true); //是否写入日志
    // 是否格式化代码    
    performanceInterceptor.setFormat(true);  
    return performanceInterceptor; 
}

记住,要在SpringBoot中配置环境为dev或者 test 环境!

spring.profiles.active=dev

2、测试使用!

//查询操作
// 测试查询  查询一个
@Test  
	public void testSelectById(){ 
		Book selectById = bookMapper.selectById(1);
		System.out.println(selectById);
	}
//Time:66 ms - ID:com.myh.mapper.BookMapper.selectById
多表 分页 模糊 自定义SQL

自定义sql
1.注解
2.和mybatis一样的配置文件
3.可以将mybatis-plsu 看成mybatis
原因是只在mybatis上面只做增强 不做修改
但是多表还是要自己写sql,虽然自己写 但是模糊和分页已经做好了

test 多表分页条件查询

User实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "user")
public class User {
	//对应数据库的主件 uuid 自增id 雪花算法 redis zookeeper
	//默认  全局唯一id  ID_WORKER
	//自增AUTO 数据库也有变成自增
	@TableId(type = IdType.AUTO)
    private Long id;
	@TableField(value = "name")
    private String name;
    private Integer age;
    private String email;
    
    @TableField(fill = FieldFill.INSERT)
    private Date gmtCreate;
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Date gmt_modified;
    
    private Book book;
    //乐观锁
    //乐观锁Version注解  需要注册插件
    @Version 
    private Integer version;
    
    @TableLogic //逻辑删除 
    private Integer deleted;
    
    @TableField(el ="order",exist = false)
    private Order order;
    
    @TableField(el ="book",exist = false)
    private List<Book> bookList;
}

Book实体类

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName(value = "book")
public class Book {
	@TableId(value = "id")
    private Long id;
	@TableField(value = "name")
    private String name;
	@TableField(value = "u_id")
    private Long uid;
}

user接口

@Repository
@Mapper
public interface UserMapper extends BaseMapper<User> {
	//所有的crud操作都已经完成编写了
	//你不需要像以前配置一大堆文件了
//	@Select("select * from `user` u,book b where u.id=b.u_id ")
//	public User getUserOne();
	
	public Page<User> findAllAndPage(IPage<User> page,@Param(Constants.WRAPPER) Wrapper<User> queryWrapper);
}	

usermapper的xml

	<resultMap type="com.myh.pojo.User" id="userAll">
		<result column="uid" property="id"/>
		<association property="book" javaType="com.myh.pojo.Book">
			<result column="bid" property="id"/>
		</association>
	</resultMap>
	
	<select id="findAllAndPage" resultMap="userAll">
		select u.id uid,b.id bid fROM user u INNER JOIN book b  on u.id=b.u_id ${ew.customSqlSegment}
	</select>

我这里简单 ,所有只显示了bid和uid,需要啥就映射啥

	//自定义SQL 分页
	@Test 
	public void findAllAndPage() {
		Page<User> page=new Page<User>(0, 5);
		QueryWrapper<User> qw=new QueryWrapper<User>();
		qw.eq("b.id", "1").eq("u.id", 1264024876485070850L);
		Page<User> findAllAndPage = userMapper.findAllAndPage(page,qw);

	} 
==> Parameters: 1(String), 1264024876485070850(Long)
<==    Columns: COUNT(1)
<==        Row: 1
==>  Preparing: select u.id uid,b.id bid fROM user u INNER JOIN book b on u.id=b.u_id WHERE b.id = ? AND u.id = ? LIMIT ?,? 
==> Parameters: 1(String), 1264024876485070850(Long), 0(Long), 5(Long)
<==    Columns: uid, bid
<==        Row: 12640
//为什么有俩条呢?因为分页返回的Ipage,里面有个count,如果不需要级在分页的时候第三个参数变为false就行了

ok到这里分页多和多表和添加查询就ok了。

总结

感想:mp解决的单表大部分操作,对于多表来说就不那么友好,但是,好在解决了其它的麻烦。

比如分页和条件查询,它都帮我们解决了 多表的话建议使用内连接配合条件查询。感兴趣的话也可以去了解jpa。

笔记来源:https://space.bilibili.com/95256449/

我自己也适当的改了一点点。

你可能感兴趣的:(ssm,java,数据库)