MyBatis 之 面向接口编程的各参数的具体详解

使用getMapper()方法实现面向接口编程

JsrDao jsrDao = SqlSessionUtil.getSession().getMapper(JsrDao.class);

组织架构:
在这里插入图片描述

数据表

在这里插入图片描述
重点:
mapper文件里面的select标签的id值必须和接口里面的方法名称一致
mapper文件的命名空间必须是包名.接口名的形式,如:

<mapper namespace="com.mybatis_03.dao.JsrDao">
    ...
</mapper>
  • 接口文件 JsrDao.java
package com.mybatis_03.dao;

import com.mybatis_03.domain.Jsr;
import com.mybatis_03.domain.pageParams;
import com.mybatis_03.vo.StuClassVo;
import org.apache.ibatis.annotations.Param;

import java.util.List;
import java.util.Map;

/**
 * @author Nigori
 * @date 2020/2/1
 **/
public interface JsrDao {

    List<Jsr> getAll();
    public void save(Jsr j);
    void update(Jsr j);
    void delete(String a006);
    
    /* 省略代码在下方分类中 */
}

  • 映射文件 JsrDao.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映射文件-->
<mapper namespace="com.mybatis_03.dao.JsrDao">

    <select id="getAll" parameterType="String" resultType="Jsr">
        select * from tb_jsr
    </select>

    <insert id="save">
        insert into tb_jsr(id,name,sex,age,tel,num,classroom) values(#{id},#{name},#{sex},#{age},#{tel},#{num},#{classroom})
    </insert>

    <update id="update">
        update tb_jsr set name = #{name},sex = #{sex},age = #{age},tel = #{tel},num = #{num},classroom = #{classroom} where id = #{id}
    </update>

    <delete id="delete">
        delete from tb_jsr where id = #{id}
    </delete>
    
    ...
    <!-- 为方便直观体现知识点的不同之处,省略代码在下方分类写 -->

</mapper>
  • 测试类 Test_03.java
package com.mybatis_03.test_03;

import com.mybatis_03.dao.JsrDao;
import com.mybatis_03.domain.Jsr;
import com.mybatis_03.util.SqlSessionUtil;
import com.mybatis_03.vo.StuClassVo;

import java.util.List;

/**
 * @author Nigori
 * @date 2020/2/9
 **/
public class Test_03 {

    public static void main(String[] args) {
        JsrDao jsrDao = SqlSessionUtil.getSession().getMapper(JsrDao.class);
        
        //查询所有
        /*List<Jsr> j = jsrDao.getAll();
        System.out.println(j);*/

        //添加操作
        /*Jsr j = new Jsr();
        j.setId("A009");
        j.setName("tly");
        j.setSex("女");
        j.setAge(29);
        j.setTel("159******");
        j.setNum("459643");
        j.setClassroom("B003");
        jsrDao.save(j);
        SqlSessionUtil.mybCommit(SqlSessionUtil.getSession());
        SqlSessionUtil.mybClose(SqlSessionUtil.getSession());*/

        //修改操作
        Jsr j = new Jsr();
        j.setId("A003");
        j.setName("out");
        j.setSex("女");
        j.setAge(29);
        j.setTel("133******");
        j.setNum("459789");
        j.setClassroom("B003");
        jsrDao.update(j);
        SqlSessionUtil.getSession().commit();
        SqlSessionUtil.mybClose(SqlSessionUtil.getSession());

        //删除操作
        /*jsrDao.delete("A005");
        SqlSessionUtil.mybCommit(SqlSessionUtil.getSession());
        SqlSessionUtil.mybClose(SqlSessionUtil.getSession());*/

        ...
        /* 省略代码在下方分类中 */
        
    }
}

  • 工具类 SqlSessionUtil.java
package com.mybatis_03.util;

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;

/**
 * @author Nigori
 * @date 2020/2/1
 **/
public class SqlSessionUtil {

    private SqlSessionUtil(){}
    private static SqlSessionFactory sqlSessionFactory;
    static{
        String resource = "mybatis-config.xml";
        InputStream inputStream = null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            e.printStackTrace();
        }
        sqlSessionFactory =  new SqlSessionFactoryBuilder().build(inputStream);
    }

    /*
         处理同一个事务,使用同一个SqlSession对象,ThreadLocal是线程存储类
         所以,ThreadLocal作用为第一次使用SqlSession对象时是创建并存放的过程,后面使用SqlSession对象时为获取的过程
     */
    private static ThreadLocal<SqlSession> t = new ThreadLocal<SqlSession>();

    //取得SQLSession对象
    public static SqlSession getSession(){
        SqlSession session = t.get();
        if(session==null){
            session = sqlSessionFactory.openSession();
            t.set(session);
        }
        return session;
    }

    //提交事务
    public static void mybCommit(SqlSession session){
        if(session!=null){
            session.commit();
        }
    }

    //关闭SQLSession对象
    public static void mybClose(SqlSession session){
        if(session!=null){
            session.close();
            //必须加,作用:剥离ThreadLocal中保存的SqlSession...[原因:线程池]
            t.remove();
        }
    }
}

  • pageParams.java
package com.mybatis_03.domain;

/**
 * @author Nigori
 * @date 2020/2/10
 **/
public class pageParams {

    private int start;
    private int limit;

    public int getStart() {
        return start;
    }

    public void setStart(int start) {
        this.start = start;
    }

    public int getLimit() {
        return limit;
    }

    public void setLimit(int limit) {
        this.limit = limit;
    }
}

  • StuClassVo.java
package com.mybatis_03.vo;

/**
 * @author Nigori
 * @date 2020/2/12
 **/
public class StuClassVo {

    private String cla;
    private String sid;
    private String teacher;

    private String jsid;
    private String name;
    private String sex;
    private int age;
    private String tel;
    private String num;
    private String classroom;

    @Override
    public String toString() {
        return "StuClassVo{" +
                "cla='" + cla + '\'' +
                ", sid='" + sid + '\'' +
                ", teacher='" + teacher + '\'' +
                ", jsid='" + jsid + '\'' +
                ", name='" + name + '\'' +
                ", sex='" + sex + '\'' +
                ", age=" + age +
                ", tel='" + tel + '\'' +
                ", num='" + num + '\'' +
                ", classroom='" + classroom + '\'' +
                '}';
    }
    
    ...
    /* setter and getter */
}

 
 

参数传递类型 parameterType

<select id="select" parameterType="" resultType="">
    ...
</select>

一、传递单参数(简单数据类型)

parameterType:

java.lang.String 改为 string / String / parameterType 不写,均可以【原因:Mybatis默认设置了别名】

使用简单类型为参数:在 #{ } 中的标识符可以随便写,但还是要有意义【{ } 中为形参】

1、使用简单数据类型(8基本数据类型+String),String

Jsr j = jsrDao.select1("A003");
System.out.println(j);
Jsr select1(String a003);   //接口
<select id="select1" parameterType="string" resultType="Jsr">
    select * from tb_jsr where id = #{id}
</select>

2、使用简单数据类型(8基本数据类型+String),int

List<Jsr> jList = jsrDao.select2(25);
for(Jsr j:jList) {
    System.out.println(j);
}
List<Jsr> select2(int i);   //接口
<select id="select2" parameterType="int" resultType="Jsr">
    select * from tb_jsr where age = #{age}
</select>

二、传递多参数

/*  绝对不可以同时为SQL语句传递多个参数,          【测试 3 失败】  */

// 3、测试:parameterType 【需求:姓名为kpo,年龄为25】
// List<Jsr> jList = jsrDao.select3("kpo",25);

//List<Jsr> select3(String kpo, int i);   //错误接口

<!--<select id="select3" parameterType="String int" resultType="Jsr">
    select * from tb_jsr where name = #{name} and age = #{age}
</select>-->

为SQL语句传递多个参数 【需求:姓名为kpo,年龄为25】

4、使用domain(POJO / Java Bean)为参数

jj 参数为一个 domain 引用类型,那么 #{ } 中的标识符必须是 domain 类的属性名

Jsr jj = new Jsr();
jj.setName("kpo");
jj.setAge(25);
List<Jsr> jList = jsrDao.select4(jj);
for(Jsr j:jList) {
    System.out.println(j);
}
List<Jsr> select4(Jsr jj);   //接口
<select id="select4" parameterType="Jsr" resultType="Jsr">
    select * from tb_jsr where name = #{name} and age = #{age}
</select>

5、使用 map 为参数

参数类型为 map 类型,那么 #{ } 中的标识符必须是 map 的 key

Map<String,Object> map = new HashMap<String, Object>();
map.put("name","kpo");
map.put("age",25);
List<Jsr> jList = jsrDao.select5(map);
for(Jsr j:jList) {
    System.out.println(j);
}
 List<Jsr> select5(Map<String, Object> map);   //接口
<select id="select5" parameterType="map" resultType="Jsr">
    select * from tb_jsr where name = #{name} and age = #{age}
</select>

10、使用 注解方式 传递多个参数

List<Jsr> jList = jsrDao.select10("kpo",25);
for(Jsr j:jList) {
    System.out.println(j);
}
List<Jsr> select10(@Param("name") String kpo, @Param("age") int i);
<select id="select10" resultType="Jsr">
    select * from tb_jsr where name = #{name} and age = #{age}
</select>

12、使用 混合模式 传递多个参数

Jsr jj = new Jsr();
jj.setName("kpo");
jj.setAge(25);
pageParams p = new pageParams();
p.setLimit(1);
p.setStart(0);
List<Jsr> jList = jsrDao.select12(jj,p);
for(Jsr j:jList) {
    System.out.println(j);
}
List<Jsr> select12(@Param("params") Jsr jj, @Param("page") pageParams p);
<select id="select12" resultType="Jsr">
    select * from tb_jsr where name = #{params.name} and age = #{params.age} limit #{page.start}, #{page.limit}
</select>

总结:
在实际开发项目中,使用 domain 引用类型(Java Bean),map集合类型,注解,混合模式都可以为SQL语句同时传递多个参数

  • 一般情况(参数个数 > 5个),使用domain就可以;
  • (参数个数 < 5个),使用注解方式;
  • map尽量不使用,因为业务可读性丧失,后期扩展和维护性差;
  • 使用混合模式时,要明确参数的合理性。

例子:(domain使用不了)需求:查询姓名为kpo,班级为一年一班学员详细情况。 [原因:s表没有id,c表没有classroom]

 select * from tb_student s join tb_classroom c on s.classroom = c.id where s.name = #{name} and c.name = #{name}

三、模糊查询和#{ }与${ }区别

6、SQL语句使用 ${ } 拼接

Jsr j = jsrDao.select6("A004");
System.out.println(j);
Jsr select6(String a004);
<select id="select6" resultType="Jsr">
    select * from tb_jsr where id = '${value}'
</select>

7、like模糊查询,使用 ${ }

List<Jsr> jList = jsrDao.select7("i");
for(Jsr j:jList) {
    System.out.println(j);
}
List<Jsr> select7(String i);
<select id="select7" resultType="Jsr">
    select * from tb_jsr where name like '%${value}%'
</select>

8、like模糊查询,使用 #{ } 占位,【"%i%"】

List<Jsr> jList = jsrDao.select8("%i%");
for(Jsr j:jList) {
    System.out.println(j);
}
List<Jsr> select8(String i);
<select id="select8" resultType="Jsr">
    select * from tb_jsr where name like #{name}
</select>

9、like模糊查询,使用 #{ } 占位,【like ‘%’ #{name} ‘%’】

List<Jsr> jList = jsrDao.select9("i");
for(Jsr j:jList) {
    System.out.println(j);
}
List<Jsr> select9(String i);
<select id="select9" resultType="Jsr">
    <!-- 注意'%' #{name} '%'中的空格 -->
    select * from tb_jsr where name like '%' #{name} '%'
</select>

总结:
必须使用 ${ } 的情况

  • i:需要动态拼接表名 select * from ${table_name}
  • ii:动态拼接排序字段 select * from table_name order by ${username}
     

返回值类型 resultType

<select id="select" parameterType="" resultType="">
    ...
</select>

一、返回简单数据类型

13、返回String类型 【需求:查询id为A004的姓名】

String name = jsrDao.select13("A004");
System.out.println(name);
String select13(String a004);
<select id="select13" resultType="String">
    select name from tb_jsr where id = #{id}
</select>

14、返回String类型 【需求:查询所有人的姓名】

List<String> stringList = jsrDao.select14();
for(String name_1:stringList){
    System.out.println(name_1);
}
List<String> select14();
<select id="select14" resultType="String">
    select name from tb_jsr
</select>

15、返回int类型 【需求:查询一共有多少条记录】

int count = jsrDao.select15();
System.out.println(count);
int select15();
<select id="select15" resultType="int">
    select count(*) from tb_jsr
</select>

二、返回domain引用类型 (POJO)

16、返回domain引用类型 Jsr

代码省略

解析返回值为domain(Jsr)的:

* 解析返回值为Jsr的:
*     <select id="select" resultType="Jsr">
*         select * from tb_jsr
*     <select/>
*
*     以上返回的是List<Jsr>集合
*     当执行了Sql语句后,通过查询得到结果:id,name,tel,age...
* 
* 具体工作:
*1)根据返回值类型,自动创建该类型对象,由该对象将查询结果封装
*     Jsr j1 = new Jsr();
*     j1.setId("A001");
*     j1.setName("lx");
*     ...
*
*2)当查询出第二条记录,继续做操作(1*     Jsr j2 = new Jsr();
*     j2.setId("A001");
*     j2.setName("lx");
*     ...
*
*     ...
*
*     (n)重复以上步骤,直至查询结束(多条记录封装成多个返回值类型的对象)
*
*     最后,MyBatis系统自动创建List集合保存这些对象
*     List<Jsr> jList = new ArrayList<>();
*     jList.add(j1);
*     jList.add(j2);
*     ...
*     jList.add(jn);
*

三、返回Map类型

17、返回map类型

使用 domain 无法进行查询结果封装时,使用map返回结果

为什么无法封装?
原因:SQL查询的结果集中的某些属性在 domain 中不存在,例如根据 name 统计表的记录条数count就不在 domain 中

List<Map<String,Object>> mapList = jsrDao.select17();
    for(Map<String,Object> map:mapList){
        Set<String> set = map.keySet();
        for (String key:set) {
            System.out.println("key:"+key);
            System.out.println("value:"+map.get(key));
        }
        System.out.println("----------------------");
    }
List<Map<String, Object>> select17();
<select id="select17" resultType="map">
    select * from tb_jsr
</select>

解析返回值为map的:

 * 解析返回值为map的:
*     <select id="select" resultType="map">
*         select * from tb_jsr
*     <select/>
*     以上返回的是List<Map<String,Object>>集合
*     当执行了Sql语句后,通过查询得到结果:id,name,tel,age...
* 
* 具体工作:
*1)根据返回值类型,自动创建该类型对象,由该对象将查询结果保存起来
*     Map<String,Object> map1 = new HashMap<>();
*     map1.put("id","A001");
*     ...
*
*2)当查询出第二条记录,继续做操作(1*     Map<String,Object> map2 = new HashMap<>();
*     map2.put("id","A002");
*     ...
*
*     ...
*
*     (n)重复以上步骤,直至查询结束(多条记录封装成多个map对象)
*
*     最后,MyBatis系统自动创建List集合保存这些map对象
*     List<Map<String,Object>> mapList = new ArrayList();
*     mapList.add(map1);
*     ...
*     mapList.add(mapn);

四、当查询的字段名与POJO(domain)属性名不一致时解决方法

【方式一:给字段起别名】

List<Jsr> jList = jsrDao.select18();
for(Jsr j:jList){
    System.out.println(j);
}
List<Jsr> select18();
<select id="select18" resultType="Jsr">
    select id,fullname as name,sex,age,tel,num,classroom from tb_jsr
</select>

【方式二:resultMap】
resultMap 作用:定义映射规则(SQL 到 Java Bean)

List<Jsr> jList = jsrDao.select19();
for(Jsr j:jList){
    System.out.println(j);
}
List<Jsr> select19();
<!--
    id:resultMap标签对的唯一标识

    type:指定一个类型,与数据库表一一对应,建立起表字段和类属性的名字一一匹配的关系(可以是POJO全路径)
-->
<resultMap id="jsMap" type="Jsr">
    <!--
        id标签:用来配置主键的对应关系
        result标签:用来配置普通字段的对应关系

        property属性:配置的是类中的属性名
        column属性:配置的是表中的字段名
    -->
    <id property="id" column="id"/>
    <result property="name" column="fullname"/>
    <result property="sex" column="sex"/>
    <result property="age" column="age"/>
    <result property="tel" column="tel"/>
    <result property="num" column="num"/>
    <result property="classroom" column="classroom"/>
</resultMap>

<select id="select19" resultMap="jsMap">
    <!-- 
        “ * ”代表:id,fullname,sex,...
        过程:fullname ===> column的fullname,然后返回给property的name里
    -->
    select * from tb_jsr
</select>

 

分页参数 RowBounds

RowBounds 分页适用于小数据量查询。在映射文件中不需要配置 RowBounds 参数,MyBatis 自动识别。

原理:执行 SQL 查询后,按照偏移量(offset)和 限制条数(limit)返回查询结果。

RowBounds rowBounds = new RowBounds(0,20);
List<Jsr> jList = jsrDao.select26("kpo",20,rowBounds);
System.out.println(jList.size());
List<Jsr> select26(@Param("name") String name, @Param("age") int age,RowBounds rowBounds);
<select id="select26" resultType="Jsr">
    select * from tb_jsr where name = #{name} and age = #{age}
</select>

 

动态SQL+SQL片段

一、动态SQL

27、if 标签 【根据tel查数据】
适用于选填条件的查询,参数不为空时,根据条件查询,为空时,全查询。
test 属性:判断的条件

List<Jsr> jList = jsrDao.select27("6");
for(Jsr j:jList) {
    System.out.println(j);
}
List<Jsr> select27(String s);
<select id="select27" parameterType="String" resultType="Jsr">
    select * from tb_jsr where 1=1
    <!--适用于选填条件的查询,参数不为空时,进行模糊查询-->
    <if test="tel != null and tel != ''">
        and tel like concat('%',#{tel},'%')
    </if>
</select>

20、where 标签 + if 标签
对 If 标签的改进(即:没有 1=1)

Jsr jj = new Jsr();
jj.setName("i");
//jj.setTel("1");
jj.setAge(25);
List<Jsr> jList = jsrDao.select20(jj);
for(Jsr j:jList){
System.out.println(j);
}
List<Jsr> select20(Jsr jj);
<select id="select20" resultType="Jsr">
    select * from tb_jsr
    <!--
        where标签:
                  使用where标签时必须搭配where标签对中的if标签来使用

                  where标签会自动屏蔽第一个连接符 and/or
    -->
    <where>
        <if test="name!=null and name!=''">
            and name like '%' #{name} '%'
        </if>
        <if test="tel!=null and tel!=''">
            and tel like '%' #{tel} '%'
        </if>
        <if test="age!=null">
            and age = #{age}
        </if>
    </where>
</select>

28、choose + when + otherwise 标签
相当于 switch…case…default…

List<Jsr> jList = jsrDao.select28(null,null,"56");
for(Jsr j:jList){
    System.out.println(j);
}
List<Jsr> select28(@Param("name") String lx,@Param("age") Integer i,@Param("tel") String s);
<select id="select28" resultType="Jsr">
        select * from tb_jsr
        <where>
            <choose>
                <when test="name != null and name != ''">
                    and name like concat('%',#{name},'%')
                </when>
                <when test="age != null and age != ''">
                    and age = #{age}
                </when>
                <otherwise>
                    and tel like concat('%',#{tel},'%')
                </otherwise>
            </choose>
        </where>
    </select>

29、set 标签
逗号必须添加,最后一个逗号会默认删除

Jsr jsr = new Jsr();
jsr.setId("A003");
jsr.setAge(26);
jsr.setTel("169******");
int num = jsrDao.update29(jsr);
if (num > 0) {
    SqlSessionUtil.mybCommit(SqlSessionUtil.getSession());
}else {
    SqlSessionUtil.getSession().rollback();
}
int update29(Jsr jsr);
<update id="update29" parameterType="jsr">
    update tb_jsr
    <set>
    <!--逗号必须添加,最后一个逗号会默认删除-->
        id = #{id},
        <if test="age != null and age != ''">
            age = #{age},
        </if>
        <if test="tel != null and tel != ''">
            tel = #{tel},
        </if>
    </set>
    where id = #{id}
</update>

30、trim 标签
prefix:前缀,表示向前添加内容 ;prefixOverrides:从前面删除内容
suffix:后缀,表示向后添加内容 ;suffixOverrides:从后面删除内容

Jsr jsr = new Jsr();
jsr.setId("A003");
jsr.setAge(26);
jsr.setTel("132******");
int num = jsrDao.update30(jsr);
if (num > 0) {
    SqlSessionUtil.mybCommit(SqlSessionUtil.getSession());
}else {
    SqlSessionUtil.getSession().rollback();
}
int update30(Jsr jsr);
<update id="update30" parameterType="jsr">
    update tb_jsr
    <trim prefix="set" prefixOverrides="," suffix="where" suffixOverrides="abc">
        ,id = #{id},age = #{age},tel = #{tel}abc
    </trim>
    id = #{id}
    </update>

21、foreach 标签
用来遍历传递来的数组参数

collection属性:标识传递参数的类型 【array:数组,list:集合】
item属性:每一次遍历出来的元素,在使用该元素时,需要套用在 #{ } 中
index属性:当前元素在集合的位置下标
open属性:拼接循环的开始符号
close属性:拼接循环的结束符号
separator属性:元素与元素之间的分隔符

String str[] = {"A001","A002","A004"};
List<Jsr> jList = jsrDao.select21(str);
for(Jsr j:jList){
    System.out.println(j);
}
List<Jsr> select21(String[] str);
<select id="select21" resultType="Jsr">
    select * from tb_jsr where id in
    <foreach collection="array" item="id" open="(" close=")" separator=",">
        #{id}
    </foreach>
</select>

31、bind 标签

List<Jsr> jList = jsrDao.select31("6");
for(Jsr j:jList){
    System.out.println(j);
}
List<Jsr> select31(String s);
<select id="select31" resultType="jsr">
    select * from tb_jsr
    <where>
        <if test="tel != null and tel != ''">
        <bind name="tel" value="'%'+ tel +'%'"/>
            and tel like #{tel}
        </if>
    </where>
</select>
二、SQL片段

22、SQL片段 【根据id查单条】

Jsr jj = jsrDao.select22("A003");
System.out.println(jj);
Jsr select22(String a003);
<!--
    在实际项目开发中,使用SQL片段来代替重复率高,且复杂的子查询
-->
<sql id="sq22">
    select * from tb_jsr
</sql>
<select id="select22" resultType="Jsr">
     <include refid="sq22"/> where id=#{id};
</select>

 

级联 + 缓存 + 存储过程

MyBatis 之 级联 + 缓存 + 存储过程

 
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值