动态SQL

动态SQL


什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句

利用动态SQL这一特性可以彻底摆脱JDBC之前拼接sql的痛苦

动态 SQL 是 MyBatis 的强大特性之一。如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。

使用动态 SQL 并非一件易事,但借助可用于任何 SQL 映射语句中的强大的动态 SQL 语言,MyBatis 显著地提升了这一特性的易用性。

如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少

if
choose (when, otherwise)
trim (where, set)
foreach

搭建测试数据库环境

CREATE TABLE `blog` (
  `id` varchar(50) NOT NULL COMMENT '博客id',
  `title` varchar(100) NOT NULL COMMENT '博客标题',
  `author` varchar(30) NOT NULL COMMENT '博客作者',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  `views` int(30) NOT NULL COMMENT '浏览量'
) ENGINE=InnoDB DEFAULT CHARSET=utf8



创建一个基础工程

  1. 导包(Lombok)
<dependency>
            <groupId>org.projectlombokgroupId>
            <artifactId>lombokartifactId>
            <version>1.18.26version>
dependency>
  1. 编写配置文件

mybatis-config.xml


DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-config.dtd">


<configuration>
    
    <properties resource="db.properties">
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    properties>

    
    <settings>
        
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    settings>


    <typeAliases>
        <package name="com.hang.pojo"/>
    typeAliases>
    

    
    <environments default="development">
        
        <environment id="development">
            <transactionManager type="JDBC"/>
            
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            dataSource>
        environment>
    environments>

    
    <mappers>
        <mapper class="com.hang.dao.BlogMapper"/>
    mappers>


configuration>
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis?useSSL=true&useUnicode=true"
username=root
password=root
  1. 编写实体类
package com.hang.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Blog {
    private String id;
    private String title;
    private String author;
    private Date createTime;//属性名和字段名不一致
    private int views;
}

这里的id用的String,我们用UUID来生成一个唯一的Id

在utils包下再新建一个工具类:

package com.hang.utils;

import org.junit.Test;

import java.util.UUID;

@SuppressWarnings("all")//镇压警告
public class IDUtils {
    public static String getId(){
        return UUID.randomUUID().toString().replaceAll("-","");//把-换掉

    }

    @Test
    public void test(){
        System.out.println(IDUtils.getId());
        System.out.println(IDUtils.getId());
        System.out.println(IDUtils.getId());
    }

}

package com.hang.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

/**
 * sqlSessionFactory(构建sqlSession的)
 * 定义一个工具类 把资源加载进来 创建一个能执行sql的对象 整个对象可以想象成一个Connection对象
 */
public class MybatisUtils {
    private static SqlSessionFactory sqlSessionFactory;//提升作用域
    //使用Mybatis第一步:获取sqlSessionFactory对象
    static {
        try {
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);//通过build把这个流加载进来
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static SqlSession getSqlSession(){
        //我们可以在工具类创建的时候实现自动提交事务! 不用再手动提交了
        SqlSession sqlSession = sqlSessionFactory.openSession(true);//会返回一个SqlSession(里面有操作数据库的方法 相当于之前的statement对象)
        return sqlSession;
        //优化代码
    }
}

  1. 编写实体类对应的Mapper接口和Mapper.xml文件

    Mapper接口:

    package com.hang.dao;
    
    import com.hang.pojo.Blog;
    
    import java.util.List;
    import java.util.Map;
    
    public interface BlogMapper {
    
    
        /**
         * 插入数据
         * @param blog
         * @return
         */
        int addBlog(Blog blog);
    
    
        /**
         * 查询博客 使用if
         * @param map
         * @return
         */
        List<Blog> queryBlogIF(Map map);
    
    
        //
        List<Blog> queryBlogChoose(Map map);
    
    
        /**
         * 更新博客
         * @param map
         * @return
         */
        int updateBlog(Map map);
    }
    
    

    Mapper.xml

    
    DOCTYPE mapper
            PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
            "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
    
    <mapper namespace="com.hang.dao.BlogMapper">
    
        <insert id="addBlog"  parameterType="blog">
            insert into mybatis.blog (id,title,author,create_time,views)
            values(#{id},#{title},#{author},#{createTime},#{views})
        insert>
    
    
        
        <select id="queryBlogIF" parameterType="map" resultType="blog">
            select * from mybatis.blog
            
            <where>
            <if test="title != null">
                 and title = #{title}
            if>
            <if test="author != null">
                and author = #{author}
            if>
            where>
        select>
    
    
    
        <select id="queryBlogChoose" resultType="blog" parameterType="map">
            select * from mybatis.blog
            <where>
               <choose>
                   <when test="title!=null">
                       title = #{title}
                   when>
                   <when test="author!=null">
                       and author = #{author}
                   when>
                   <otherwise>
                       and views = #{views}
                   otherwise>
               choose>
            where>
        select>
    
    
    
    
        <update id="updateBlog" parameterType="map" >
            update  mybatis.blog
            <set>
                <if test="title!=null">
                    title = #{title},
                if>
                <if test="author!=null">
                    author = #{author}
                if>
            set>
            where id = #{id}
    
    
    
            <trim prefix="WHERE" prefixOverrides="AND |OR ">
                ...
            trim>
            
            <trim prefix="" prefixOverrides="" suffix="" suffixOverrides="">
    
            trim>
        update>
    
    mapper>
    

IF




优化


    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        
        <where>
        <if test="title != null">
             and title = #{title}
        if>
        <if test="author != null">
            and author = #{author}
        if>
        where>
    select>

choose(when,otherwise)

有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
还是上面的例子,但是策略变为:传入了 “title” 就按 “title” 查找,传入了 “author” 就按 “author” 查找的情形。若两者都没有传入,就返回标记为 featured 的 BLOG(这可能是管理员认为,与其返回大量的无意义随机 Blog,还不如返回一些由管理员精选的 Blog)。
 <select id="queryBlogChoose" resultType="blog" parameterType="map">
        select * from mybatis.blog
        <where>
           <choose>
               <when test="title!=null">
                   title = #{title}
               when>
               <when test="author!=null">
                   and author = #{author}
               when>
               <otherwise>
                   and views = #{views}
               otherwise>
           choose>
        where>
    select>



select * from mybatis.blog
<where>
    <if test="title != null">
        title = #{title}
    if>
    <if test="author != null">
        and author = #{author}
    if>
where>

trim(where,set)

用于动态更新语句的类似解决方案叫做 setset 元素可以用于动态包含需要更新的列,忽略其它不更新的列

set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号(这些逗号是在使用条件语句给列赋值时引入的)

 <update id="updateBlog" parameterType="map" >
        update  mybatis.blog
        <set>
            <if test="title!=null">
                title = #{title},
            if>
            <if test="author!=null">
                author = #{author}
            if>
        set>
        where id = #{id}
    update>

所谓的动态SQL,本质还是SQL语句 , 只是我们可以在SQL层面,去执行一个逻辑代码

if

where,set,choose,when

测试类

import com.hang.dao.BlogMapper;
import com.hang.pojo.Blog;
import com.hang.utils.IDUtils;
import com.hang.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

import java.util.Date;
import java.util.HashMap;
import java.util.List;

/**
 * 既然能用Java插入数据 那也能用Java写数据库的脚本 给别人一个库 把这个东西写在Java里 让别人去跑这个Java文件就行
 */
public class MyTest {

    @Test
    public void addInitBlog(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

        Blog blog = new Blog();
        blog.setId(IDUtils.getId());
        blog.setTitle("Mybatis使用如此简单");
        blog.setAuthor("wuwuwu");
        blog.setCreateTime(new Date());
        blog.setViews(9999);


        mapper.addBlog(blog);



        blog.setId(IDUtils.getId());
        blog.setTitle("Java使用如此简单");
        mapper.addBlog(blog);

        blog.setId(IDUtils.getId());
        blog.setTitle("Spring使用如此简单");
        mapper.addBlog(blog);

        blog.setId(IDUtils.getId());
        blog.setTitle("微服务使用如此简单");
        mapper.addBlog(blog);



        sqlSession.close();
    }


    @Test
    public void queryBlogIF(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

        HashMap map = new HashMap();//通过不同参数实现动态sql效果
        map.put("title","Java使用如此简单");
        map.put("author","吴哲航");

        List<Blog> blogs = mapper.queryBlogIF(map);//map为空也能查
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

    /**
     * where元素只会在至少有一个子元素的条件返回sql子句的情况下才回去插入where子句,而且,若语句的开头为and或者or where元素会将它们去掉
     */


    @Test
    public void queryBlogChoose(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

        HashMap map = new HashMap();
        //map.put("title","Java使用如此简单");
        map.put("author","吴哲航");
        map.put("views",9999);

        List<Blog> blogs = mapper.queryBlogChoose(map);
        for (Blog blog : blogs) {
            System.out.println(blog);
        }
        sqlSession.close();
    }

    @Test
    public void updateBlog(){
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        BlogMapper mapper = sqlSession.getMapper(BlogMapper.class);

        HashMap map = new HashMap();
        map.put("title","Java使用如此简单222");
        map.put("author","吴哲航22");
        map.put("id","dfe8161b356b417db7b24ea95eb67d3a");

        int i = mapper.updateBlog(map);
        if (i>0){
            System.out.println("更新成功!");
        }
        sqlSession.close();
    }
}

你可能感兴趣的:(sql,mybatis,java,数据库)