diff --git a/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml b/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml index d19fe03..bc1b964 100644 --- a/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml +++ b/ccdi-project/src/main/resources/mapper/ccdi/project/CcdiBankStatementMapper.xml @@ -148,7 +148,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" - bs.project_id = #{query.projectId} + AND (bs.project_id = #{query.projectId}) AND IFNULL(bs.AMOUNT_CR, 0) > 0 diff --git a/ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapperXmlTest.java b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapperXmlTest.java new file mode 100644 index 0000000..ec8bae6 --- /dev/null +++ b/ccdi-project/src/test/java/com/ruoyi/ccdi/project/mapper/CcdiBankStatementMapperXmlTest.java @@ -0,0 +1,121 @@ +package com.ruoyi.ccdi.project.mapper; + +import com.ruoyi.ccdi.project.domain.dto.CcdiBankStatementQueryDTO; +import org.apache.ibatis.builder.xml.XMLMapperBuilder; +import org.apache.ibatis.mapping.BoundSql; +import org.apache.ibatis.mapping.Environment; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.scripting.xmltags.XMLLanguageDriver; +import org.apache.ibatis.session.Configuration; +import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory; +import org.apache.ibatis.type.TypeAliasRegistry; +import org.junit.jupiter.api.Test; + +import javax.sql.DataSource; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class CcdiBankStatementMapperXmlTest { + + private static final String RESOURCE = "mapper/ccdi/project/CcdiBankStatementMapper.xml"; + + @Test + void selectStatementPage_shouldKeepWhitespaceBeforeDynamicAndConditions() throws Exception { + Configuration configuration = new Configuration(); + configuration.setEnvironment(new Environment("test", new JdbcTransactionFactory(), new NoOpDataSource())); + registerTypeAliases(configuration.getTypeAliasRegistry()); + configuration.getLanguageRegistry().register(XMLLanguageDriver.class); + configuration.addMapper(CcdiBankStatementMapper.class); + + try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(RESOURCE)) { + XMLMapperBuilder xmlMapperBuilder = + new XMLMapperBuilder(inputStream, configuration, RESOURCE, configuration.getSqlFragments()); + xmlMapperBuilder.parse(); + } + + MappedStatement mappedStatement = configuration.getMappedStatement( + "com.ruoyi.ccdi.project.mapper.CcdiBankStatementMapper.selectStatementPage"); + CcdiBankStatementQueryDTO queryDTO = new CcdiBankStatementQueryDTO(); + queryDTO.setProjectId(33L); + queryDTO.setTabType("in"); + + Map params = new HashMap<>(); + params.put("query", queryDTO); + + BoundSql boundSql = mappedStatement.getBoundSql(params); + String sql = boundSql.getSql().replaceAll("\\s+", " ").trim(); + + assertFalse(sql.contains("?AND"), sql); + assertTrue(sql.contains("(bs.project_id = ?) AND IFNULL"), sql); + } + + @Test + void statementFilterWhere_shouldWrapBaseConditionToAvoidParameterAndCollision() throws Exception { + try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(RESOURCE)) { + String xml = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); + String projectIdLine = Arrays.stream(xml.split("\\R")) + .filter(line -> line.contains("bs.project_id = #{query.projectId}")) + .findFirst() + .orElse(""); + + assertTrue(xml.contains("AND (bs.project_id = #{query.projectId})"), xml); + assertTrue(projectIdLine.contains("AND (bs.project_id = #{query.projectId})"), projectIdLine); + } + } + + private void registerTypeAliases(TypeAliasRegistry typeAliasRegistry) { + typeAliasRegistry.registerAlias("map", Map.class); + } + + private static class NoOpDataSource implements DataSource { + + @Override + public java.sql.Connection getConnection() { + throw new UnsupportedOperationException("Not required for SQL rendering tests"); + } + + @Override + public java.sql.Connection getConnection(String username, String password) { + throw new UnsupportedOperationException("Not required for SQL rendering tests"); + } + + @Override + public java.io.PrintWriter getLogWriter() { + return null; + } + + @Override + public void setLogWriter(java.io.PrintWriter out) { + } + + @Override + public void setLoginTimeout(int seconds) { + } + + @Override + public int getLoginTimeout() { + return 0; + } + + @Override + public java.util.logging.Logger getParentLogger() { + return java.util.logging.Logger.getGlobal(); + } + + @Override + public T unwrap(Class iface) { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public boolean isWrapperFor(Class iface) { + return false; + } + } +}