Java框架myBatis(二)

news2025/1/11 2:19:07

一、#{}和${}的区别

#{}所采取的时占位符方式(底层是预编译模式),与JDBC中的?方式相同,传参更加方便安全 ,防止了sql注入。当我们需要向sql传值,使用#{};

${}是将内容直接拼接到sql语句中(底层是字符串拼接),一般不用与sql传值。一般用于向sql中动态传递列名 并且在接口处需要通过@Param()进行绑定。其一般用于传列名,可以用于按照某一列排序(select * from表 order by ${列名} desc/asc),或是不确定列的查询(select ${列名} from 表)等操作

区别:

1、底层实现不同: #{}底层是预编译功能,防止sql注入,更加安全

                                ${}}底层是字符串拼接,直接将值拼接到sql中

2、使用场景不同: #{}一般用于向sql中的列传值

                                ${}一般用于向sql中动态传递列名,例如排序时后面列名可改变 

                                                                                        例如select后面的列名可以自由选择

 

二、多表关联查询

 将student表和major表关联         

package com.wbc.myBatisProject.model;

public class Student {
    private int id;
    private String name;
    private int num;
    private String gender;
    private Major major;//建议在学生中关联专业,将专业相关的属性放在major
    //private int id; private String name 需学生类重新把关联的专业属性创建了一遍,太过冗余
    public Major getMajor() {
        return major;
    }

    public void setMajor(Major major) {
        this.major = major;
    }

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}
package com.wbc.myBatisProject.model;

import java.util.List;

public class Major {
    private int id;
    private String name;
    private List<Student> studentList;

    public int getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

studentDao层

package com.wbc.myBatisProject.dao;

import com.wbc.myBatisProject.model.Student;

public interface StudentDao {
    Student getStudentById(int id);
}

student映射

(1)直接多表关联查询出需要的数据

<?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">

<!--namespace需要和接口路径对应-->
<mapper namespace="com.wbc.myBatisProject.dao.StudentDao">
<!--    对关联查询道德学生信息进行自定义封装-->
    <resultMap id="studentMap" type="Student">
        <id column="id" property="id"></id>
        <result column="num" property="num"></result>
        <result column="name" property="name"></result>
        <result column="gender" property="gender"></result>
<!--        映射关联数据 专业名称  首先会创建一个major对象 然后将major对象封装到student对象-->
        <association property="major" javaType="major">
            <result column="mname" property="name"></result>
        </association>
    </resultMap>
    <select id="getStudentById" resultMap="studentMap" >
        select s.id,s.num,s.name,s.gender,m.name mname from student s inner join major m on s.majorid = m.id where s.id = #{id}
    </select>
</mapper>

        在关联查询中通过select标签的resultMap属性绑定结果映射resultMap标签的id属性

        resultMap标签的type属性绑定返回的类型

        id标签的column属性绑定查询的主键 property属性是返回类型Student内部的属性

        result标签用于绑定主键之外的查询值 column和property与id类似

        association标签用于映射关联数据(查询关联表中的数据)property绑定关联的表 javaType表示关联的类,内部通过result标签绑定数据

(2) 先查询主表,再查询关联表

<resultMap id="studentMap1" type="Student">
        <id column="id" property="id"></id>
        <result column="num" property="num"></result>
        <result column="name" property="name"></result>
        <result column="gender" property="gender"></result>
        <association property="major" javaType="Major" select="findMajorById" column="majorid">

        </association>
    </resultMap>
    <select id="getStudentById1" resultMap="studentMap1">
        select id,num,name,gender,majorid from student where id = #{id}
    </select>
<!--    嵌套查询学生关联的专业-->
    <select id="findMajorById" resultType="Major">
        select name from major where id = #{majorid}
    </select>

        通过写两个select标签分别查询student表和major表,association标签中的select属性与查询关联表的select标签中的id属性进行绑定 column与主表中查询出的需要在关联表使用的列进行绑定。

        select中的 resultType属性确定返回类型

(3)查询一对多关联信息

假设我们需要查询专业和专业内选择该专业的所有学生

正常查询需要两个major对象接收结果,而myBatis为我们提供了collection标签为我们解决了这个问题

<?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">

<!--namespace需要和接口路径对应-->
<mapper namespace="com.wbc.myBatisProject.dao.MajorDao">

<!--    查询专业时,可以将多个学生封装到一个集合中-->
    <resultMap id="majorMap" type="major">
        <id column="id" property="id"></id>
        <result property="name" column="name"></result>
<!--        将查询到的多条结果封装到集合-->
        <collection property="studentList" javaType="list" ofType="student">
            <result column="num" property="num"></result>
            <result column="sname" property="name"></result>
        </collection>
    </resultMap>
    <select id="findMajorById" resultMap="majorMap" >
        select m.id,m.name,s.num,s.name sname from major m inner join student s on m.id = s.majorid where m.id = #{id}
    </select>
</mapper>

通过在major类中添加集合属性来接收多个结果

 collection标签中的property属性对应着类中的集合名称,javaType对应着返回的集合类型,offType对应着集合中的泛型

在collection内部通过result标签接收查询结果

(4)一对多关联查询的两次查询

当我们进行分页操作时,一次操作会出现list集合中的数量和实际sql查询数量不一致的情况,这时候需要分两次查询

<!--分两次查询-->
    <resultMap id="majorMap1" type="major">
        <id column="id" property="id"></id>
        <result property="name" column="name"></result>
        <!--        将查询到的多条结果封装到集合-->
        <collection property="studentList" javaType="list" ofType="student" select="findStudents" column="id">
        </collection>
    </resultMap>
    <select id="findMajors1"  resultMap="majorMap1">
        select id,name from major
    </select>
    <select id="findStudents"  resultMap="majorMap1">
        select id,name from student where majorid = #{id}
    </select>
</mapper>

通过在collecetion标签中添加select属性和column属性绑定第二条sql语句并传入参数

 (5)注释方式执行sql

 @Insert("insert into major(naem)values(#{name})")
    void insertMajor(Major major);

    @Select("select id , name from major")
    List<Major> majors();

当sql语句简单时,可以使用注解标签添加sql,但复杂的sql不建议使用注解

一般适用于单张表的简单增删改查 

三、动态sql

动态sql是myBatis一个强大的功能,避免了根据不同条件需要拼接不同字符串的痛苦过程

以Teacher类为例

package com.wbc.myBatisProject.model;

import org.apache.ibatis.annotations.Insert;

public class Teacher {
    private Integer id;
    private String name;
    private Integer num;
    private String gender;

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public Integer getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }
}
package com.wbc.myBatisProject.dao;

import com.wbc.myBatisProject.model.Teacher;

import java.util.List;

public interface TeacherDao {
    List<Teacher> teachers(Teacher teacher);
}

<?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">

<!--namespace需要和接口路径对应-->
<mapper namespace="com.wbc.myBatisProject.dao.TeacherDao">

    <!--
        动态SQL
            可以在sql中添加逻辑判断
            <if>标签中的test属性条件如果返回为true,则执行if标签体,不成立则不执行
            <where>标签 当标签内的if语句有条件成立时,就会动态添加where关键字,如果where关键字后紧跟着的关键字(例如and,or),就会自动删除以保证sql语句语法错误
    -->
    <select id="teachers" resultType="Teacher" >
        select * from teacher
            <where>
                <if test="num!=null">
                    num = #{num}
                </if>
                <if test="name!=null">
                    and name = #{name}
                </if>
                <if test="gender!=null">
                    and gender = #{gender}
                </if>
            </where>

    </select>
</mapper>


        动态SQL可以在sql中添加逻辑判

        <if>标签

标签中的test属性条件如果返回为true,则执行if标签体,不成立则不执行

        <where>标签

当标签内的if语句有条件成立时,就会动态添加where关键字,如果where关键字后紧跟着的关键字(例如and,or),就会自动删除以保证sql语句语法错误

        <trim>标签

同样的,用<trim>同样可以完成这项操作,tirm的功能更加强大,灵活度更高

<!--
    <trim> 标签 当条件判断成立时,可以自定义前缀关键字和后缀关键字
    prefix="where" 添加前缀关键字
    prefixOverrides="and | or"覆盖指定后缀关键字
-->
<select id="teachers" resultType="Teacher" >
        select * from teacher
            <trim prefix="where" prefixOverrides="and | or">
                <if test="num!=null">
                    num = #{num}
                </if>
                <if test="name!=null">
                    or name = #{name}
                </if>
                <if test="gender!=null">
                    and gender = #{gender}
                </if>
            </trim>

    </select>

<choose>标签

并且 if也可以用choose标签替换 choose标签的使用于java中的choose类似

<when>标签

<otherwise>标签        

当我们使用choose标签时,内部必须使用when标签做条件判断,when标签的test属性用于判断条件。otherwise标签相当于else,在choose标签内部至多可以写一个otherwise标签,也可以不写otherwise标签

<!--
    otherwise相当于else 可以不写,最多可以写一个
    但是当使用<choose>标签时,必须在标签体内写<when>表签 when标签的test属性用于判断条件是否成立
-->
    <select id="teachers" resultType="Teacher" >
        select * from teacher
            <trim prefix="where" prefixOverrides="and | or">
                <choose >
                    <when test="name!=null">
                        name=#{name}
                    </when>
                    <otherwise>
                        name="李老师"
                    </otherwise>
                </choose>
            </trim>

    </select>

  <set>标签

当我们需要用if等选择标签进行列名拼接时,会出现最后一位仍有逗号的情况。原因是如果最后一位没有达成if标签中的条件时,其他位作为最后一位会将原本的逗号带着拼接进sql语句。而set标签就可以解决这一问题,它可以把最后一个逗号去掉

<!--set去逗号-->
    <!--当每次拼接后需要逗号连接,但有可能前面的不符合条件不执行 set标签可以把最后一个,删除,以保证语法正确-->
    <!--当然set标签也可以用item代替-->
    <update id="updateTeacher" parameterType="Teacher" >
        update teacher
           <set>
               <if test="num!=null">
                   num=#{num},
               </if>
               <if test="name!=null">
                   name=#{name},
               </if>
               <if test="gender!=null">
                   gender=#{gender},
               </if>
           </set>
        <where>
            id = #{id}
        </where>
    </update>

      测试

 @Test
    public void test1(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        TeacherDao teacherDao = sqlSession.getMapper(TeacherDao.class);
        Teacher teacher = new Teacher();
        teacher.setId(1);
        teacher.setName("陈老师");
        teacher.setNum(1004);
        teacherDao.updateTeacher(teacher);
        sqlSession.commit();
        sqlSession.close();
    }

 传入的参数teacher没有调用setGender方法设置gender,在调用gender时gender=null不符合if条件,此时name是set标签中最后的需要拼接的元素,此时set自动将逗号去掉了,保障了语法的正确性 

<foreach>标签 

foreach标签的作用是循环

此处我们假设两个示例

第一个是我们的批量删除,如果我们每次删除时前端请求一次,将id发送给后端,后端再调用sql删除,是否太过麻烦。有了foreach之后,我们可以一次性拿到所有要删除事物的id发给后端,后端将其传入数组或List集合,将其传入dao层映射的方法中,通过foreach标签循环调用sql,完成批量删除的操作

假设1、2、3是需要批量删除的老师的id 通过数组传输

 @Test
    public void test2(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        TeacherDao teacherDao = sqlSession.getMapper(TeacherDao.class);
       teacherDao.deleteTeacher(new Integer[]{1,2,3});
        sqlSession.commit();
        sqlSession.close();
    }

dao层接口通过此方法映射给对应的Mapper 

List<Teacher> findTeacher(List<String> columns);

从而调用这条sql

 <!-- foreach标签循环 collection是传参类型 传入数组时等于array 传入List则等于list-->
    <!--item 表示增强for循环中的每次循环取出的值  open是循环开始时需要拼接的 separator是传入参数后拼接的  close是结束时需要拼接的-->
    <delete id="deleteTeacher">
        delete from teacher  where id in
               <foreach item="id" collection="array" open="(" separator="," close=")">
                   #{id}
               </foreach>
    </delete>

foreach 标签中,collection="传入数据的类型"(数组填array,集合填list)

                           item=”每次从数组或集合中取出的数据的别名“(随便起一个名字)

                           open=”循环开始前需要拼接的符号“

                           separator=”每次循环传入数据后需要拼接的符号“

                            close=”循环结束需要拼接的符号“                           

第二个例子是我们在前端通过标签筛选想要看到的东西,前端拿到这些标签传入后端,后端再根据传入的数据调取数据库数据返回前端,也需要我们通过foreach循环拼接列名

 @Test
    public void test3(){
        SqlSession sqlSession = MyBatisUtil.getSqlSession();
        TeacherDao teacherDao = sqlSession.getMapper(TeacherDao.class);
        List<String> columns = new ArrayList<>();
        columns.add("num");
        columns.add("name");
        columns.add("gender");
        teacherDao.findTeacher(columns);
        sqlSession.commit();
        sqlSession.close();
    }

 这里由于sql语句不需要在循环前拼接,所以没有写 open属性和close属性

由于传入的是列名,所以不可以用#{xxx}传输,需要用¥{xxx}传输

<select id="findTeacher" resultType="Teacher">
        select
            <foreach collection="list" item="column" separator=",">
                ${column}
            </foreach>
            from teacher
    </select>

自此,全部的动态sql学习完毕

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2076113.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Uniapp 微信小程序,实现页面滚动Tab悬停吸顶,点击tab内容跟随滚动

Uniapp 微信小程序&#xff0c;实现页面滚动Tab悬停吸顶&#xff0c;点击tab内容跟随滚动 页面股东tab悬停原理&#xff1a; 运用uniapp原生提供方法uni.createSelectorQuery()获取滚动对应节点的信息&#xff0c;即节点距离页面顶部的距离&#xff0c;再通过uniapp原生监听页…

【C语言】深入理解指针(一)

指针1 1.内存和地址2.指针变量和地址2.1取地址操作符&#xff08;&&#xff09;2.2指针变量和将引用操作符2.3解引用操作符2.4指针变量的大小 3.指针变量类型的意义3.1指针变量类型3.2void*指针 4.const修饰指针5.指针运算5.1 指针- 整数5.2指针-指针3.指针的关系运算 6.野…

《高等代数》最大公因式典型例题

说明&#xff1a;此内容用于本人复习巩固&#xff0c;如果也能帮助到大家那就更加有意义了。 注&#xff1a;这道题主要从 1)公因式整除多项式的线性组合 2)最大公因式能够被其它公因式整除 3)如果两个多项式互相整除&#xff0c;那就说明这两个多项式相等 这三个知识点出…

Hadoop的HA配置与实现(ZooKeeper)

目录 一、Hadoop的HA架构二、配置实现Hadoop的HA三、效果 一、Hadoop的HA架构 集群规划 112&#xff1a;NameNode1 ResourceManager1 JournalNode1 113&#xff1a;NameNode2 ResourceManager2 JournalNode2 114&#xff1a;DataNode1 NodeManager1 115&#xff1a;DataNode2 N…

如何快速建30个文件夹

文件夹的快速新建只能通过专门的软件来实现&#xff0c;快速建30个&#xff0c;我们可以使用批处理命令&#xff0c;也可以用第三方软件&#xff0c;批处理的命令&#xff0c;需要我们熟悉如何编写&#xff0c;而第三方软件的话不需要那么多的知识&#xff0c;直接在软件上一键…

货运搬家小程序app定制开发过程中需要的主要功能介绍

货运搬家小程序是一个集成了物流服务全过程的数字化解决方案&#xff0c;它通过移动平台提供注册与登录、货物管理、车辆管理、路线规划、货物分配、订单管理、实时追踪、评价与反馈、价格透明等功能。 具体的功能&#xff1a; 注册与登录用户可以通过小程序注册账号并登录&am…

inflight 守恒算法的实现和仿真

前面介绍过&#xff0c;只要某条流的 inflt 在 bdp 之外再增加一个相等的余量 I&#xff0c;即 inflt bdp I&#xff0c;比如 I 2&#xff0c;I 3&#xff0c;…&#xff0c;就一定会收敛到公平&#xff0c;且不会占据过多 buffer&#xff0c;因此 rtt 不会膨胀&#xff0c…

html+css网页设计 动漫 海贼王14个页面

htmlcss网页设计 动漫 海贼王14个页面 网页作品代码简单&#xff0c;可使用任意HTML编辑软件&#xff08;如&#xff1a;Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad 等任意html编辑软件进行运行及修改编辑等操作&#xff09;。 获取源码 1&#x…

开放式耳机对耳朵好吗?开放式耳机哪个品牌好?

许多人在选择开放式耳机时并不了解如何选购。对开放式耳机也不是很了解&#xff0c;所以我在这里做个简单的科普和分享。今天跟大家聊聊开放式耳机会伤害耳朵吗&#xff1f;开放式耳机有什么好处&#xff1f;等等&#xff0c;下面一起来看看吧~ 开放式耳机是什么意思&#xff1…

如何有效激活微信陌生客户:加好友后的沟通策略!

在当今这个数字化时代&#xff0c;微信已成为我们与客户建立联系的重要桥梁。对于许多企业和个人而言&#xff0c;成功添加陌生客户到微信列表只是第一步&#xff0c;真正的挑战在于如何有效激活这些潜在客户&#xff0c;转化为实际交易或长期关系。 下面分享一些沟通策略&…

oracle ONS configuration failed NoserversAvailable:Subscription time out导致应用起不来

java.lang.IllegalArgumentException:ONS configuration failed Caused by: oracle.ons.NoserversAvailable:Subscription time out ##已部署到服务器解决方案&#xff1a; 修改这个2个jar包后缀 ##在项目工程里面&#xff0c;<artifactId>ojdbc8</artifactId> m…

具有强制函数的物理信息神经网络

图片由 agsandrew 在 iStock 上发布 一、说明 在物理学、数学、经济学、工程学和许多其他领域&#xff0c;微分方程根据变量的导数来描述函数。简而言之&#xff0c;当涉及一个变量相对于其他变量的变化率时&#xff0c;你可能会找到一个微分方程。许多示例描述了这些关系。微分…

debian12 - install and config telnet

文章目录 debian12 - install and config telnet概述笔记配置文件END debian12 - install and config telnet 概述 前面实验&#xff0c;在xinetd中指定telnet服务&#xff0c;查看状态时&#xff0c;看到telnet服务bind失败。 直接从其他计算机来连telnet又是正常的&#xf…

随记-部署flink-1.16.3、jdk-11.0.19、zookeeper-3.4.13、kafka_2.12-2.2.2

一、部署flink-1.16.3、jdk-11.0.19、zookeeper-3.4.13、kafka_2.12-2.2.2 #软件下载 https://archive.apache.org/dist/kafka/2.2.2/kafka_2.12-2.2.2.tgz https://archive.apache.org/dist/zookeeper/zookeeper-3.4.13/zookeeper-3.4.13.tar.gz https://archive.apache.org/…

Clustering-Guided Class Activation for WeaklySupervised Semantic Segmentation

pdf&#xff1a;https://ieeexplore.ieee.org/stamp/stamp.jsp?tp&arnumber10381698 code&#xff1a;https://github.com/DCVL-WSSS/ClusterCAM 摘要&#xff1a; 基于transformer的弱监督语义分割(WSSS)方法利用其捕获全局上下文的强大能力得到了积极的研究。然而&am…

day8JS-作用域

1. 变量的作用域(变量函数) 作用域是变量的可作用范围&#xff0c;变量只有在自己的作用域下才会生效。 函数会产生作用域&#xff0c;在函数内定义的变量只能在函数内使用。 2. 作用域分类 局部作用域&#xff1a; 函数内定义的变量和形参的作用域就是局部作用域&#xff1b;这…

【Hot100】LeetCode—207. 课程表

目录 1- 思路有向图记录入度数组出度列表 2- 实现⭐207. 课程表——题解思路 3- ACM 实现 题目连接&#xff1a;207. 课程表 1- 思路 有向图记录入度数组出度列表 根据输入① 构造遍历构造入度数组② 构造出度列表根据入度数组为 0 的数 加入到 队列中&#xff0c;进行处理 2…

在线拼图用什么软件?5款顶级照片拼接工具

照片拼接在一起用什么软件&#xff1f;当你想全景展现山西应县木塔的震撼之美时&#xff0c;5款精选照片拼接软件能帮你解锁全新视角。 这座千年古塔&#xff0c;巍峨耸立&#xff0c;细节之处尽显匠心独运。而通过拼接技术&#xff0c;每一块木构的精致、每一层塔檐的飞翘都能…

OpenBayes 教程上新 | 青岛小哥焦恩俊版二郎神来袭,MuseV + MuseTalk 分分钟实现高质量数字人制作!

使用传统的数字人训练方案生成一个高质量的数字人&#xff0c;常常需要大量的时间和算力资源&#xff0c;同时对训练素材的要求也较高&#xff0c;如果想要达到良好的唇形一致效果&#xff0c;通常需要数小时乃至更久。 MuseV 和 MuseTalk 的出现为数字人领域带来了新的突破&a…

【Canvas与桌面】十字网格黑灰背景(1920x1080)

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>十字网格黑灰背景(1920x1080)</title><style type"te…