Mybatis Mapper 中 Postgres && 语句错误?

问题描述 投票:0回答:1

我有一个正在工作的 postgres 查询,我试图在 Mybatis 中设置它,但不断收到语法错误。我想在 Mybatis 中实现的 PgAdmin 中运行的查询检查两个数组之间是否存在任何公共项。我的 pgAdmin 中的工作查询如下:

SELECT * FROM weather_schema.weather weather
WHERE STRING_TO_ARRAY(weather.phenoms, ',') && '{"TO", "WI"}'```

现在下面是我如何在 Mybatis xml Mapper 中进行此设置,其中 '{"TO", "WI"}' 被称为“phenoms”的可注入字符串列表替换。

<select id="getFilteredWeather" resultMap="WeatherObj">
    SELECT
    *
    FROM weather_schema.weather weather
    WHERE
    string_to_array(weather.custom_phenoms, ',') &amp;&amp; 
    <foreach item="phenom" index="," collection="phenoms"
             open="&#39;{&quot;" separator="&quot;,&quot;" close="&quot;}&#39;">
        #{phenom}
    </foreach>
</select>

这给出了以下结果:


org.mybatis.spring.MyBatisSystemException\] with root cause
org.postgresql.util.PSQLException: The column index is out of range: 7, number of columns: 6.
java xml postgresql psql mybatis
1个回答
0
投票

#{}
是准备好的语句中的占位符,因此不能在文字中使用它。

虽然在技术上可以使用

${}
而不是
#{}
来生成这样的文字,但不建议这样做,因为这样很难防止 SQL 注入(请参阅此 FAQ 条目)。

我将向您展示三种替代解决方案。

  1. 加入字符串列表并使用右侧的
    STRING_TO_ARRAY
  2. 使用
    ARRAY[...]::TEXT[]
    语法
  3. 使用自定义类型处理程序

1.加入字符串列表并使用右侧的
STRING_TO_ARRAY

关于如何使用连接的

phenoms
,可能有一些选项。
一种方法是向
WhetherObj
添加一个新方法。

public String getPhenomsStr() {
  return String.join(",", phenoms);
}

那么映射器中的

WHERE
子句将如下所示。

WHERE
string_to_array(weather.custom_phenoms, ',') &amp;&amp;
string_to_array(#{phenomsStr} ',')

2.使用
ARRAY[...]::TEXT[]
语法

这个想法与你原来的解决方案类似。

WHERE
string_to_array(weather.custom_phenoms, ',') &amp;&amp;
string_to_array(
<foreach item="phenom" collection="phenoms"
    open="ARRAY[" separator="," close="]::TEXT[]">
  #{phenom}
</foreach>

3.使用自定义类型处理程序

您可以编写一个调用

Statement#setArray()
的自定义类型处理程序。

import java.sql.Array;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Arrays;
import java.util.List;

import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

public class StringListTypeHandler extends BaseTypeHandler<List<String>> {

  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, List<String> parameter, JdbcType jdbcType)
      throws SQLException {
    Array array = ps.getConnection().createArrayOf("TEXT", parameter.toArray());
    ps.setArray(i, array);
    array.free();
  }
  // ...
}

注意:此类型处理程序的完整实现位于此可执行文件demo中。

然后,您可以在参数引用中指定类型处理程序。

WHERE
string_to_array(weather.custom_phenoms, ',') &amp;&amp;
#{phenoms,typeHandler=my.pkg.StringListTypeHandler}

© www.soinside.com 2019 - 2024. All rights reserved.