Mybatis框架

Mybatis框架
        Mybatis的含义:Mybatis框架是一个持久层框架,几乎解决了jdbc代码在手动设置参数和对结果集的手动获取问题,原本是apache公司的开源项目,最后转给Google公司。Mybatis会将参数封装在一个对象中传递给数据库,并将sql语句执行后的结果集封装成对象。

        它提供全局配置文件,建立与数据库的连接;将接口进行分装并提供类和方法实现对数据库的链接和操作;对sql语句执行后的结果进行高级映射并封装成对象;支持动态sql;支持缓存。

        Mybatis中存在自动映射,因为当在数据库中查询的表的属性名和类中的属性名完全相同时才会自动映射并封装,所以需要保证类中的属性和数据库中的属性名相同;如果类中的属性为私有属性,那么类中必须实现get和set方法;还需要保证类中要有无参构造方法,由于mybatis在数据库中查询数据后需要创建对象,调用对应类的无参构造方法,如果找不到对应的无参构造方法,mybatis就会报错;当数据库中的属性名存在驼峰命名,mybatis也是会进行自动映射,但前提是需要开启属性mapUnderscoreToCamelCase,这个属性需要在全局配置文件中设置,表示是否开启驼峰命名的自动映射,true为开启,开启后例如在数据库中的属性名为student_id,那么类中的属性只要设置为studentId这种驼峰命名的方式就可以进行自动映射。

搭建Mybatis框架
        在数据库中创建表,并在创建的项目中创建对应表的模型类;例如在数据库中创建一个学生表,那么为了方便理解我们也在项目中创建一个学生类,如图所示

        我们通常将类中所有的属性都定义为其包装类类型,这样方便后面动态查询条件的判断

<?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>
  <environments default="development">
    <environment id="development">
      <transactionManager type="JDBC"/>
      <dataSource type="POOLED">
        <property name="driver" value="${driver}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${username}"/>
        <property name="password" value="${password}"/>
      </dataSource>
    </environment>
  </environments>
  <mappers>
    <mapper resource="org/mybatis/example/BlogMapper.xml"/>
  </mappers>
</configuration>

        1、在项目的pom.xml配置文件中导入mybatis的jar包

        2、配置全局配置文件(数据库连接信息)

        在resources目录创建一个.xml文件用来配置全局文件,并在文件中写入配置信息

        其中<dataSource>标签用来配置连接数据库的配置信息,其中driver的值为com.mysql.cj.jdbc.Driver,url的值为jdbc:mysql://127.0.0.1:3306/mybatisdb?serverTimezone=Asia/Shanghai,username和password则为自己连接数据库的用户名和密码,这里我使用的数据库是SQLyog

        <dataSource type="POOLED">如果type为unpooled那么表示获取连接时不是从连接池中获取,而是返回一个新建的连接;如果type为pooled

        (1)⾸先先判断空闲连接池内有没有空闲连接,如果还有则给你返回⼀个空闲连接。

        (2)、如果没有空闲连接,则去活动连接池内看看还有没有位置,如果还有,则new⼀个连接给你返回

        (3)、如果活动连接池没有位置了,则返回在活动连接池使⽤最久的连接。意思就是给你返回⼀个在活动连接池内待最久的连接

        <mappers>标签用来添加映射配置文件,一个映射添加一个<mapper>标签,标签中resource属性表示映射文件对于全局配置文件的相对地址

        3、写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">
<mapper namespace=""></mapper>
        <mapper>标签中用来写sql语句,namespace属性的值对应和此映射文件所绑定的接口的包名,例如

        这样映射文件就和接口进行了绑定,我们还需要在配置文件中获取连接数据库的信息以及构建SqlSessionFactory,由于SqlSessionFactory一旦创建就会一直存在于Mybatis的应用过程中,并且由于创建SqlSessionFactory的开销过大 ,所以我们在构建SqlSessionFactory时只需要创建一次即可,所以我们可以创建一个类并将创建SqlSessionFactory的方法放在这个类的静态代码块中,这样即使多次调用这个类但是创建SqlSessionFactory只会执行一次。

public class MyBatisUtil {
    static SqlSessionFactory sqlSessionFactory = null;

    static {
        try {
            //        将全局配置文件放入到流中
            InputStream inputStream = Resources.getResourceAsStream("mybatisConfig.xml");
            //        与数据库建立连接
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public SqlSession getSqlSession() {
        return sqlSessionFactory.openSession();//通过SqlSessionFactory对象获取SqlSession
    }
}

        getSqlSession方法时用来通过SqlSessionFactory对象的openSession方法获取SqlSession对象,我们可以通过SqlSession对象来执行与参数和返回值相匹配的接口

        如果向执行sql语句,首先要在接口中定义抽象方法,并确定参数列表和返回值;然后在映射文件中写对应的sql语句,如果为select语句则需要在<select>标签中书写sql语句,如果为insert语句则需要在<insert>标签中书写sql语句,update和delect语句同理。

public interface StudentDao {
    Student find(int id);//查询通过id查询学生的信息
}
        sql语句中的id需要与接口中的方法名相同,resultType为返回值类型这里的类型为Student,由于Student为自定义的类型,所以需要写该类型的包名,#{id}表示传过来的参数的值

<select id="find" resultType="com.ffyc.mybatisdemo.model.Student">
        select * from student where id = #{id}
</select>
        以下为具体实现的方法

public void findStudent() {
        SqlSession sqlSession = new MyBatisUtil().getSqlSession();//通过类获取SqlSession对象
        StudentDao studentDao = sqlSession.getMapper(StudentDao.class);//通过接口的class(类)对象,获取代理对象,由于接口和映射配置文件绑定,所以可以通过代理对象调用接口中的方法
        Student student = studentDao.find(1);//通过代理对象调用接口中的find方法,并传入参数1
        System.out.println(sqlSession);
        sqlSession.close();
    }
        4、测试

        执行方法后的结果如下,得到如下结果需要在Student中实现toString方法

参数传递问题
        与映射器绑定的接口中的方法中的参数可以是任意一个,因为映射器配置文件中的id属性的值和对应接口的方法名相同,所以同一个接口中的方法不能重名。当方法中的参数为一个时,直接将该参数进行传递即可;而当参数为多个时需要使用@Param注解对参数进行绑定,@Param里的值为类中的属性名,与其绑定的则为形参。

void find(@Param("id")Integer id,@Param("no")Integer no,@Param("name")String name);
        当接口中的参数过于多时,我们可以将参数封装在一个对象中,通过传递对象来传递参数,但是我们还需要在映射器中加入parameterType属性来说明传递的参数的类型。

void find(Student student);
<select id="find" parameterType="Student"></select>
增删改查
        当我们对数据库进行增添操作时,我们先把数据封装在对象中并将值传给数据库中进行操作,此时如果我们还想通过刚新插入的数据的id查询其它的内容,由于id是自增的是由数据库进行自加的,所以我们并不知道id是多少。这时我们可以通过在sql语句的<insert>标签中添加三个属性,就可以获取到数据库在对数据进行添加后的id,并将id封装在对象的属性中。useGeneratedKeys="true"表示是否开启将自增属性传回,keyColumn="id"表示数据库表中的自增属性,keyProperty="id"表示要将获取到的自增属性的值赋值给类中的哪个属性,这样能获取自增属性id的条件是id得是自增属性。

<insert id="saveAdmin" parameterType="Admin" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
        insert into admin(account,password,gender)value(#{account},#{password},#{gender})
</insert>
        在新增,删除和修改操作中,我们在将SqlSession关闭之前,需要将SqlSession的实例化对象的commit方法进行提交,而查询操纵则不需要。因为查询操作没有对数据库中的数据进行改变。

        Mybatis中还存在增删改查操作的注解标签,一般如果某些增删改查操作的sql语句较为简单,我们就可以直接在对应的接口上面通过注解标签的形式来进行操作。

@Select("select * from grade where id = #{id}")
    int selectGrade(int id);
#{}和${}的区别
        #{}为占位符,通过预编译的方式先用?代替出现占位符的地方,等到将sql语句编译完成再将传入的参数,可以防止sql注入

        ${}为拼接符,拼接符就像字符串一样被Mybatis拼接到sql语句中,不能防止sql注入

结果处理
        结果处理就是Mybatis对sql语句执行后的结果进行的封装处理,有时我们不止只在一张表中进行查询操作,返回的结果集中可能存在多个表中的数据,这时我们就需要在mapper映射器中将所有的映射关系进行配置,因为Mybatis在多表查询后时不会将结果进行自动映射并封装的。

        例如在学生和年级关系中,如果想要查询一个学生的信息和其所对应的年级信息,这是一个多对一关系的关联查询,查询的结果集中存在不属于学生表的属性,这时我们需要在自定义的学生类中添加一个年级类型的属性用来存放和年级相关的所有信息,并在mapper映射器中配置各个查询结果的属性所对应类中的属性。

public  class Student {
    private Integer id;
    private String name;
    private String gender;
    private Grade grade;

    public Integer getId() {
        return id;
    }

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

    public Integer getNo() {
        return no;
    }

    public void setNo(Integer no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

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

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Grade getGrade() {
        return grade;
    }

    public void setGrade(Grade grade) {
        this.grade = grade;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", no=" + no +
                ", name='" + name + '\'' +
                ", gender='" + gender + '\'' +
                ", grade=" + grade +
                ", admin=" + admin +
                '}';
    }
}

public class Grade {
    private int id;
    private String name;

    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;
    }

    @Override
    public String toString() {
        return "Grade{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", studentList=" + studentList +
                '}';
    }
}

        如果查询结果集中的属性存在于多个表中,我们在查询<select>标签中的resultType属性将会变为resultMap属性,其值为<resultMap>标签中自定义的id的值,type="Student"表示返回结果集的类型,<resultMap>标签中有<id>和<result>标签,<id>标签代表数据库的表中主键属性,<result>标签则代表其他属性,column="id"表示在数据库表中的属性名,property="id"表示自定义类中的属性名。如果类中存在其他自定义类型的属性则使用<association>标签表示,其中也存在<id>和<result>标签配置方式和前面相同。我们还需要人为的在查询语句中给结果的属性列起别名,这样可以保证在配置映射关系时一个结果集的属性名可以对应一个类中的属性,这是多对一关系结果集映射关系的配置。

<resultMap id="findInfo" type="Student">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <result column="gender" property="gender"></result>
        <association property="grade" javaType="Grade">
            <result column="gname" property="name"></result>
        </association>
</resultMap>
    <select id="findStudent" resultMap="findInfo">
        SELECT s.id,s.name,s.gender,g.name gname FROM student s LEFT JOIN grade g ON s.gradeid = g.id WHERE s.id = #{id}
    </select>
        如果我们要查询在一个年级中有多少个学生以及每个学生的基本信息,这是一个一对多关系的关联查询,这时我们也需要在年级类中添加新的属性,由于是一对多关系所以一个年级就会对应多个学生,所以我们需要添加一个存放学生信息的集合属性。

public class Grade {
    private int id;
    private String name;
    private List<Student> studentList;
}
        配置映射关系的方式和前面大致相同,仍然是写在一个<resultMap>标签中,当属性为集合时我们需要使用<collection>标签,property="studentList"表示在类中这个集合的名字,javaType="list"表示这个集合的类型,ofType="Student"表示集合中的泛型是什么类型,其余的配置方式和前面的都是一样的。

<resultMap id="findGrade" type="Grade">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <collection property="studentList" javaType="list" ofType="Student">
            <id column="sid" property="id"></id>
            <result column="sname" property="name"></result>
        </collection>
</resultMap>
    <select id="findStudent" resultMap="findGrade">
        SELECT
          g.id,
          g.name,
          s.id sid,
          s.name sname
        FROM
          grade g
          LEFT JOIN student s
            ON g.id = s.gradeid
    </select>

        在这种一对多的关联查询中我们还可以使用嵌套查询来解决分页问题的产生,通过将一个复杂的查询转换为多个简单查询。例如查询所有年级以及每个年级对应的所有学生的信息。具体的思路是我们先通过一个简单查询将所有的年级信息查询出来,再根据年级的id来查询每个年级所对应的所有学生。

        其中我们还是使用<resultMap>标签进行对映射关系的配置,和前面的关联查询不同<collection>标签的属性要比前面多两个column="id"表示我们接下来可能需要用到的属性,这里我们是需要根据年级的id进行之后的查询操作的,select="findStudent2"表示一个自定义的名字,和另一个简单查询的id值相同并且另一个简单查询的返回值类型也就变为了Student类型,还是同样将需要的学生信息的属性配置到<collection>标签中。

<resultMap id="GradeMap" type="Grade">
        <id column="id" property="id"></id>
        <result column="name" property="name"></result>
        <collection property="studentList" javaType="list" ofType="Student" column="id" select="findStudent2">
            <id column="id" property="id"></id>
            <result column="name" property="name"></result>
        </collection>
</resultMap>
    <select id="findStudent1" resultMap="GradeMap">
            select * from grade
    </select>
    <select id="findStudent2" resultType="Student">
        select id,name from student where gradeid = #{id}
    </select>
动态sql
        我们在进行查询操作时,有时查询的条件不止一个,这时我们就需要在select语句中手动添加查询条件例如:

select * from student where id = 1 and name = "小明"
        前面我们将类中的属性创建为包装类类型,这样当参数无效时只有两中可能:一种是null,另一种是" ",这时我们如果不将为null或者为" "的属性删除的话我们就查询不到我们想要的数据,这时我们就需要动态地将查询条件进行改变,Mybatis框架中刚好有这种功能。我们可以将where语句的部分写入到Mybatis提供的<where>标签中,并将where后面的语句使用<if>标签进行判断。<where>标签会动态的进行插入或删除我们需要的或者不需要的sql语句,当<where>标签中的<if>条件成立时<where>标签就会将where加入到sql语句中,并且将条件成立的<if>标签中的语句也加入到sql语句中where的后面,而且<where>还会动态地判断where后面的第一个语句是否为and或者or,如果是还会将and和or进行删除,当<where> 标签中没有一个<if>条件成立时<where>标签就不会将where加入到sql语句中,从而实现动态sql的效果。

<select id="findStudent">
    select * from student
    <where>
        <if test="id!=null&amp;id!=''">
            id = #{id}
        </if>
        <if test="name!=null&amp;name!=''">
            and name = #{name}
       </if>
    </where>
</select>
        使用<trim>标签也可以达到这种效果,prefix="where"表示需要在语句中添加的前缀,只要有一个<if>标签成立就加前缀,反之则一个都不加。prefixOverrides="and|or"表示当插入语句中的第一个为and或者or时就将其删除。

<select id="findStudent">
        select * from student
        <trim prefix="where" prefixOverrides="and|or">
            <if test="id!=null&amp;id!=''">
                id = #{id}
            </if>
            <if test="name!=null&amp;name!=''">
                and name = #{name}
            </if>
            <if test="gender!=null&amp;gender!=''">
                and gender = #{gender}
            </if>
        </trim>
</select>
        <set>标签也是这样如果有<if>标签成立就插入set,如果没有就不插入。如果插入语句的最后一个为","则<set>标签就会将","进行删除。

<update id="updateStudent" parameterType="Student">
        update student
        <set>
            <if test="name!=null&amp;name!=''">
                name = #{name},
            </if>
            <if test="gender!=null&amp;gender!=''">
                gender = #{gender}
            </if>
        </set>
        where id = #{id}
</update>
        <trim>标签prefix="set"表示插入的前缀,suffixOverrides=","表示当插入语句的最后一个为","就删除

<update id="updateStudent">
        update student
        <trim prefix="set" suffixOverrides=",">
            <if test="name!=null&amp;name!=''">
                name = #{name},
            </if>
            <if test="gender!=null&amp;gender!=''">
                gender = #{gender}
            </if>
            where id = #{id}
        </trim>
</update>
Mybatis的一级二级缓存
        通过缓存可以减少用户对数据库访问的次数,进而减少了数据库的压力,提高查询性能。我们可以将通过相同的操作而得到相同的结果集的数据保存到缓存中,这样当用户进行多次相同的操作时就不会再向数据库中访问数据,而是直接通过缓存提高了查询效率。我们一般将一段时间内不会发生改变的数据存放在缓存中,例如对某些网页的访问,一个网页在一段时间内可能有很多的用户对其进行访问,我们不能让用户都去访问数据库中的数据,而是可以通过缓存拿到相同的数据,而缓存中的数据我们只需要让其每过一段时间自动刷新一次即可。

        一级缓存

        一级缓存的作用域是同一个SqlSession中,在一个SqlSession中如果执行多次相同的sql操作,那么从第二次操作开始,读取到的数据都是来自于缓存中的,当一个SqlSession不存在后,其对应的缓存也将被销毁,Mybatis默认开启的是一级缓存。

        二级缓存

        二级缓存是 SqlSessionFactory 级别的,作用域为同一个namespace中,当用户执行同一个namespace中的同一个sql语句时,第一次访问会先向数据库中访问并将访问后的数据存放在二级缓存中,当第二次执行同一个namespace中的同一个sql语句时,就会从缓存中读取数据,除非当缓存在超时,被声明需要刷新,或者sqlSession在执行update,insert,delete操作并commit提交时,会清空缓存区,防止读取的数据存在问题。
————————————————
版权声明:本文为CSDN博主「楠佩忆心轩」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_52391639/article/details/125816937

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

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

相关文章

数学建模(二)线性规划

课程推荐&#xff1a;6 线性规划模型基本原理与编程实现_哔哩哔哩_bilibili 目录 一、线性规划的实例与定义 1.1 线性规划的实例 1.2 线性规划的定义 1.3 最优解 1.4 线性规划的Mathlab标准形式 1.5 使用linprog函数 二、线性规划模型建模实战与代码 2.1 问题提出 2.2…

机器学习深度学习——seq2seq实现机器翻译(详细实现与原理推导)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位即将上大四&#xff0c;正专攻机器学习的保研er &#x1f30c;上期文章&#xff1a;机器学习&&深度学习——seq2seq实现机器翻译&#xff08;数据集处理&#xff09; &#x1f4da;订阅专栏&#xff1a;机器学习&…

机器学习编译系列

机器学习编译MLC 1. 引言2. 机器学习编译--概述2.1 什么是机器学习编译 1. 引言 陈天奇目前任教于CMU&#xff0c;研究方向为机器学习系统。他是TVM、MXNET、XGBoost的主要作者。2022年夏天&#xff0c;陈天奇在B站开设了《机器学习编译》的课程。   《机器学习编译》课程共分…

立即开始使用 3D 图像

一、说明 这个故事介绍了使用这种类型的数据来训练机器学习3D模型。特别是&#xff0c;我们讨论了Kaggle中可用的MNIST数据集的3D版本&#xff0c;以及如何使用Keras训练模型识别3D数字。 3D 数据无处不在。由于我们希望构建AI来与我们的物理世界进行交互&#xff0c;因此使用3…

了解 Langchain️是个啥?:第 1 部分

一、说明 在日常生活中&#xff0c;我们主要致力于构建端到端的应用程序。我们可以使用许多自动 ML 平台和 CI/CD 管道来自动化 ml 管道。我们还有像Roboflow和Andrew N.G.的登陆AI这样的工具来自动化或创建端到端的计算机视觉应用程序。 如果我们想在OpenAI或拥抱脸的帮助下创…

Day 26 C++ list容器(链表)

文章目录 list基本概念定义结构双向迭代器优点缺点List和vector区别存储结构内存管理迭代器稳定性随机访问效率 list构造函数——创建list容器函数原型示例 list 赋值和交换函数原型 list 大小操作函数原型示例 list 插入和删除函数原型示例 list 数据存取函数原型注意示例 lis…

论文详解 ——《SNR-Aware Low-light Image Enhancement》

文章目录 Abstract1.Introduction2. Related Work3. Our Method3.1 Long- and Short-range Branches3.2 SNR-based Spatially-varying Feature Fusion3.3 SNR-guided Attention in Transformer3.4 Loss Function 4. Experiments4.1. Datasets and Implementation Details4.2 Co…

SpringBoot | 使用newWorkStealingPool和CompletableFuture进行并发异步处理

关注wx&#xff1a; CodingTechWork 需求 一个列表操作需要异步处理每个元素&#xff0c;最终需要将列表各个元素的操作结果统一返回&#xff0c;无需关注该列表中的顺序执行。这个线程池不会保证任务的顺序执行&#xff0c;即为WorkStealing抢占式的工作。 开发模板 线程池…

基于SpringBoot实现MySQL备份与还原

基于SpringBoot实现MySQL备份与还原&#xff0c;需求是在页面上对所有的平台数据执行备份和恢复操作&#xff0c;那么就需要使用代码去调用MySQL备份和恢复的指令&#xff0c;下面是具体实现步骤&#xff1b; MySQL备份表设计 CREATE TABLE IF NOT EXISTS mysql_backups (id …

6.1 安全漏洞与网络攻击

数据参考&#xff1a;CISP官方 目录 安全漏洞及产生原因信息收集与分析网络攻击实施后门设置与痕迹清除 一、安全漏洞及产生原因 什么是安全漏洞 安全漏洞也称脆弱性&#xff0c;是计算机系统存在的缺陷 漏洞的形式 安全漏洞以不同形式存在漏洞数量逐年递增 漏洞产生的…

前端开发:数组对象判断重复的方法详解

前言 在前端开发过程中,关于数据处理是非常常用的操作,尤其是通过算法处理从后端获取的数据甚为重要。而且在前端开发中,两大类型的数据处理是必备的:数组和对象。与其说是数据处理,不如说是数组和对象的处理。实际开发中,关于数组数据的处理所占比例更高,尤其是涉及到表…

使用Flask.Request的方法和属性,获取get和post请求参数(二)

1、Flask中的request 在Python发送Post、Get等请求时&#xff0c;我们使用到requests库。Flask中有一个request库&#xff0c;有其特有的一些方法和属性&#xff0c;注意跟requests不是同一个。 2、Post请求&#xff1a;request.get_data() 用于服务端获取客户端请求数据。注…

理解ConcurrentSkipListMap(有点类似于并发的TreeMap)

是一个分层的结构。 从最上面开始查找&#xff0c;最后层层往下查。 插入和删除有可能会引起节点Level的变更。 key是有序的&#xff0c;因此可以看做是并发的TreeMap

ubuntu18.04下配置muduoC++11环境

1.安装muduo依赖的编译工具及库 Cmake sudo apt-get install cmakeBoost sudo apt-get install libboost-dev libboost-test-devcurl、c-ares DNS、google protobuf sudo apt-get install libcurl4-openssl-dev libc-ares-dev sudo apt-get install protobuf-compiler libp…

带你了解SpringBoot支持的复杂参数--自定义对象参数-自动封装

&#x1f600;前言 本篇博文是关于SpringBoot 在响应客户端请求时支持的复杂参数和自定义对象参数&#xff0c;希望您能够喜欢&#x1f60a; &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章…

go struct 的常见问题

go struct 的常见问题 1. 什么是struct&#xff1f;2. 如何声明、定义和创建一个struct&#xff1f;3. struct和其他数据类型&#xff08;如数组、切片、map等&#xff09;有什么区别&#xff1f;4. 如何访问struct字段&#xff1f;5. struct是否支持继承&#xff0c;是否支持重…

JavaWeb_xml

文章目录 1.xml是什么&#xff1f;2.xml的用途 1.xml是什么&#xff1f; xml 是可扩展的标记性语言 2.xml的用途 1、用来保存数据&#xff0c;而且这些数据具有自我描述性 2、它还可以做为项目或者模块的配置文件 3、还可以做为网络传输数据的格式&#xff08;现在 JSON 为主…

【Github】SourceTree技巧汇总

sourceTree登录github账户 会跳转到浏览器端 按照Git Flow 初始化仓库分支 克隆远程仓库到本地 推送变更到远程仓库 合并分支 可以看到目前的本地分支&#xff08;main、iOS_JS&#xff09;和远程分支&#xff08;origin/main、origin/HEAD、origin/iOS_JS&#xff09;目前所处…

5134. 简单判断

文章目录 Question输入样例1&#xff1a; 3 7 0 输出样例1&#xff1a; IdeasCode Question 给定三个非负整数 x,y,z &#xff0c;请你按如下要求进行判断并输出相应结果&#xff1a; 如果 x>yz &#xff0c;则输出 。 如果 y>xz &#xff0c;则输出 -。 如果 xy 且 z0…