有关mybatis的动态sql

时间:2020-12-18 05:06:56

一般地,实现动态SQL都是在xml中使用

例子 :
Model类

package lyb.model.report;

/**
 * Created by lyb-pc on 17-7-19.
 */
public class UserCustomerAuthority {

    private String login_code;
    private String login_name;
    private String store_code;
    private String store_name;

    public String getLogin_code() {
        return login_code;
    }

    public void setLogin_code(String login_code) {
        this.login_code = login_code;
    }

    public String getLogin_name() {
        return login_name;
    }

    public void setLogin_name(String login_name) {
        this.login_name = login_name;
    }

    public String getStore_code() {
        return store_code;
    }

    public void setStore_code(String store_code) {
        this.store_code = store_code;
    }

    public String getStore_name() {
        return store_name;
    }

    public void setStore_name(String store_name) {
        this.store_name = store_name;
    }
}

对应于一个sqlbuilder 有:

package lyb.model.report;

import org.apache.ibatis.jdbc.SQL;

import java.sql.Timestamp;
import java.util.Map;

/**
 * Created by lyb-pc on 17-7-19.
 */
public class UserCustomerAuthoritySqlBuilder {

    public String buildUserCustomerAuthorityFull(Map<String, Object> parameters) {

        String user_id = (String) parameters.get("user_id");

        SQL a = new SQL().SELECT("user_id",
                "user_name",
                "customer_id",
                "customer_name")
                .FROM("WCC_User_Customer_Connection")
                .WHERE("user_id = #{user_id}")
                .GROUP_BY("customer_name",
                        "user_id",
                        "user_name",
                        "customer_id");

        return a.toString();
    }
}

这里使用SQL()构造器的语法, 把所有的原始sql转化为相应的语句, 可以动态根据参数来进行配置, 如这里的user_id就是使用了一个占位符, 在真正执行语句的时候传递给jdbc. 可以将SQL()部分作为一个StringBuilder来使用, 需要使用占位符的时候就使用#{}, 这样的模式, 在最后执行的时候会把参数进行匹配, 并加上'', 也可以直接字符串拼接.

直接使用字符串拼接的如 like和in的使用:

if (invFirstClass != null) {
    a.WHERE("Inventory.cInvCode like " + "'" + invFirstClass + "%'");
}

if (invSecondClass != null) {
    a.WHERE("Inventory.cInvCode like " + "'" + invSecondClass + "%'");
}


if (barcode != null) {
    a.WHERE("Inventory.cInvAddCode = #{barcode}");
}

if (cDCCode != null) {
    a.WHERE("DistrictClass.cDCCode = #{cDCCode}");
}

if (customer_id_list != null) {
    a.WHERE("Customer.cCusCode in" + "(" + customer_id_list + ")");
}


SQL t = new SQL().SELECT("Count(*) as count")
        .FROM("(" + a.toString() + ") as table_temp");

如上面的代码, 展示了like和in的用法, 也有子查询的用法, 即先用一个SQL(), 作为子查询然后一层层嵌套.

实际调用的时候是 :
建立一个Mapper文件, 作为sqlSession掉用时实例化的DAO层.

package lyb.mapper;

import lyb.model.report.UserCustomerAuthority;
import lyb.model.report.UserCustomerAuthoritySqlBuilder;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Result;
import org.apache.ibatis.annotations.Results;
import org.apache.ibatis.annotations.SelectProvider;

import java.util.List;

/**
 * Created by lyb-pc on 17-7-19.
 */
public interface UserCustomerAuthorityMapper {

    @Results(id = "userCustomerAuthorityDefault123", value = {
            @Result(property = "store_name", column = "customer_name"),
            @Result(property = "store_code", column = "customer_id"),
            @Result(property = "login_code", column = "user_id"),
            @Result(property = "login_name", column = "user_name")
    })
    @SelectProvider(type = UserCustomerAuthoritySqlBuilder.class, method = "buildUserCustomerAuthorityFull")
    public List<UserCustomerAuthority> getAuthority(@Param(value = "user_id") String user_id);
}

里面定义好查询结果的ResultMap, 以及使用的SqlProvider.
这样是把具体的sql实现代码给分散出来, 并且具体的代码也具有了一定的可移植性, 而不必直接编写sql的xml文件, 但是如果需要针对多数据源的切换还是需要不同的设置或者是切换语句等.
注意的是在mapper文件中, @Param的注解和sqlBuilder的对应关系.

调用为:

@RequestMapping(value = "/TestStoresListShow", method = RequestMethod.POST)
    public @ResponseBody
    UCCheckResponse storesListShow(@RequestBody UCCheckRequestParams params) {
        UCCheckResponse response = new UCCheckResponse();
        String login_code = params.getLogin_code();
        SqlSession sqlSession = sessionFactory.openSession();

        UserCustomerAuthorityMapper authorityMapper = sqlSession.getMapper(UserCustomerAuthorityMapper.class);

        List<UserCustomerAuthority> authorityList = authorityMapper.getAuthority(params.getLogin_code());
// StringBuilder customer_id_list = new StringBuilder();
// customer_id_list = JohnsonReportHelper.GetCustomerIdListBuilder(authorityList, customer_id_list);

        if (authorityList.size() == 0) {
            response = (UCCheckResponse) JohnsonReportHelper.GenErrorResponse(response, 5002, "该用户没有对应门店数据权限");
            return response;
        }else {
            response = (UCCheckResponse) JohnsonReportHelper.GenRightResponsePart(response);
            response.setData(authorityList);
            return response;
        }
    }

通过sqlSession得到Mapper对象, 就可以继续调用了.