MyBatis动态SQL

Posted nuist__NJUPT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis动态SQL相关的知识,希望对你有一定的参考价值。

MyBatis动态SQL

MyBatis提供了对SQL语句的动态组装,不再需要开发人员手动拼接SQL语句,MyBatis的动态SQL元素与JSTL或XML文本处理器相似,常用if,choose,when,otherwise,trim,where,set,foreach和bind等元素。
准备工作:
1-使用mysql创建名为spring的数据库,在该数据库中创建用户表user,并录入相关数据,如下所示。


2-用IDEA创建名为DynamicSQL的web应用,并在web目录下的WEB-INF文件夹下导入相关jar包,并将jar包添加为库项目。

3-在src目录下创建日志文件log4j.properties

# Global logging configuration
log4j.rootLogger=ERROR, stdout
# MyBatis logging configuration...
log4j.logger.org.mybatis.example.BlogMapper=TRACE
# Console output...
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p [%t] - %m%n

4-在src目录下创建spring配置文件applicationContext.xml,在该文件中配置数据源,需要扫描的包,是注解生效等

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/tx
       http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--指定需要扫描的包,是注解生效-->
    <context:component-scan base-package="com.dao"/>
    <context:component-scan base-package="com.controller"/>
    <!--配置数据源-->
    <bean id = "dataSource" class = "org.apache.commons.dbcp2.BasicDataSource">
        <!--配置数据库驱动-->
        <property name = "driverClassName" value = "com.mysql.jdbc.Driver"/>
        <!--配置连接数据库的url-->
        <property name = "url" value = "jdbc:mysql://localhost:3306/spring?characterEncoding=utf8"/>
        <!--连接数据库的用户名-->
        <property name = "username" value = "root"/>
        <!--连接数据库的密码-->
        <property name = "password" value = "123456"/>
        <!--最大连接数-->
        <property name = "maxTotal" value = "30"/>
        <!--最大空闲连接数-->
        <property name = "maxIdle" value = "10"/>
        <!--初始化最大连接数-->
        <property name = "initialSize" value = "5"/>
    </bean>
    <!--添加事务支持-->
    <bean id = "txManager" class = "org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name = "dataSource" ref = "dataSource"/>
    </bean>
    <!--开启事务注解-->
    <tx:annotation-driven transaction-manager="txManager"/>
    <!--配置MyBatis工厂,同时指定数据源,并与MyBatis完美整合-->
    <bean id = "sqlSessionFactory" class = "org.mybatis.spring.SqlSessionFactoryBean">
        <property name = "dataSource" ref = "dataSource"/>
        <!--configLocation的属性值为MyBatis的核心配置文件-->
        <property name = "configLocation" value = "classpath:com/mybatis/mybatis-config.xml"/>
    </bean>
    <!--Mapper代理开发,使用Spring自动扫描MyBatis接口并装配,Spring将指定包中的所有被@Mapper注解过的接口自动装配为MyBatis的映射接口-->
    <bean class = "org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!--mybatis-spring的组件扫描器-->
        <property name = "basePackage" value = "com.dao"/>
        <property name = "sqlSessionFactoryBeanName" value = "sqlSessionFactory"/>
    </bean>
</beans>

5-在src目录下创建com.po包,在该包中创建user表的可持久化类MyUser。

public class MyUser {
    public Integer uid ; //主键
    public String uname ;
    public String usex ;

    public Integer getUid() {
        return uid;
    }

    public void setUid(Integer uid) {
        this.uid = uid;
    }

    public String getUname() {
        return uname;
    }

    public void setUname(String uname) {
        this.uname = uname;
    }

    public String getUsex() {
        return usex;
    }

    public void setUsex(String usex) {
        this.usex = usex;
    }
    @Override
    public String toString(){
        return "User [uid = " + uid + " uname = " + uname + " usex = " + usex + "]" ;
    }
}

6-在src目录下创建com.mybatis包,在该包中创建user表的SQL映射文件UserMapper.xml和MyBatis的核心配置文件mybatis-comfig.xml

UserMapper.xml文件:

<?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.dao.UserDao">
<!--使用if元素根据条件动态查询用户信息-->
    <select id = "selectUserByIf" parameterType = "com.po.MyUser" resultType = "com.po.MyUser">
        select * from user where 1=1
        <if test = "uname != null and uname != ''">
            and uname like concat('%', #{uname}, '%')
        </if>
        <if test = "usex != null and usex != ''">
            and usex = #{usex}
        </if>
    </select>
    <!--choose,when,otherwise类似于switch,case,default,选择语句-->
    <!--使用choose,when,otherwise,根据条件动态查询用户信息,当满足第一个when的时候,其它不执行,第一个不满足,而第二个满足,则执行第二个when,否则执行otherwise-->
    <select id = "selectUserByChoose" parameterType = "com.po.MyUser" resultType = "com.po.MyUser">
        select * from user where 1=1
        <choose>
            <when test = "uname != null and uname != ''">
                and uname like concat('%', #{uname}, '%')
            </when>
            <when test = "usex != null and usex != ''">
                and usex = #{usex}
            </when>
            <otherwise>
                and uid > 10
            </otherwise>
        </choose>
    </select>
    <!--trim的主要功能是在自己包含的内容前加上某些前缀,也可以在其后加上某些后缀,与之对应的属性是prefix和suffix,
    也可以把内容的某些首部覆盖,也可以把尾部的某些内容覆盖,对应的属性为prifixOverrides和suffixOverrides,可以使用trim来代替where元素的功能-->
    <!--使用trim元素根据条件动态查询用户信息-->
    <select id = "selectUserByTrim" parameterType = "com.po.MyUser" resultType = "com.po.MyUser">
        select * from user
        <trim prefix = "where" prefixOverrides = "and | or">
            <if test = "uname != null and uname != ''">
                and uname like concat('%', #{uname}, '%')
            </if>
            <if test = "usex != null and usex !=''">
                and usex = #{usex}
            </if>
        </trim>
    </select>
    <!--where元素的作用是会在写入where元素的地方输出一个where语句,另外一个好处是不需要考虑where里面的条件的输出是什么样子,
    MyBatis将智能处理-->
    <!--使用where元素根据条件动态查询用户信息-->
    <select id = "selectUserByWhere" parameterType = "com.po.MyUser" resultType = "com.po.MyUser">
        select * from user
        <where>
        <if test = "uname != null and uname != ''">
            and uname like concat('%', #{uname}, '%')
        </if>
        <if test = "usex != null and usex != ''">
            and usex = #{usex}
        </if>
        </where>
    </select>
    <!--使用set元素动态修改一个元素-->
    <update id = "updateUserBySet"  parameterType = "com.po.MyUser" >
        update user
        <set>
            <if test = "uname != null"> uname = #{uname},</if>
            <if test = "usex != null"> usex = #{usex}</if>
        </set>
        where uid = #{uid}
    </update>
    <!--foreach元素主要用在构建in条件中,它可以在SQL语句中迭代一个集合,foreach元素的属性主要有item,index,collection,open,separator,close
    item表示集合中每一个元素进行迭代的别名;index表示指定一个名字,用于表示每次迭代到达的位置;open表示该语句以什么开始;separator表示每次以什么符号作为分隔符;;
    close表示以什么结束;在使用foreach元素时,最关键,最容易出错的是collection属性,该属性是必选的,但在不同的情况下,该属性的值不一样,主要有以下三种情况:、
    第一,如果传入的是单参数且参数类型是一个List,collection属性值为list;第二,如果传入的是单参数且参数类型是一个array数组,collection的属性是值是array;
    第三,如果传入的参数是多个,需要把它封装成一个Map,当然单参数也可以封装成Map,Map的key是参数名,collection属性值是传入的List或array对象在自己封装的Map中的key
    -->
    <!--使用foreach语句查询用户信息-->
    <select id = "selectUserByForeach" parameterType = "List" resultType = "com.po.MyUser">
        select * from user where uid in
        <foreach item = "item" index = "index" collection = "list" open = "(" separator = "," close = ")">
            #{item}
        </foreach>
    </select>

    <!--bind元素,当进行模糊查询,使用符号拼接字符串,则无法防止SQL注入,如果使用字符串拼接函数或者连接符号,但在不同的数据库拼接函数和连接符号不同
    例如MySQL的concat和Oracle的连接符号||,这样SQL映射文件就需要根据不同的数据库提供不同的实现,显然比较麻烦,不利于代码的移植,MyBatis提供bind元素来解决这一问题-->
    <!--使用bind元素进行模糊查询-->
    <select id = "selectUserByBind" resultType = "com.po.MyUser" parameterType = "com.po.MyUser">
        <bind name = "param_uname" value = "'%' + uname + '%'"/>
        select * from user where uname like #{param_uname}
    </select>
</mapper>

mybatis-comfig.xml文件:

<?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>
    <!--在使用MyBatis嵌套查询方式进行关联查询时,使用MyBatis延时加载可以在一定程度上提高查询效率-->
    <settings>
        <!--打开延时加载开关-->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--将积极加载改成按需加载-->
        <setting name = "aggressiveLazyLoading" value = "false"/>
    </settings>
    <!--告诉MyBatis映射文件的位置-->
    <mappers>
        <mapper resource = "com/mybatis/UserMapper.xml"/>
    </mappers>
</configuration>

7-在src目录下创建com.dao包,在该包中创建接口UserDao,该接口和SQL映射文件组成映射器,完成SQL映射,spring将指定包中被@Mapper注解的接口自动装配为MyBatis的映射接口


import com.po.MyUser;
import org.apache.ibatis.annotations.Mapper;
import org.springframework.stereotype.Repository;

import java.util.List;
@Repository
@Mapper
public interface UserDao {
    public List<MyUser> selectUserByIf(MyUser user) ;
    public List<MyUser> selectUserByChoose(MyUser user) ;
    public List<MyUser> selectUserByTrim(MyUser user) ;
    public List<MyUser> selectUserByWhere(MyUser user) ;
    public int updateUserBySet(MyUser user) ;
    public List<MyUser> selectUserByForeach(List<Integer> listId) ;
    public List<MyUser> selectUserByBind(MyUser myuser) ;
}

8-在src目录下创建包com.controller,在该包中创建UserController类,在该类中注入接口对象,并调用接口方法

import com.dao.UserDao;
import com.po.MyUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;

import java.util.ArrayList;
import java.util.List;

@Controller
public class UserController {
    @Autowired
    public UserDao userDao ;
    public void test(){
        MyUser ifmu = new MyUser() ;
        ifmu.setUname("张") ;
        ifmu.setUsex("女") ;
        List<MyUser> list = userDao.selectUserByIf(ifmu) ;
        for(MyUser myUser : list){
            System.out.println(myUser) ;
        }
        System.out.println("=========================") ;
        MyUser choosemu = new MyUser() ;
        choosemu.setUsex("") ;
        choosemu.setUname("") ;
        List<MyUser> list1 = userDao.selectUserByChoose(choosemu) ;
        for(MyUser myUser : list1){
            System.out.println(myUser + " ") ;
        }
        System.out.println("=========================") ;
        MyUser trimmu = new MyUser() ;
        trimmu.setUname("胡") ;
        trimmu.setUsex("男") ;
        List<MyUser> list2 = userDao.selectUserByTrim(trimmu) ;
        for(MyUser myUser1 : list2){
            System.out.println(myUser1) ;
        }
        System.out.println("=========================") ;
        MyUser wheremu = new MyUser(mybatis动态sql片段与分页,排序,传参的使用

Mybatis -- 动态Sql概述动态Sql之<if>(包含<where>)动态Sql之<foreach>sql片段抽取

mybatis动态sql之利用sql标签抽取可重用的sql片段

MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段

[mybatis]动态sql_sql_抽取可重用的sql片段

Mybatis动态sql