优化 test

This commit is contained in:
yulichang 2023-01-10 15:27:14 +08:00
parent fedd137dc2
commit 83585c075f
8 changed files with 352 additions and 30 deletions

View File

@ -45,11 +45,11 @@
<properties>
<springboot.version>2.5.4</springboot.version>
<jdkVersion>1.8</jdkVersion>
<jdkVersion.test>1.8</jdkVersion.test>
<jdkVersion>17</jdkVersion>
<jdkVersion.test>17</jdkVersion.test>
<maven.deploy.skip>true</maven.deploy.skip>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<github.global.server>github</github.global.server>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

View File

@ -12,8 +12,8 @@
<artifactId>test-join</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

View File

@ -1,11 +1,23 @@
package com.github.yulichang.test.join.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.github.yulichang.test.join.util.ThreadLocalUtils;
import org.apache.ibatis.builder.SqlSourceBuilder;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.sql.SQLException;
import java.util.Objects;
/**
* mybatis-plus配置
*/
@ -16,11 +28,49 @@ public class MybatisPlusConfig {
* 分页插件
*/
@Bean
public MybatisPlusInterceptor paginationInterceptor() {
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor page = new PaginationInnerInterceptor(DbType.H2);
page.setOptimizeJoin(false);
interceptor.addInnerInterceptor(page);
interceptor.addInnerInterceptor(new SqlInterceptor());
return interceptor;
}
/**
* 校验sql
*/
public static class SqlInterceptor implements InnerInterceptor {
@Override
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
String sql = boundSql.getSql();
String s = ThreadLocalUtils.get();
if (StringUtils.isNotBlank(s) && !Objects.equals(formatSql(sql), formatSql(s))) {
System.err.println("执行sql: " + SqlSourceBuilder.removeExtraWhitespaces(sql));
System.err.println("预期sql: " + SqlSourceBuilder.removeExtraWhitespaces(s));
throw new RuntimeException("sql error");
}
InnerInterceptor.super.beforeQuery(executor, ms, parameter, rowBounds, resultHandler, boundSql);
}
private String formatSql(String sql) {
if (StringUtils.isBlank(sql)) {
return sql;
}
sql = sql.replaceAll("\n", "");
sql = sql.replaceAll("\r", "");
sql = sql.replaceAll("\t", "");
sql = sql.replaceAll("\s", "");
return dg(sql);
}
private String dg(String str) {
if (str.contains(" ")) {
str = str.replaceAll(" ", "");
return dg(str);
}
return str;
}
}
}

View File

@ -14,6 +14,9 @@ public class UserDto {
private Integer userId;
@TableField(exist = false)
private String userName;
private Integer createBy;
@TableField(exist = false)

View File

@ -0,0 +1,22 @@
package com.github.yulichang.test.join.util;
public class ThreadLocalUtils {
private final static ThreadLocal<String> userThreadLocal = new ThreadLocal<>();
/**
* 设置数据到当前线程
*/
public static void set(String sql) {
userThreadLocal.set(sql);
}
/**
* 获取线程中的数据
*/
public static String get() {
String s = userThreadLocal.get();
set(null);
return s;
}
}

View File

@ -79,3 +79,13 @@ INSERT INTO address (id, user_id, area_id, tel, address, del) VALUES (20,20, 100
INSERT INTO address (id, user_id, area_id, tel, address, del) VALUES (21,21, 10021, '10000000021', '朝阳21', false);
INSERT INTO address (id, user_id, area_id, tel, address, del) VALUES (22,22, 10022, '10000000022', '朝阳22', false);
DELETE FROM user_dto;
INSERT INTO user_dto (id, user_id, create_by, update_by, del) VALUES
(1,1, 2, 3, false),
(2,1, 2, 3, false),
(3,1, 2, 3, false),
(4,1, 2, 3, false),
(5,1, 2, 3, false),
(6,1, 2, 3, false),
(7,1, 2, 3, false),
(8,1, 2, 3, false);

View File

@ -54,6 +54,5 @@ create table user_dto
user_id int not null,
create_by int not null,
update_by int not null,
version int not null,
del bit null
);

View File

@ -2,6 +2,7 @@ package com.github.yulichang.test.join;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.test.join.dto.AddressDTO;
import com.github.yulichang.test.join.dto.UserDTO;
@ -11,6 +12,7 @@ import com.github.yulichang.test.join.entity.UserDO;
import com.github.yulichang.test.join.entity.UserDto;
import com.github.yulichang.test.join.mapper.UserDTOMapper;
import com.github.yulichang.test.join.mapper.UserMapper;
import com.github.yulichang.test.join.util.ThreadLocalUtils;
import com.github.yulichang.toolkit.MPJWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.junit.jupiter.api.Test;
@ -40,12 +42,22 @@ class LambdaWrapperTest {
@Test
void testJoin() {
ThreadLocalUtils.set("""
SELECT t.id,t.pid,t.`name`,t.`json`,t.sex,t.head_img,t.create_time,t.address_id,t.address_id2,t.del,t.create_by,t.update_by,
t1.id AS joina_id,t1.user_id,t1.area_id,t1.tel,t1.address,t1.del AS joina_del,t2.id AS joinb_id,t2.province,t2.city,t2.area,t2.postcode,t2.del AS joinb_del
FROM `user` t LEFT JOIN address t1 ON (t1.user_id = t.id)
LEFT JOIN area t2 ON (t2.id = t1.area_id)
WHERE t.del=false AND t1.del=false AND t2.del=false AND (t.id <= ?)
ORDER BY t.id DESC
""");
MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
.selectAll(UserDO.class)
.selectCollection(AddressDO.class, UserDTO::getAddressList, addr -> addr
.association(AreaDO.class, AddressDTO::getArea))
.leftJoin(AddressDO.class, AddressDO::getUserId, UserDO::getId)
.leftJoin(AreaDO.class, AreaDO::getId, AddressDO::getAreaId)
.le(UserDO::getId, 10000)
.orderByDesc(UserDO::getId);
List<UserDTO> list = userMapper.selectJoinList(UserDTO.class, wrapper);
@ -56,6 +68,16 @@ class LambdaWrapperTest {
@Test
void testJoin1() {
ThreadLocalUtils.set("""
SELECT t.id,t.pid,t.`name`,t.`json`,t.sex,t.head_img,t.create_time,t.address_id,t.address_id2,t.del,t.create_by,t.update_by,
t1.id AS joina_id,t1.user_id,t1.area_id,t1.tel,t1.address,t1.del AS joina_del,
t2.id AS joinb_id,t2.province,t2.city,t2.area,t2.postcode,t2.del AS joinb_del
FROM `user` t
LEFT JOIN address t1 ON (t1.user_id = t.id)
LEFT JOIN area t2 ON (t2.id = t1.area_id)
WHERE t.del=false AND t1.del=false AND t2.del=false
ORDER BY t.id DESC
""");
MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
.selectAll(UserDO.class)
.selectCollection(AddressDO.class, UserDTO::getAddressList, addr -> addr
@ -74,6 +96,15 @@ class LambdaWrapperTest {
*/
@Test
void testWrapper() {
ThreadLocalUtils.set("""
SELECT t.id
FROM `user` t
LEFT JOIN address t1 ON (t1.user_id = t.id)
LEFT JOIN area t2 ON (t2.id = t1.area_id)
WHERE t.del = false
AND t1.del = false
AND t2.del = false
""");
//基本数据类型 String
MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
.select(UserDO::getId)
@ -84,6 +115,16 @@ class LambdaWrapperTest {
assert list.get(0) != null;
System.out.println(list);
ThreadLocalUtils.set("""
SELECT t.create_time
FROM `user` t
LEFT JOIN address t1 ON (t1.user_id = t.id)
LEFT JOIN area t2 ON (t2.id = t1.area_id)
WHERE t.del = false
AND t1.del = false
AND t2.del = false
""");
//java.sql包下的类
MPJLambdaWrapper<UserDO> wrapper1 = new MPJLambdaWrapper<UserDO>()
.select(UserDO::getCreateTime)
@ -99,38 +140,97 @@ class LambdaWrapperTest {
@Test
@SuppressWarnings("unchecked")
void testMSCache() {
// PageHelper.startPage(1, 10);
ThreadLocalUtils.set("""
SELECT t.id,
t.pid,
t.`name`,
t.`json`,
t.sex,
t.head_img,
t.create_time,
t.address_id,
t.address_id2,
t.del,
t.create_by,
t.update_by
FROM `user` t
WHERE t.id = ?
AND t.del = false
AND (t.id <= ?)
ORDER BY t.id ASC, t.name ASC
""");
MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
.selectAll(UserDO.class)
.setEntity(new UserDO() {{
setId(1);
}})
// .eq(UserDO::getId,1)
.le(UserDO::getId, 100)
.orderByAsc(UserDO::getId, UserDO::getName);
System.out.println(wrapper.getSqlSegment());
System.out.println(wrapper.nonEmptyOfNormal());
System.out.println(wrapper.isEmptyOfNormal());
System.out.println("-----------------");
System.out.println(wrapper.nonEmptyOfWhere());
System.out.println(wrapper.isEmptyOfWhere());
List<UserDO> list = userMapper.selectList(wrapper);
// list.forEach(System.out::println);
list.forEach(System.out::println);
}
@Test
void testMSCachee() {
void testTableAliasR() {
ThreadLocalUtils.set("""
SELECT tt.id,
tt.user_id,
tt.create_by,
tt.update_by,
ua.`name` AS userName,
ub.`name` AS createName,
uc.`name` AS updateName
FROM user_dto tt
LEFT JOIN `user` ua ON (ua.id = tt.user_id)
LEFT JOIN `user` ub ON (ub.id = tt.create_by)
LEFT JOIN `user` uc ON (uc.id = tt.update_by)
WHERE ua.del = false
AND ub.del = false
AND uc.del = false
AND (ua.id <= ? AND ub.id >= ?)
""");
MPJLambdaWrapper<UserDto> wrapper = new MPJLambdaWrapper<UserDto>("tt")
.selectAll(UserDto.class)
.leftJoin(UserDO.class, "ua", UserDO::getId, UserDto::getUserId, ext -> ext
.select(UserDO::getId))
.selectAs(UserDO::getName, UserDto::getUserName)
.le(UserDO::getId, 100))
.leftJoin(UserDO.class, "ub", UserDO::getId, UserDto::getCreateBy, ext -> ext
.select(UserDO::getImg))
.leftJoin(UserDO.class, "uc", UserDO::getId, UserDto::getUpdateBy);
userDTOMapper.selectJoinList(UserDto.class, wrapper);
System.out.println(1);
.selectAs(UserDO::getName, UserDto::getCreateName)
.ge(UserDO::getId, 0))
.leftJoin(UserDO.class, "uc", UserDO::getId, UserDto::getUpdateBy, ext -> ext
.selectAs(UserDO::getName, UserDto::getUpdateName));
List<UserDto> userDtos = userDTOMapper.selectJoinList(UserDto.class, wrapper);
assert StringUtils.isNotBlank(userDtos.get(0).getUserName());
assert StringUtils.isNotBlank(userDtos.get(0).getCreateName());
assert StringUtils.isNotBlank(userDtos.get(0).getUpdateName());
ThreadLocalUtils.set("""
SELECT tt.id,
tt.pid,
tt.`name`,
tt.`json`,
tt.sex,
tt.head_img,
tt.create_time,
tt.address_id,
tt.address_id2,
tt.del,
tt.create_by,
tt.update_by,
ua.id,
ub.head_img
FROM `user` tt
LEFT JOIN `user` ua ON (ua.id = tt.pid)
LEFT JOIN `user` ub ON (ub.id = tt.create_by)
LEFT JOIN `user` uc ON (uc.id = tt.update_by)
WHERE tt.del = false
AND ua.del = false
AND ub.del = false
AND uc.del = false
AND (ua.head_img = tt.name AND tt.id = ua.id)
""");
MPJLambdaWrapper<UserDO> w = new MPJLambdaWrapper<UserDO>("tt")
.selectAll(UserDO.class)
.leftJoin(UserDO.class, "ua", UserDO::getId, UserDO::getPid, ext -> ext
@ -149,17 +249,66 @@ class LambdaWrapperTest {
*/
@Test
void testInner() {
ThreadLocalUtils.set("""
SELECT t.id,
t.pid,
t.`name`,
t.`json`,
t.sex,
t.head_img,
t.create_time,
t.address_id,
t.address_id2,
t.del,
t.create_by,
t.update_by,
t1.id AS joina_id,
t1.pid AS joina_pid,
t1.`name` AS joina_name,
t1.`json` AS joina_json,
t1.sex AS joina_sex,
t1.head_img AS joina_head_img,
t1.create_time AS joina_create_time,
t1.address_id AS joina_address_id,
t1.address_id2 AS joina_address_id2,
t1.del AS joina_del,
t1.create_by AS joina_create_by,
t1.update_by AS joina_update_by
FROM `user` t
LEFT JOIN `user` t1 ON (t1.pid = t.id)
WHERE t.del = false
AND (t.id > ?)
""");
//自连接
MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
.disableSubLogicDel()//关闭副表逻辑删除
// .disableLogicDel()//关闭主表逻辑删除
.selectAll(UserDO.class)
.selectCollection(UserDO.class, UserDO::getChildren)
.leftJoin(UserDO.class, UserDO::getPid, UserDO::getId);
.leftJoin(UserDO.class, UserDO::getPid, UserDO::getId)
.gt(UserDO::getId, 0);
List<UserDO> list = userMapper.selectJoinList(UserDO.class, wrapper);
// assert list.size() == 2 && list.get(0).getChildren().size() == 9;
System.out.println(list);
ThreadLocalUtils.set("""
SELECT t.id,
t.pid,
t.`name`,
t.`json`,
t.sex,
t.head_img,
t.create_time,
t.address_id,
t.address_id2,
t.del,
t.create_by,
t.update_by,
t1.`name` AS createName,
t2.`name` AS updateName
FROM `user` t
LEFT JOIN `user` t1 ON (t1.id = t.create_by)
LEFT JOIN `user` t2 ON (t2.id = t.update_by)
WHERE (t2.id = t.update_by AND t.id = t1.id)
""");
//关联一张表多次
MPJLambdaWrapper<UserDO> w = new MPJLambdaWrapper<UserDO>()
.disableLogicDel()
@ -176,6 +325,51 @@ class LambdaWrapperTest {
List<UserDO> dos = userMapper.selectJoinList(UserDO.class, w);
assert dos.get(0).getCreateName() != null && dos.get(0).getUpdateName() != null;
ThreadLocalUtils.set("""
SELECT t.id,
t.pid,
t.`name`,
t.`json`,
t.sex,
t.head_img,
t.create_time,
t.address_id,
t.address_id2,
t.del,
t.create_by,
t.update_by,
t1.`name` AS alias,
t1.id AS joina_id,
t1.pid AS joina_pid,
t1.`name` AS joina_name,
t1.`json` AS joina_json,
t1.sex AS joina_sex,
t1.head_img AS joina_head_img,
t1.create_time AS joina_create_time,
t1.address_id AS joina_address_id,
t1.address_id2 AS joina_address_id2,
t1.del AS joina_del,
t1.create_by AS joina_create_by,
t1.update_by AS joina_update_by,
t2.id AS joinb_id,
t2.pid AS joinb_pid,
t2.`name` AS joinb_name,
t2.`json` AS joinb_json,
t2.sex AS joinb_sex,
t2.head_img AS joinb_head_img,
t2.create_time AS joinb_create_time,
t2.address_id AS joinb_address_id,
t2.address_id2 AS joinb_address_id2,
t2.del AS joinb_del,
t2.create_by AS joinb_create_by,
t2.update_by AS joinb_update_by
FROM `user` t
LEFT JOIN `user` t1 ON (t1.pid = t.id)
LEFT JOIN `user` t2 ON (t2.pid = t1.id)
WHERE t.del = false
AND (t1.id <= ? AND t.id <= ?)
""");
MPJLambdaWrapper<UserDO> wrapper1 = new MPJLambdaWrapper<UserDO>()
.disableSubLogicDel()
.selectAll(UserDO.class)
@ -187,9 +381,6 @@ class LambdaWrapperTest {
.le(UserDO::getId, 5))
.le(UserDO::getId, 4);
List<UserDO> list1 = userMapper.selectJoinList(UserDO.class, wrapper1);
System.out.println(wrapper1.getSqlSegment());
System.out.println(wrapper1.getSqlSelect());
assert "(t1.id <= #{ew.paramNameValuePairs.MPGENVAL1} AND t.id <= #{ew.paramNameValuePairs.MPGENVAL2})".equals(wrapper1.getSqlSegment());
System.out.println(list1);
}
@ -244,6 +435,30 @@ class LambdaWrapperTest {
@Test
void testTableAlias() {
ThreadLocalUtils.set("""
SELECT t.id,
t.pid,
t.`name`,
t.`json`,
t.sex,
t.head_img,
t.create_time,
t.address_id,
t.address_id2,
t.del,
t.create_by,
t.update_by,
aa.id,
aa.user_id,
aa.area_id,
aa.tel,
aa.address,
aa.del
FROM `user` t
LEFT JOIN address aa ON (aa.user_id = t.id)
WHERE t.del = false
AND aa.del = false
""");
MPJLambdaWrapper<UserDO> wrapper = new MPJLambdaWrapper<UserDO>()
// .disableLogicDel()//关闭主表逻辑删除
.selectAll(UserDO.class)
@ -266,6 +481,8 @@ class LambdaWrapperTest {
.leftJoin(AddressDO.class, AddressDO::getId, UserDO::getAddressId2);
List<UserDO> list = userMapper.selectJoinList(UserDO.class, wrapper);
assert list.get(0).getAddressList().get(0).getAddress()!= null;
assert list.get(0).getAddressList2().get(0).getAddress()!= null;
System.out.println(list);
}
@ -293,6 +510,27 @@ class LambdaWrapperTest {
*/
@Test
void test3() {
ThreadLocalUtils.set("""
SELECT t.id,
t.pid,
t.`name`,
t.`json`,
t.sex,
t.head_img,
t.create_time,
t.address_id,
t.address_id2,
t.del,
t.create_by,
t.update_by,
t1.address
FROM `user` t
LEFT JOIN address t1 ON (t.id = t1.user_id AND t.id = t1.user_id)
WHERE t.del = false
AND t1.del = false
AND (t.id = ? AND (t.head_img = ? OR t1.user_id = ?) AND t.id = ?)
LIMIT ?
""");
IPage<UserDTO> page = userMapper.selectJoinPage(new Page<>(1, 10), UserDTO.class,
MPJWrappers.<UserDO>lambdaJoin()
.selectAll(UserDO.class)