MyBatis - как создать динамическое предложение WHERE
Служба получает неизвестный объект, содержащий список из трех значений [столбец, оператор, значение]. Например, EMAIL - like - "TEST"
Основываясь на результирующем списке для построения предложения WHERE, которое я имею, я также смог бы построить такое условие следующим образом (например)
ГДЕ (электронная почта, например, 'test' И user_id <> 5) ИЛИ (trans_id <100 AND session_id> 500)
Кто-нибудь может мне помочь, как это сделать?
2 ответа
Я заново открыл MyBatis после долгого отсутствия сам (я был знаком с iBatis в свое время). Пример Рольфа выглядит так, как будто это может быть реализация.Net, я могу ошибаться, но я не думаю, что нотация Java выглядит сейчас так. Совет Рольфа о буквальных строках очень полезен.
Я создал небольшой класс для хранения ваших столбцов, операторов и значений и передаю их в 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.stackru.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>
В этом ответе есть две ключевые части. Одним из них является "динамический" элемент, а другим являются буквальные элементы $$ вокруг "оператора" в вашем вопросе.
<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 Dynamic SQL по этой теме.