Skip to content

Commit

Permalink
修复动态节点处理错误.
Browse files Browse the repository at this point in the history
  • Loading branch information
nieqiurong committed Jan 13, 2025
1 parent bb2e18c commit ec394ea
Show file tree
Hide file tree
Showing 3 changed files with 380 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* <p>试验性功能,解决mybatis堆内存过大的问题(看后期mybatis官方会不会解决堆内存占用问题)</p>
Expand Down Expand Up @@ -126,17 +128,33 @@ private synchronized static String cacheStr(String str) {

private static final StaticTextSqlNode SPACE_SQL_NODE = new StaticTextSqlNode(StringPool.SPACE);

private static final Pattern PATTERN = Pattern.compile("^\\s+|\\s+$");

/**
* 将前后空白符替换成空格
*
* @param str 字符串 (非空)
* @return 处理后文本
* @since 3.5.10.1
*/
public static String replaceLeadingAndTrailingWhitespace(String str) {
Matcher matcher = PATTERN.matcher(str);
return matcher.replaceAll(StringPool.SPACE);
}

protected MixedSqlNode parseDynamicTags(XNode node) {
List<SqlNode> contents = new ArrayList<>();
NodeList children = node.getNode().getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
XNode child = node.newXNode(children.item(i));
if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) {
String text = cacheStr(child.getStringBody("")).trim();
if (text.isEmpty()) {
String text = cacheStr(child.getStringBody(""));
String trimText = text.trim();
if (trimText.isEmpty()) {
contents.add(SPACE_SQL_NODE);
continue;
}
text = replaceLeadingAndTrailingWhitespace(text);
TextSqlNode textSqlNode = new TextSqlNode(text);
if (textSqlNode.isDynamic()) {
contents.add(textSqlNode);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,341 @@
package com.baomidou.mybatisplus.core;

import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MybatisXMLLanguageDriverTest {

private static final Logger LOGGER = LoggerFactory.getLogger(MybatisXMLLanguageDriver.class);

@Test
void test1() {
assertSql("""
<script>
select * from `user`
<where>
<if test="true">
1=1
</if>
and 2=2
<if test="true">
and 3=3
</if>
</where>
</script>
""", "select * from `user` WHERE 1=1 and 2=2 and 3=3");
}

@Test
void test2() {
assertSql("""
<script>
select * from `user`
<where>
<if test="false">
1=1
</if>
and 2=2
<if test="true">
and 3=3
</if>
</where>
</script>
""", "select * from `user` WHERE 2=2 and 3=3");
}

@Test
void test3() {
assertSql("""
<script>
select * from `user`
<where>
<if test="false">
1=1
</if>
and 2=2
<if test="true">
and 3=3
</if>
</where>
</script>
""", "select * from `user` WHERE 2=2 and 3=3");
}

@Test
void test4() {
assertSql("""
<script>
select * from `user`
<where>
<if test="true">1=1</if>and 2=2<if test="true">and 3=3</if>
</where>
</script>
""", "select * from `user` WHERE 1=1and 2=2and 3=3");

}

@Test
void test5() {
assertSql("""
<script>
select * from `user`
where 1=1
<if test="1==1">and id is not null</if>
<if test="1==1">and name is not null</if>
</script>
""", "select * from `user`\n" +
" where 1=1 and id is not null and name is not null");
}

@Test
void test6() {
assertSql("""
<script>
select * from `user`
where 1=1
<if test="1==1">and id is not null</if><if test="1==1">and name is not null</if>
</script>
""", "select * from `user`\n" +
" where 1=1 and id is not null and name is not null");
}

@Test
void test7() {
assertSql("""
<script>
select * from `user`
<where>
<if test="1==1">and id is not null</if><if test="1==1">and name is not null</if>
</where>
</script>
""", "select * from `user` WHERE id is not nulland name is not null");
}

@Test
void test8() {
assertSql("""
<script>
select * from `user`
<where>
<if test="1==1">and id is not null</if>
<if test="1==1">and name is not null</if>
</where>
</script>
""", "select * from `user` WHERE id is not null and name is not null");
}

@Test
void test9() {
assertSql("""
<script>
select * from `user`
<where>
<if test="1==1">and id is not null</if>
<if test="1==1">and name is not null</if>
</where>
</script>
""", "select * from `user` WHERE id is not null and name is not null");
}

@Test
void test10() {
assertSql("""
<script>
select * from `user` where 1 = 1
<if test="1==1">and id is not null</if><if test="1==1">and name is not null</if>
</script>
""", "select * from `user` where 1 = 1 and id is not null and name is not null");
}

@Test
void test11() {
assertSql("""
<script>
select * from `user` where 1 = 1
<if test="1==1">and id is not null</if>
<if test="1==1">and name is not null</if>
</script>
""", "select * from `user` where 1 = 1 and id is not null and name is not null");
}

@Test
void test12() {
assertSql("""
<script>
select * from `user` where 1 = 1 and id in
<foreach collection='@java.util.Arrays@asList(1,2,3,4,5)' item='item' separator=',' open='(' close=')'>
#{item}
</foreach>
</script>
""", "select * from `user` where 1 = 1 and id in ( ? , ? , ? , ? , ? )");
}

@Test
void test13() {
assertSql("""
<script>
select * from `user` where 1 = 1 and
<foreach collection='@java.util.Arrays@asList(1,2,3,4,5)' item='item' separator='and'>
<if test="item == 1">id is not null</if>
<if test="item == 2">name is not null</if>
<if test="item == 3">age is not null</if>
</foreach>
</script>
""", "select * from `user` where 1 = 1 and id is not null and name is not null and age is not null");
}

@Test
void test14() {
assertSql("""
<script>
update user
<set>
<if test="true">username=#{username},</if>
<if test="false">password=#{password},</if>
<if test="true">email=#{email},</if>
<if test="true">bio=#{bio},</if>
</set>
where id=#{id}
</script>
""", "update user SET username=?, email=?, bio=? where id=?");
}

@Test
void test15() {
assertSql("""
<script>
update user
<!--这是一条更新语句-->
<set>
<if test="true">username=#{username},</if>
<if test="false">password=#{password},</if>
<if test="true">email=#{email},</if>
<if test="true">bio=#{bio},</if>
</set>
where id=#{id}
</script>
""", "update user SET username=?, email=?, bio=? where id=?");
}

@Test
void test16() {
assertSql("""
<script>
update user
<!--这是一条更新语句-->
<bind name="name" value="test" />
<set>
<if test="true">username=#{username},</if>
<if test="false">password=#{password},</if>
<if test="true">email=#{email},</if>
<if test="true">bio=#{bio},</if>
</set>
where id=#{id}
</script>
""", "update user SET username=?, email=?, bio=? where id=?");
}

@Test
void test17() {
assertSql("""
<script>
select * from `user`
<where>
<!--
查了点东西啊
12345
789
-->
<if test="true">1=1</if>and 2=2<if test="true">and 3=3</if>
</where>
</script>
""", "select * from `user` WHERE 1=1and 2=2and 3=3");
}

@Test
void test18() {
assertSql("""
<script>
select * from `user`
<where>
<choose>
<when test="false">
and age > #{age}
</when>
<when test="false">
and name like concat(#{name},'%')
</when>
<otherwise>
and sex = '男'
</otherwise>
</choose>
</where>
</script>
""", "select * from `user` WHERE sex = '男'");
}

@Test
void test19() {
assertSql("""
<script>
select * from `user`
<where>
<choose>
<when test="false">
and age > #{age}
</when>
<when test="true">
and name like concat(#{name},'%')
</when>
<otherwise>
and sex = '男'
</otherwise>
</choose>
</where>
</script>
""", "select * from `user` WHERE name like concat(?,'%')");
}

@Test
void test20() {
assertSql("""
<script>
select * from `user`
<where>
<choose>
<when test="false">
and age > #{age}
</when>
<when test="true">and name like concat(#{name},'%')</when>
<otherwise>
and sex = '男'
</otherwise>
</choose>
</where>
and 1=1
</script>
""", "select * from `user` WHERE name like concat(?,'%') and 1=1");
}



void runMybatis(String script, String sql) {
var languageDriver = new XMLLanguageDriver();
var sqlSource = languageDriver.createSqlSource(new MybatisConfiguration(), script, Object.class);
LOGGER.info("mybatis parse :{}", sqlSource.getBoundSql(null).getSql());
}


void assertSql(String script, String sql) {
var languageDriver = new MybatisXMLLanguageDriver();
var sqlSource = languageDriver.createSqlSource(new MybatisConfiguration(), script, Object.class);
runMybatis(script, sql);
var boundSql = sqlSource.getBoundSql(null).getSql();
LOGGER.info("mybatis-plus parse :{}", boundSql);
Assertions.assertEquals(sql, boundSql);
}

}
Loading

0 comments on commit ec394ea

Please sign in to comment.