MyBatis - 如何创建动态 WHERE 子句

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

服务获取一个未知对象,其中包含三个值的列表[列,运算符,值]例如, 电子邮件 - 就像 - “测试”

基于结果列表构建我拥有的 WHERE 子句,但我也可以构建如下条件(例如)

WHERE(电子邮件如“测试”和 user_id <> 5)或(trans_id <100 AND session_id> 500)

有谁可以帮我怎么做吗?

java ibatis mybatis
3个回答
8
投票

我自己也时隔许久重新发现了MyBatis(曾经也熟悉过iBatis)。 Rolf 的示例看起来可能是 .Net 实现,我可能是错的,但我不认为 Java 表示法现在看起来像那样。 Rolf 关于文字字符串的提示非常有用。

我创建了一个小类来保存列、运算符和值,并将它们传递到 MyBatis 中进行处理。 列和运算符是字符串文字,但我将这些值保留为 sql 参数(我想 MyBatis 能够进行任何必要的类型转换)。

public class TestAnswer {
    public static void main(String[] args) {
            ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
            SqlSessionFactory sqlFactory = (SqlSessionFactory) ctx.getBean("sqlSessionFactory");            
            MappedStatement statement = sqlFactory.getConfiguration().getMappedStatement("testAnswer");                        

            ArrayList<Clause> params1 = new ArrayList<Clause>();
            params1.add(new Clause("email","like","test"));
            params1.add(new Clause("user","<>",5));

            ArrayList<Clause> params2 = new ArrayList<Clause>();
            params2.add(new Clause("trans_id","<",100));
            params2.add(new Clause("session_id",">",500));

            HashMap params = new HashMap();
            params.put("params1", params1);
            params.put("params2", params2);

            BoundSql boundSql = statement.getBoundSql(params);
            System.out.println(boundSql.getSql());             
    }

    static class Clause{        
        private String column;
        private String operator;
        private Object value;

        public Clause(String column, String operator, Object value){
            this.column = column;
            this.operator = operator;
            this.value = value;
        }

        public void setColumn(String column) {this.column = column;}
        public void setOperator(String operator) {this.operator = operator;}
        public void setValue(Object value) {this.value = value;}
        public String getColumn() {return column;}
        public String getOperator() {return operator;}
        public Object getValue() {return value;}        
    }    
}

如您所见,我使用 Spring,但我预计类似的东西可能会在 Spring 环境之外工作。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

    <mapper namespace="com.stackoverflow.TestMapper">

    <select id="testAnswer" parameterType="map" resultType="hashmap">
      select *
    FROM somewhere
        <where>
            <foreach item="clause" collection="params1" separator=" AND " open="(" close=")"> 
                ${clause.column} ${clause.operator} #{clause.value} 
            </foreach>            
            OR
            <foreach item="clause" collection="params2" separator=" AND " open="(" close=")"> 
                ${clause.column} ${clause.operator} #{clause.value} 
            </foreach>    
        </where>
    </select>

</mapper>

2
投票

这个答案有两个关键部分。一个是“动态”元素,另一个是问题中“运算符”周围的 $$ 文字元素。

  <select id="yourSelect" parameterClass="Map" resultMap="somethingsomething" >
    select * from YOURTABLE
      <dynamic prepend="WHERE">
        <isNotNull prepend="AND" property="email">
          email $operator$ #testvalue#
        </isNotNull>
      </dynamic>
  </select>

另请参阅有关此主题的 DataMapper 动态 SQL 文档


0
投票

查看 myBatis 文档,了解动态 where 子句。 https://mybatis.org/mybatis-3/dynamic-sql.html

<select id="findActiveBlogLike"
     resultType="Blog">
  SELECT * FROM BLOG
  <where>
    <if test="state != null">
         state = #{state}
    </if>
    <if test="title != null">
        AND title like #{title}
    </if>
    <if test="author != null and author.name != null">
        AND author_name like #{author.name}
    </if>
  </where>
</select>

where 元素知道仅当包含标签返回任何内容时才插入“WHERE”。此外,如果该内容以“AND”或“OR”开头,它知道将其删除

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