Mybatis动态SQL中的元素代码演示和讲解

1. if

在MyBatis中,元素是最常用的判断语句,它类似于Java中的if语句,主要用于实现某些简单的条件选择。

代码演示 (实现一个多条模糊 根据姓名和职业组合条件查询用户信息列表的动态SQL)

实体类
package beans.Pojo;

public class User {
    private Integer id;
    private String name;
    private String job;

    public User() {
    }

    public User(Integer id, String name, String job) {
        this.id = id;
        this.name = name;
        this.job = job;
    }

    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", job='" + job + '\'' +
                '}';
    }
}
首先配置 SqlMapConfig.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>
    <!--    核心配置文件-->
    <properties resource="jdbc.properties"></properties>
    <!--配置类型别名-->
    <typeAliases>
<!--        <typeAlias type="beans.Pojo.User" alias="user"></typeAlias>-->
        <package name="beans.Pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"></transactionManager>
            <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="beans.dao"></package>
    </mappers>
</configuration>

其中的 jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc\:mysql\://localhost\:3306/···
jdbc.username= ···
jdbc.password= ···

日志 log4j.properties

# Global logging configuration,建议开发环境中要用debug
log4j.rootLogger=DEBUG, stdout
# 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
创建一个接口 UserMapper
public interface UserMapper {
    //模糊
    List<User> findMohu(String name);
    //多个模糊
    List<User> findMohuByNamAndJob(User user);
}
修改映射文件CustomerMapper.xml

在映射文件中使用if元素编写根据姓名和职业组合条件查询用户信息列表的动态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">

<!-- parameterType 输入映射
     resultType 和 resultMap 完成输出映射-->
<!-- 与接口相关联-->
<mapper namespace="beans.dao.UserMapper">

    <!-- 动态sql if 实现多模糊的效果-->
    <select id="findMohuByNamAndJob" parameterType="user" resultType="user">
        <!-- where 1=1 永为真 防止sql注入-->
        select * from t_user where 1=1
        <if test="name!=null and name!='' ">
            and name like concat ('%',#{name},'%')
        </if>
        <if test="job!=null and job!='' ">
            and job = #{job}
        </if>
    </select>

    <!-- 单个模糊-->
    <select id="findMohu" parameterType="String" resultType="user">
        select * from t_user  where name like #{name}
    </select>
</mapper>

题外话:

where 1=1的写法是为了检化程序中对条件的检测

上述例子的两个参数都可能为空, 这时你要构造语句的话,一个个检测再写语句就麻烦

加where 或直接用 and ?,你这里还要对参数是否为空进行检测

用上 where 1=1 之后,就不存在这样的问题, 条件是 and 就直接and ,是or就直接 or

如果不写1=1,那么在每一个不为空的查询条件面前,都必须判断有没有where字句。否则要在第一个出现的地方加where

测试类
InputStream inputStream;
SqlSessionFactory sessionFactory;

@Before
public void before() {
    try {
        inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
 //模糊
 @Test
    public void main9(){
        SqlSession sqlSession = sessionFactory.openSession();
        User user = new User();
        user.setName("V");
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> mohu = mapper.findMohu("%"+user.getName()+"%");
        for (User user1 : mohu) {
            System.out.println(user1);
        }
        sqlSession.close();
    }

    //多个模糊
    @Test
    public void main10(){
        SqlSession sqlSession = sessionFactory.openSession();
        User user = new User();
        user.setName("V");
        user.setJob("A");
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> mohu = mapper.findMohuByNamAndJob(user);
        for (User user1 : mohu) {
            System.out.println(user1);
        }
        sqlSession.close();
    }

在这里插入图片描述

在这里插入图片描述

2 <choose>、<when>、<otherwise>元素

相当于Java中的switch和case语句(多条件分支判断 )

如果遇到下面的场景:

当用户名称不为空,则只根据用户名称进行筛选

当用户名称为空,而用户职业不为空,则只根据用户职业进行用户筛选

当用户名称和用户职业都为空,则要求查询出所有当前在线用户的用户信息

此种情况下,使用if元素进行处理是非常不合适的。如果使用的java语言,这种情况显然更适合使用switch…case…default语句来处理。针对上面情况,MyBatis中可以用choose、when、otherwise元素进行处理。

代码演示
实体类:
package beans.Pojo;

public class User {
    private Integer id;
    private String name;
    private String job;
    private Integer online;

    public User() {
    }

    public User(Integer id, String name, String job,Integer online) {
        this.id = id;
        this.name = name;
        this.job = job;
        this.online=online;
    }

    public User(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public String getJob() {
        return job;
    }

    public void setJob(String job) {
        this.job = job;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getOnline() {
        return online;
    }

    public void setOnline(Integer online) {
        this.online = online;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", job='" + job + '\'' +
                ", online=" + online +
                '}';
    }
}
首先配置 SqlMapConfig.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>
    <!--    核心配置文件-->
    <properties resource="jdbc.properties"></properties>
    <!--配置类型别名-->
    <typeAliases>
<!--        <typeAlias type="beans.Pojo.User" alias="user"></typeAlias>-->
        <package name="beans.Pojo"/>
    </typeAliases>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"></transactionManager>
            <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="beans.dao"></package>
    </mappers>
</configuration>

其中的 jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc\:mysql\://localhost\:3306/···
jdbc.username= ···
jdbc.password= ···

日志 log4j.properties

# Global logging configuration,建议开发环境中要用debug
log4j.rootLogger=DEBUG, stdout
# 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
创建一个接口 UserMapper
public interface UserMapper {
    //多条件分支判断
    List<User> findMohuByNamAndJobByOnline(User user);
}
关联 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">

<!-- parameterType 输入映射
     resultType 和 resultMap 完成输出映射-->
<!-- 与接口相关联-->
<mapper namespace="beans.dao.UserMapper">

    <!-- 多条件分支判断-->
    <select id="findMohuByNamAndJobByOnline" parameterType="user" resultType="user">
        select * from t_user where 1=1
        <choose>
            <when test="name!=null and name!='' ">
            and name like concat ('%',#{name},'%')
            </when>
            <when test="job!=null and job!='' ">
                and job= #{job}
            </when>
            <otherwise>
                <!--不为空 就是在线-->
                and online is not null
            </otherwise>
        </choose>
    </select>
</mapper>

测试

InputStream inputStream;
SqlSessionFactory sessionFactory;

@Before
public void before() {
    try {
        inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

    @Test
    public void main11(){
        SqlSession sqlSession = sessionFactory.openSession();
        User user = new User();
        // name   和   job  在我的设置为空
        user.setName("");
        user.setJob("");
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List<User> online = mapper.findMohuByNamAndJobByOnline(user);
        for (User user1 : online) {
            System.out.println(user1);
        }
        sqlSession.close();
    }

在这里插入图片描述

3.<where>、<trim>元素

上面的 “where 1=1”这种写法对于初学者来将不容易理解,并且也不够雅观。 针对上述情况中“where 1=1”,在MyBatis的SQL中就可以使用<where>或<trim>元素进行动态处理。 将映射文件中的"where 1=1"条件删除 ,并使用where 元素替换后的代码

    <!-- 动态sql if 实现多模糊的效果-->
    <select id="findMohuByNamAndJob" parameterType="user" resultType="user">
        <!-- where 1=1 永为真 防止sql注入-->
        select * from t_user
        <where>
        <if test="name!=null and name!='' ">
            and name like concat ('%',#{name},'%')
        </if>
        <if test="job!=null and job!='' ">
            and job = #{job}
        </if>
        </where>
    </select>

在上述代码中,使用where元素对“where 1=1"条件进行了替换,where元素会自动判断组合条件下拼装的SQL语句,只有where 元素内的条件成立时,才会在拼接SQL中加入where关键字,否则将不会添加

使用 trim 对 “where 1=1” 进行替换

 <!-- 动态sql if 实现多模糊的效果-->
    <select id="findMohuByNamAndJob" parameterType="user" resultType="user">
        <!-- where 1=1 永为真 防止sql注入-->
        select * from t_user
        <trim prefix="where" prefixOverrides="and"> 
        <if test="name!=null and name!='' ">
            and name like concat ('%',#{name},'%')
        </if>
        <if test="job!=null and job!='' ">
            and job = #{job}
        </if>
        </trim>
    </select>

prefx代表的是语句的前缀(这里使用where来连接后面的SQL片段),而prefixOverrides属性代表的是需要去除的那些特殊字符串

4 set元素

一般用来实现单个字段的更新

set元素中,如果遇到了逗号,他会把对应的逗号去掉.注意 因为set元素删除了逗号,当set中的if条件如果有1个以上成立,就会导致sql语法错误

到这里 我就只写接口和接口相关联的xml 以及我们的配置文件了

接口

//更新
void update(User user);

UserMapper.xml

<!-- set 更新-->
<update id="update" parameterType="user">
  update t_user
  <set>
      <if test="name!=null and name!='' ">
          name=#{name},
      </if>
      <if test="job!=null and job!='' ">
          job=#{job},
      </if>
      <if test="online!=null and online!=''">
          online=#{online}
      </if>
  </set>
  where id=#{id}
</update>

测试类

InputStream inputStream;
SqlSessionFactory sessionFactory;

@Before
public void before() {
    try {
        inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

    @Test
    public void main12(){
        SqlSession sqlSession = sessionFactory.openSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        //实体类创建一个有参构造
        User user = new User(1,"dsm","A",1);
        mapper.update(user);
        //提交事务
        sqlSession.commit();
        //关闭资源
        sqlSession.close();
    }

在这里插入图片描述

5.<foreach>元素

foreach元素就相当于java中的for循环语句

它主要的目的还是做批量的操作。比如查询1000条数据中的一百条数据时,就需要使用foreach来提高效率。

接口:(我使用的是把list包进map中)
//根据多个用户id 来查询用户信息
List<User> findByIdsFro(Map map);
UserMapper.xml
    <!-- 根据多个用户id 来查询用户信息-->
    <select id="findByIdsFro" parameterType="map" resultType="user">
        select * from t_user where id in
        <foreach collection="mylist" item="id" index="mylist" open="(" separator="," close=")">
            #{id}
        </foreach>
    </select>
collection:

​ List对象默认用"list"代替作为key键名,数组对象用"array"代替作为key键名,Map对象则是自己声明的key键名,没有默认的。

item

迭代中当前对象(value)的别名,该参数为必选。

index

如果传来的值是list或数组,index是元素的序号,下标。如果是map,index是当前键值队中的key(键名),该参数可选。

open

foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选

separator:

元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。

close:

foreach代码的关闭符号,一般是)和open="("合用。常用在 in(), values() 时。该参数可选。

测试:
InputStream inputStream;
SqlSessionFactory sessionFactory;

@Before
public void before() {
    try {
        inputStream = Resources.getResourceAsStream("SqlMapConfig.xml");
        sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Test
public void test1(){
    SqlSession sqlSession = sessionFactory.openSession();
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    ArrayList<Integer> list = new ArrayList<>();
    list.add(1);
    list.add(2);
    list.add(3);
    Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();
    //注意 map的键 为mylist
    map.put("mylist",list);
    List<User> byIdsFro = mapper.findByIdsFro(map);
    byIdsFro.stream().forEach(System.out::println);
    sqlSession.close();
}

在这里插入图片描述

6<bind>元素

从OGML表达式中创造一个变量,并将其绑定在上下文,常用与模糊查询中

优点是可以防止注入攻击,统一各种数据库系统的格式,比如说:

MySQL先前要使用concat进行模糊查询的拼接

Oracle使用的是"||"。

代码演示:

接口

List<User> findMohu(String name);

UserMapper.xml

<select id="findMohu" parameterType="String" resultType="user">
    <!--name表示他的变量名 与like #{ } 对应-->
		<!--value是值-->
		<!--_parameter是Mybatis内置的参数,代表传入的值-->
		<!--'%'是sql语句中模糊查询的方法,用+号与传入值拼接起来-->
    <bind name="name" value="'%'+_parameter+'%'"/>
    select * from t_user  where name like #{name}
</select>

测试:

@Test
public void main9(){
    SqlSession sqlSession = sessionFactory.openSession();
    User user = new User();
    user.setName("V");
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    List<User> mohu = mapper.findMohu(user.getName());
    mohu.stream().forEach(System.out::println);
    sqlSession.close();
}

在这里插入图片描述

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值