三十二、MyBatis注解SQL

脚本sql

XML配置方式的动态SQL我就不讲了,有兴趣可以自己了解,下面是用<script>的方式把它照搬过来,用注解来实现。适用于xml配置转换到注解配置很明显,在java中写xml可读性和维护性太差,尤其当SQL很长时,这样写是很痛苦的。

//查询所有,@Results字段里只需映射实体类和表字段名不一致的字段名
 @Select(" SELECT * FROM child_channel ORDER BY rank ASC,online_status DESC")
    @Results({
            @Result(property = "onlineStatus", column = "online_status"),
            @Result(property = "hasNew", column = "has_new"),
            @Result(property = "updateTm",column = "update_tm"),
            @Result(property = "createTm",column = "create_tm")
    })
 List<Channel> findChannelList();
//用函数
@Select("<script>" +
            " SELECT COUNT(*) FROM child_unit WHERE 1=1 " +
            "  <when test='params.category != null'> AND category = #{params.category} </when> " +
            "  <when test='params.onlineStatus != null'> AND online_status = #{params.onlineStatus} </when> " +
            "  ORDER BY id ASC" +
            "</script>")
    Integer count(@Param(value = "params") Map<String, Object> params);
//连接查
@Select(" SELECT * FROM child_unit c1 JOIN child_unit_position c2 ON c2.unit_id = c1.id WHERE c2.unit_group_id = #{unitGroupId} ORDER BY c2.rank ASC")
    @Results({
            @Result(property = "subTitle", column = "sub_title"),
            @Result(property = "contentId", column = "content_id"),
            @Result(property = "openType", column = "open_type"),
            @Result(property = "onlineStatus",column = "online_status"),
            @Result(property = "hasNew",column = "has_new"),
            @Result(property = "createTm", column = "create_tm"),
            @Result(property = "updateTm", column = "update_tm")
    })
//删除
@Delete("<script>"
            + " DELETE FROM child_channel WHERE id IN "
            + "     <foreach item='item' index='index' collection='idSet' open='('            separator=',' close=')'>"
            + "         #{item}"
            + "     </foreach>"
            + "</script>")
int deleteByPrimaryKeySet(@Param("idSet") Set<Long> idSet);

在方法中构建sql

dao接口中是不能写实现的,所以这里借用内部类来生成动态SQL。增改删也有对应的@InsertProvider、@UpdateProvider、@DeleteProvider

@Mapper
public interface MybatisDao {
    //使用UserDaoProvider类的findUserById方法来生成sql
    @SelectProvider(type = UserDaoProvider.class, method = "findUserById")
    public List<User> findUserById(User user);
    
    class UserDaoProvider {
        public String findUserById(User user) {
            String sql = "SELECT * FROM user";
            if(user.getId()!=null){
                sql += " where id = #{id}";
            }
            return sql;
        }
    }

这比<script>更加清晰,适用于查询语句不是很长、条件不多的场景,SQL很直观。但是在写很长的SQL时,这样拼接SQL同样会很痛苦

结构化SQL

public String findUserById(User user) {    
            return new SQL(){{    
                SELECT("id,name");    
                SELECT("other");    
                FROM("user");    
                if(user.getId()!=null){    
                    WHERE("id = #{id}");    
                }    
                if(user.getName()!=null){    
                    WHERE("name = #{name}");    
                }    
            //从这个toString可以看出,其内部使用高效的StringBuilder实现SQL拼接    
            }}.toString();    
        }    

这是把前面的内部类改造一下

SELECT:表示要查询的字段,如果一行写不完,可以在第二行再写一个SELECT,这两个SELECT会智能的进行合并而不会重复

FROM和WHERE:跟SELECT一样,可以写多个参数,也可以在多行重复使用,最终会智能合并而不会报错

这样语句适用于写很长的SQL时,能够保证SQL结构清楚。便于维护,可读性高。但是这种自动生成的SQL和HIBERNATE一样,在实现一些复杂语句的SQL时会束手无策。所以需要根据现实场景,来考虑使用哪一种动态SQL

上面的例子只是最基本的用法:更多详细用法,可以参考mybatis中文网的专门介绍

http://www.mybatis.org/mybatis-3/zh/statement-builders.html

List传值错误

动态SQL中,有时要对批量数据进行处理,难免会使用list做为参数

@SelectProvider(type = UserDaoProvider.class, method = "find")
    public List<Map> find(List list);    
    
    class UserDaoProvider {
        public String find(List list) {

这是一个最简单的list传参,但是在运行时会报传参错误。这是mybatis内部机制造成的,其参数需要是key/value结构,当遇到这里不是key/value结构的list时,mybatis会自己把它转换成key/value结构,key就是他的名字"list",value就是他的值List,要正确传参需要使用key/value结构的map,如下

@SelectProvider(type = UserDaoProvider.class, method = "find")
    public List<Map> find(List list);    
    
    class UserDaoProvider {
        public String find(Map map) {
            List list = (List) map.get("list");

猜你喜欢

转载自blog.csdn.net/u010285974/article/details/82767578