Bootstrap

8、MyBatis框架——动态SQL

目录

一、搭建项目

二、动态SQL的使用

1、动态查询

(1)if标签

(2)where标签

2、动态修改

(1)set标签

3、trim标签

4、查询条件优先级

(1)选择标签choose

5、批量删除

(1)连接词or

(2)连接词in


一、搭建项目

(1)准备数据库表

CREATE DATABASE mybatisdatabase;
USE mybatisdatabase;
CREATE TABLE IF NOT EXISTS `admin`(
`uid` INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(20),
`upassword` VARCHAR(20) NOT NULL,
`phone` VARCHAR(11) UNIQUE NOT NULL,
`address` VARCHAR(10) NOT NULL
);

INSERT INTO `admin`(`username`,`upassword`,`phone`,`address`) VALUES
('张三','123456','15689609560','安徽合肥包河区'),
('王二','666666','13395581841','安徽合肥蜀山区'),
('李四','456789','18144172517','安徽合肥高新区');

(2)新建module--->java框架Maven工程--->完善工程目录

(3) 在pom.xml中添加需要使用的依赖

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>com.mybatis</groupId>
  <artifactId>mybatis05</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>mybatis05</name>
  <url>http://maven.apache.org</url>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
    </dependency>
    
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis</artifactId>
      <version>3.5.11</version>
    </dependency>
    
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.48</version>
    </dependency>

    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>

    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.24</version>
    </dependency>
  </dependencies>
</project>

(4)创建实体类和Mapper接口 

package com.mybatis.entity;

import lombok.Data;

@Data
public class Admin {

  private long uid;
  private String username;
  private String upassword;
  private String phone;
  private String address;



}
package com.mybatis.mapper;

public interface AdminMapper {
}

(5)在resources目录下新建config文件,存放mybatis全局配置文件和外部数据源

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

    <!--    引入外部数据源参数-->
    <properties resource="config/jdbc.properties"></properties>

    <settings>
        <!--        开启驼峰映射-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!--        开启日志打印-->
        <setting name="logImpl" value="LOG4J"/>
    </settings>

    <!--    给表起别名-->
    <typeAliases>
        <package name="com.mybatis.entity"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${jdbc.driver}"/>
                <property name="url" value="${jdbc.url}"/>
                <property name="username" value="${jdbc.username}"/>
                <property name="password" value="${jdbc.password}"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <package name="com.mybatis.mapper"/>
    </mappers>
</configuration>
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/mybatisdatabase
jdbc.username=root
jdbc.password=123456

(6)在resources目录下新建与Mapper接口层级相同的文件夹存放Mapper映射文件 

<?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.mybatis.mapper.AdminMapper">

</mapper>

(7)在resources目录下添加日志配置文件log4j.properties 

#打印日志的级别:可控制打印信息,哪些打印,哪些不打印
#Console:打印窗口
log4j.rootLogger=DEBUG,Console
#Console
log4j.appender.Console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Target=System.out
#设置打印格式
log4j.appender.Console.layout=org.apache.log4j.PatternLayout
#设置打印信息
log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
#打印日志级别:设置打印级别只要不是ERROR级别就不打印
log4j.logger.org.apache=ERROR
log4j.logger.org.mybatis=ERROR
log4j.logger.org.springframework=ERROR
#这个需要
log4j.logger.log4jdbc.debug=ERROR
log4j.logger.com.gk.mapper=ERROR
log4j.logger.jdbc.audit=ERROR
log4j.logger.jdbc.resultset=ERROR
#这个打印SQL语句非常重要
log4j.logger.jdbc.sqlonly=DEBUG
log4j.logger.jdbc.sqltiming=ERROR
log4j.logger.jdbc.connection=FATAL

二、动态SQL的使用

动态SQL就是在MyBatis中拼接SQL语句的一种规范,在JDBC中也可以使用StringBuild类中的方法拼接SQL语句,但MyBatis对SQQL语句的拼接更加灵活,性能更加强大 

1、动态查询

在AdminMapper接口中创建search方法,根据姓名或手机号码查询,当只传递一个参数时SQL语句应该如何编辑

package com.mybatis.mapper;

import com.mybatis.entity.Admin;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface AdminMapper {

    List<Admin> search(@Param("username") String username, @Param("phone") String phone);
}

(1)if标签

if标签:判断标签,判断结果为true即执行if标签中的语句

        test:判断条件

通过判断传递的参数是否为空,进行SQL语句的拼接

只用if标签的话,如果第一个条件为空,会在where后面直接拼接and.......,SQL语句会出现错误,而且不传参的话,SQL语句也无法执行,多了个where

(2)where标签

根据条件的个数,判定是否要添加where关键词。

只要where标签中有满足的条件,就会在SQL语句后添加where

如果where后面的第一个条件带有and或or连接词,where标签会自动去除(只能取出拼接语句前面的连接词)

package com.mybatis.mapper;

import com.mybatis.entity.Admin;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface AdminMapper {

    List<Admin> search(@Param("username") String username, @Param("phone") String phone);
}
<?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.mybatis.mapper.AdminMapper">
    
    <select id="search" resultType="admin">
select * from admin
        <where>
            <if test="username != null">
                username = #{username}
            </if>
            <if test="phone != null">
                and phone = #{phone}
            </if>
        </where>

    </select>
</mapper>
package com.mybatis.mapper;

import com.mybatis.entity.Admin;
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 org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import static org.junit.Assert.*;

public class AdminMapperTest {

    SqlSessionFactory sqlSessionFactory = null;
    @Before
    public void init(){
        InputStream resourceAsStream = null;
        try {
            resourceAsStream = Resources.getResourceAsStream("config/mybatis-config.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    }

    @Test
    public void search() {
        //创建SqlSession会话
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取AdminMapper接口的动态代理对象
        AdminMapper adminMapper = sqlSession.getMapper(AdminMapper.class);
        //通过接口调用方法
        List<Admin> adminList = adminMapper.search("张三",null);
        for (Admin admin:adminList){
            System.out.println("admin = " + admin);
        }
        //关闭资源
        sqlSession.close();
    }
}

2、动态修改

在AdminMapper接口中创建update(Admin admin)方法

package com.mybatis.mapper;

import com.mybatis.entity.Admin;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface AdminMapper {

    int update(Admin admin);
}

(1)set标签

当set标签中有条件成立时就会附加set关键字,字段为null时该列不会被更新。set可以忽略与sql无关的逗号。

<?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.mybatis.mapper.AdminMapper">
    
    <update id="update" parameterType="admin">
        update admin
        <set>
            <if test="username != null">
                username = #{username}
            </if>
            <if test="upassword != null">
                ,upassword = #{upassword}
            </if>
            <if test="phone != null">
                ,phone = #{phone}
            </if>
            <if test="address != null">
                ,address = #{address}
            </if>
        </set>where uid = #{uid}
    </update>

    
</mapper>
package com.mybatis.mapper;

import com.mybatis.entity.Admin;
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 org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import static org.junit.Assert.*;

public class AdminMapperTest {

    SqlSessionFactory sqlSessionFactory = null;
    @Before
    public void init(){
        InputStream resourceAsStream = null;
        try {
            resourceAsStream = Resources.getResourceAsStream("config/mybatis-config.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    }


    @Test
    public void update() {
        //创建SqlSession会话,开启事务自动提交
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        //获取AdminMapper接口的动态代理对象
        AdminMapper adminMapper = sqlSession.getMapper(AdminMapper.class);
        //创建Admin对象存储要修改的数据
        Admin admin = new Admin();
        admin.setUsername("老二");
        admin.setUpassword("333333");
        admin.setUid(2);
        //通过接口调用方法
        int line = adminMapper.update(admin);
        System.out.println("line = " + line);
        //关闭资源
        sqlSession.close();
    }
}

3、trim标签

trim标签能实现where--->if,set--->if;

        suffixOverrides:去除后缀

        prefixOverrides:去除前缀

                        suffix:添加后缀

                        prefix:添加前缀 

package com.mybatis.mapper;

import com.mybatis.entity.Admin;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface AdminMapper {

    List<Admin> search(@Param("username") String username, @Param("phone") String phone);
}
<?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.mybatis.mapper.AdminMapper">

    <select id="search" resultType="admin">
select * from admin
        <trim prefix="where" prefixOverrides="and">
            <if test="username != null">
                username = #{username}
            </if>
            <if test="phone != null">
                and phone = #{phone}
            </if>
        </trim>
    </select>
</mapper>
package com.mybatis.mapper;

import com.mybatis.entity.Admin;
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 org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import static org.junit.Assert.*;

public class AdminMapperTest {

    SqlSessionFactory sqlSessionFactory = null;
    @Before
    public void init(){
        InputStream resourceAsStream = null;
        try {
            resourceAsStream = Resources.getResourceAsStream("config/mybatis-config.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    }

    @Test
    public void search() {
        //创建SqlSession会话
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取AdminMapper接口的动态代理对象
        AdminMapper adminMapper = sqlSession.getMapper(AdminMapper.class);
        //通过接口调用方法
        List<Admin> adminList = adminMapper.search(null,"18144172517");
        for (Admin admin:adminList){
            System.out.println("admin = " + admin);
        }
        //关闭资源
        sqlSession.close();
    }

}

4、查询条件优先级

当查询条件为多个是,看定义条件的优先级 

(1)选择标签choose

类似多分支结构switch,只会选择一个分支,当有一个when标签满足条件时,结束choose标签

choose标签中的otherwise标签可设置默认条件

5、批量删除

可通过遍历拿到的值进行删除

(1)连接词or

foreach标签

        collection:需要遍历的集合

        item:存储集合中的每一个元素

        separator:循环元素执行的分隔符

        open:循环开始标识

        close:循环结束标识

package com.mybatis.mapper;

import com.mybatis.entity.Admin;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface AdminMapper {

    List<Admin> search(@Param("username") String username, @Param("phone") String phone);

    int update(Admin admin);

    Integer deleteByUid(List<Integer> list);
}
<?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.mybatis.mapper.AdminMapper">

    <delete id="deleteByUid">
        delete from admin
            <where>
                <foreach collection="list" item="uid" separator="or">
                    uid = #{uid}
                </foreach>
            </where>
    </delete>

</mapper>
package com.mybatis.mapper;

import com.mybatis.entity.Admin;
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 org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import static org.junit.Assert.*;

public class AdminMapperTest {

    SqlSessionFactory sqlSessionFactory = null;
    @Before
    public void init(){
        InputStream resourceAsStream = null;
        try {
            resourceAsStream = Resources.getResourceAsStream("config/mybatis-config.xml");
        } catch (IOException e) {
            e.printStackTrace();
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    }

  
    @Test
    public void deleteByUid() {
        //创建SqlSession会话,开启事务自动提交
        SqlSession sqlSession = sqlSessionFactory.openSession(true);
        //获取AdminMapper接口的动态代理对象
        AdminMapper adminMapper = sqlSession.getMapper(AdminMapper.class);
        //创建要删除的uid的集合
        List<Integer> list = new ArrayList<Integer>();
        list.add(2);
        list.add(3);
        //通过接口调用方法
        Integer line = adminMapper.deleteByUid(list);
        System.out.println("line = " + line);
        //手动提交事务
        sqlSession.commit();
        //关闭资源
        sqlSession.close();
    }
}

(2)连接词in

<?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.mybatis.mapper.AdminMapper">

    <delete id="deleteByUid">
        delete from admin

                <where>
                    <foreach collection="list" item="uid" open="uid in(" separator="," close=")">
                        #{uid}
                    </foreach>
                </where>

    </delete>

</mapper>

;