动态SQL

if和where

  • if标签:作为判断入参来使用的,如果符合条件,则把if标签体内的SQL拼接上。
    ==注意:==用if进行判断是否为空时,不仅要判断null,也要判断空字符串。
  • where标签:会去掉条件中的第一个and符号。
<select id="findUserList" parameterType="vo.UserQueryVO" resultType="user">
        SELECT * FROM user
        <where>
            <if test="user != null">
                <if test="user.sex != null and user.sex != ''">
                    sex=#{user.sex}
                </if>
                <if test="user.username != null and user.username != ''">
                    AND username LIKE '%${user.username}%'
                </if>
            </if>
        </where>
</select>

SQL片段

MyBatis提供了SQL片段的功能,可以提高SQL的可重用性。

<!--声明一个SQL片段-->
    <sql id="select_user_where">
        <if test="user != null">
            <if test="user.sex != null and user.sex != ''">
                sex=#{user.sex}
            </if>
            <if test="user.username != null and user.username != ''">
                AND username LIKE '%${user.username}%'
            </if>
        </if>
    </sql>
    <select id="findUserList" parameterType="vo.UserQueryVO" resultType="user">
        SELECT * FROM USER
        <where>
            <!--引用SQL片段-->
            <include refid="select_user_where"/>
        </where>
    </select>

foreach遍历

案例:查询指定id的用户

select * from user where id in (64,65,66);
//定义包装类
package vo;

import model.User;

import java.util.List;

//定义查询包装类,以后.xml的参数从这个对象取
public class UserListQuery {
    private User user;
    private List<Integer> ids;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public List<Integer> getIds() {
        return ids;
    }

    public void setIds(List<Integer> ids) {
        this.ids = ids;
    }
}
<!--UserMapper.xml-->
<select id="findListUser" parameterType="vo.UserListQuery" resultType="user">
     SELECT * FROM USER
     <where>
         <if test="ids != null and ids.size > 0">
             <!--
			collection:集合,写集合属性
			item:遍历接收变量
			open:遍历开始
			close:遍历结束
			separator:拼接格式
			-->
             <foreach collection="ids" item="id" open="AND id in(" close=")" separator=",">
                 ${id}
             </foreach>
         </if>
     </where>
</select>
//测试类
@Test
    public void test4(){
        SqlSession session = ssf.openSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        UserListQuery ulq = new UserListQuery();
        List<Integer> list = new ArrayList<Integer>();
        list.add(64);
        list.add(65);
        list.add(66);
        ulq.setIds(list);
        System.out.println(mapper.findListUser(ulq));
        session.close();
    }

另一种遍历,参数直接传入id集合

<select id="findListUser" parameterType="java.util.List" resultType="user">
        SELECT * FROM USER
        <where>
            <!--如果是直接传入集合参数,则该处的参数名称只能填写list-->
            <if test="list != null and list.size > 0">
                <foreach collection="list" item="id" open="AND id IN (" close=")" separator=",">
                    #{id}
                </foreach>
            </if>
        </where>
</select>
//测试类
@Test
    public void test4(){
        SqlSession session = ssf.openSession();
        UserMapper mapper = session.getMapper(UserMapper.class);
        List<Integer> list = new ArrayList<Integer>();
        list.add(10);
        list.add(16);
        list.add(22);
        System.out.println(mapper.findListUser(list));
        session.close();
    }

MyBatis与Hibernate的区别【面试题】

MyBatis技术特点:

好处

  • 通过直接编写SQL语句,可以直接对SQL进行性能的优化。
  • 学习门槛低,学习成本低。只要有SQL基础,就可以学习MyBatis,而且很容易上手。
  • 由于直接编写SQL语句,所以灵活多变,代码维护性更好。

缺点

  • 不能支持数据库无关性,即数据库发生变更,要写多套代码进行支持,移植性不好。
  • 需要编写结果映射。

Hibernate技术特点:

好处

  • 标准的ORM框架,程序员不需要编写SQL语句。
  • 具有良好的数据库无关性,即数据库发生变化的话,代码无需再次编写。

缺点

  • 学习门槛高,需要对数据关系模型有良好的基础,而且在设置OR映射的时候,需要考虑好性能和对象模型的权衡。
  • 程序员不能自主的去进行SQL性能优化。

MyBatis应用场景:

需求多变的互联网项目,例如电商项目。

Hibernate应用场景:

需求明确,业务固定的项目,例如OA项目、ERP项目等。

关联查询

一对一 resultType实现(扩展类实现

复杂查询时,单表对应的po类已不能满足输出结果集的映射。所以要根据需求建立一个扩展类来作为resultType的类型.

例子

查找某个订单id的信息,包括用户名字和地址。

  • 第一步:写个订单的扩展类
//订单类
package model;

import java.util.Date;

public class Orders {
    private Integer id;
    private Integer user_id;
    private String note;
    private String number;
    private Date createtime;

    public Orders() {
    }

    public Orders(Integer id, Integer user_id, String note, String number, Date createtime) {
        this.id = id;
        this.user_id = user_id;
        this.note = note;
        this.number = number;
        this.createtime = createtime;
    }

    public Integer getId() {
        return id;
    }

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

    public Integer getUser_id() {
        return user_id;
    }

    public void setUser_id(Integer user_id) {
        this.user_id = user_id;
    }

    public String getNote() {
        return note;
    }

    public void setNote(String note) {
        this.note = note;
    }

    public String getNumber() {
        return number;
    }

    public void setNumber(String number) {
        this.number = number;
    }

    public Date getCreatetime() {
        return createtime;
    }

    public void setCreatetime(Date createtime) {
        this.createtime = createtime;
    }

    @Override
    public String toString() {
        return "Orders{" +
                "id=" + id +
                ", user_id=" + user_id +
                ", note='" + note + '\'' +
                ", number='" + number + '\'' +
                ", createtime=" + createtime +
                '}';
    }
}
//订单扩展类
package model;

import java.util.Date;

public class OrdersExt extends Orders{
    private String username;
    private String address;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "OrdersExt{" +
                "username='" + username + '\'' +
                ", address='" + address + '\'' +
                '}'+super.toString();
    }
}
  • 第二步:声明订单接口
package mapper;

import model.OrdersExt;

public interface OrderMapper {
    public OrdersExt findOrderById(int id);
}
  • 第三步:声明订单配置文件
<?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="mapper.OrderMapper">
    <select id="findOrderById" parameterType="int" resultType="model.OrdersExt">
        select
            o.*,u.username,u.address
        from
            orders o ,user u
        where
            o.user_id = u.id
            and u.id= #{id};
    </select>
</mapper>
  • 第四步:加载映射文件
<!--告诉mybatis加载映射文件-->
    <mappers>
        <package name="mapper"/>
    </mappers>
  • 第五步:测试
package test;

import mapper.OrderMapper;
import model.OrdersExt;
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.InputStream;

public class one {
    SqlSessionFactory ssf;
    @Before
    public void setup()throws Exception{
        InputStream is =
                Resources.getResourceAsStream("SqlMapConfig.xml");
        ssf = new SqlSessionFactoryBuilder().build(is);
    }
    @Test
    public void test(){
        SqlSession session = ssf.openSession();
        OrderMapper mapper = session.getMapper(OrderMapper.class);
        OrdersExt res = mapper.findOrderById(10);
        System.out.println(res);
        session.close();
    }
}