2022尚硅谷SSM框架跟学(二)MyBatis基础二

news2025/1/18 4:36:31

2022尚硅谷SSM框架跟学二MyBatis基础二

      • 6.MyBatis的各种查询功能
        • 6.1查询一个实体类对象
        • 6.2查询一个list集合
        • 6.3查询单个数据
          • MyBatis别名对应文档
        • 6.4查询一条数据为map集合
        • 6.5查询多条数据为map集合
          • (1)方式一
          • (2)方式二
      • 7.特殊SQL的执行
        • 7.1模糊查询
        • 7.2批量删除
        • 7.3动态设置表名
        • 7.4添加功能获取自增的主键
      • 8自定义映射resultMap
        • 8.1resultMap处理字段和属性的映射关系
          • 方法一:字段名起别名,别名是属性名
          • 方法二:设置一个全局配置信息
          • 方法三:用自定义映射resultMap实现
          • 总结:
        • 8.2多对一映射处理
          • 8.2.1、级联方式处理映射关系
          • 8.2.2使用association处理映射关系
          • 8.2.3分步查询
            • (1)查询员工信息
            • (2)根据员工所对应的部门id查询部门信息
            • (3)分布查询的优势
        • 8.3一对多映射处理
          • 8.3.1collection
          • 8.3.2分步查询
            • (1)查询部门信息
            • (2)根据部门id查询部门中的所有员工

6.MyBatis的各种查询功能

6.1查询一个实体类对象

按照功能创建一个接口SelectMapper
接口
配置Mapper的配置文件
配置Mapper的配置文件
创建测试类
创建测试类
在SelectMapper.java中添加方法

    /**
     * @param
     * @return com.atguigu.mybatis.pojo.User
     * @description //根据id获取User对象
     * @param: id
     * @date 2023/1/3 19:10
     * @author wty
     **/
    User getUserById(@Param("id") Integer id);

在SelectMapper.xml中添加语句

    <!-- User getUserById(Integer id); -->
    <select id="getUserById" resultType="User">
        select *
        from t_user
        where id = #{id}
    </select>

在SelectMapperTest.java测试类中添加方法

    @Test
    public void getUserByIdTest() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);

        User user = mapper.getUserById(6);

        System.out.println(user);

        sqlSession.close();
    }

查询结果
查询结果
原本要查询一行多列的结果集,但是sql写错了查询成了多行多列,这样会出现怎么样的结果呢,一起看下
查询多行多列
报错

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 6

错误详情
提醒我们了,Mapper接口的返回值如果是User,那么查询结果是一行多列,sql不能写错。

6.2查询一个list集合

当查询的数据为多条时,不能使用实体类作为返回值,否则会抛出异常TooManyResultsException;
但是若查询的数据只有一条,可以使用实体类或集合作为返回值

在SelectMapper.java中添加方法

    /**
     * @param
     * @return java.util.List<com.atguigu.mybatis.pojo.User>
     * @description //查询所有用户信息
     * @date 2023/1/3 19:15
     * @author wty
     **/
    List<User> getAllUser();

在SelectMapper.xml中添加语句

    <!-- List<User> getAllUser(); -->
    <select id="getAllUser" resultType="User">
        select *
        from t_user
    </select>

在SelectMapperTest.java测试类中添加方法

    @Test
    public void checkLoginByParamTest() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        User user = mapper.checkLoginByParam("Linda", "234");

        System.out.println(user);

        sqlSession.close();
    }

查询结果
查询成功
如果把SelectMapper.xml中的查询语句更改成查询一行多列,放到这里可以吗,我们一起来看一下。
一行多列
发现查询结果没有问题
查询结果

6.3查询单个数据

单行单列数据,比如数量、平均数,或者某个具体条件查询的某个字段值

在SelectMapper.java中添加方法

    /**
     * @param
     * @return java.lang.Integer
     * @description //获取用户的总数量
     * @date 2023/1/3 19:42
     * @author wty
     **/
    Integer getCount();

在SelectMapper.xml中添加语句

    <!-- Integer getCount(); -->
    <select id="getCount" resultType="java.lang.Integer">
        select count(*)
        from t_user
    </select>

在SelectMapperTest.java测试类中添加方法

    @Test
    public void getCount() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);

        Integer count = mapper.getCount();

        System.out.println("查询的记录数:" + count);

        sqlSession.close();
    }

查询结果
查询结果
除了以上写法外,还有另一种写法resultType=“int”
在SelectMapper.xml中添加语句

    <!-- Integer getCount(); -->
    <select id="getCount" resultType="int">
        select count(*)
        from t_user
    </select>

依然可以执行成功
除了以上写法外,还有另一种写法resultType=“Integer”
在SelectMapper.xml中添加语句

	<!-- Integer getCount(); -->
    <select id="getCount" resultType="Integer">
        select count(*)
        from t_user
    </select>

也可以成功
不区分大小写integer

	<!-- Integer getCount(); -->
    <select id="getCount" resultType="integer">
        select count(*)
        from t_user
    </select>

发现也可以成功
INT大写

    <!-- Integer getCount(); -->
    <select id="getCount" resultType="INT">
        select count(*)
        from t_user
    </select>

依旧可以成功

得出结论:
1.resultType后面的内容不区分大小写
2.resultType提前设置好了别名

MyBatis别名对应文档

MyBatis提前设置好的别名在官方文档中查询如下:

Alias别名Mapped Type(Mapper接口返回类型)
_bytebyte
_longlong
_shortshort
_intint
_integerint
_doubledouble
_floatfloat
_booleanboolean
stringString
byteByte
longLong
shortShort
intInteger
integerInteger
doubleDouble
floatFloat
booleanBoolean
dateDate
decimalBigDecimal
bigdecimalBigDecimal
objectObject
mapMap
hashmapHashMap
listList
arraylistArrayList
collectionCollection
iteratorIterator

6.4查询一条数据为map集合

查询的时候,不是字段名就对应实体类,而是起了别名,那么就需要map集合了。

在SelectMapper.java中添加方法

    /**
     * @param
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @description //通过id查询User信息转换成别名
     * @param: id
     * @date 2023/1/3 22:48
     * @author wty
     **/
    Map<String, Object> getUserByidToMap(@Param("id") Integer id);

在SelectMapper.xml中添加语句

    <!-- Map<String, Object> getUserByidToMap(@Param("id") Integer id); -->
    <select id="getUserByidToMap" resultType="map">
        select *
        from t_user
        where id = #{id}
    </select>

在SelectMapperTest.java测试类中添加方法

    @Test
    public void getUserByidToMapTest() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);

        Map<String, Object> map = mapper.getUserByidToMap(6);
        // {password=456, gender=男, id=6, age=24, email=tony@126.com, username=tony}
        System.out.println(map);

        sqlSession.close();
    }

查询结果
获取结果
注意如果有字段为null那么map集合是不会放进去值的。
例如:
Lisa的年龄和邮箱为null
sqlyog
查询map结果:
查询结果

6.5查询多条数据为map集合

(1)方式一

将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,此时可以将这些map放在一个list集合中获取。

在SelectMapper.java中添加方法

    /**
     * @param
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @description //查询所有用户信息
     * @date 2023/1/3 23:02
     * @author wty
     **/
    Map<String, Object> getAllUserToMap();

在SelectMapper.xml中添加语句

    <!-- Map<String, Object> getAllUserToMap(); -->
    <select id="getAllUserToMap" resultType="map">
        select *
        from t_user
    </select>

在SelectMapperTest.java测试类中添加方法

    @Test
    public void getAllUserToMap() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);

        Map<String, Object> map = mapper.getAllUserToMap();
        System.out.println(map);

        sqlSession.close();
    }

执行后发现报错

org.apache.ibatis.exceptions.TooManyResultsException: Expected one result (or null) to be returned by selectOne(), but found: 7

因为mapper接口中规定的返回值是一个Map<String,Object>集合,但是实际返回值是多个Map集合。
mapper接口
解决方案,用List集合嵌套Map集合
更改SelectMapper.java中的方法

    /**
     * @param
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @description //查询所有用户信息
     * @date 2023/1/3 23:02
     * @author wty
     **/
    List<Map<String, Object>> getAllUserToMap();

修改SelectMapperTest.java测试类

    @Test
    public void getAllUserToMap() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);

        List<Map<String, Object>> list = mapper.getAllUserToMap();
        System.out.println(list);

        sqlSession.close();
    }

而SelectMapper.xml无需修改
查询结果
查询结果

(2)方式二

将表中的数据以map集合的方式查询,一条数据对应一个map;若有多条数据,就会产生多个map集合,并且最终要以一个map的方式返回数据,此时需要通过@MapKey注解设置map集合的键,值是每条数据所对应的map集合。

在SelectMapper.java中修改方法

    /**
     * @param
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @description //查询所有用户信息
     * @date 2023/1/3 23:02
     * @author wty
     **/
    //List<Map<String, Object>> getAllUserToMap();
    @MapKey("id")
    Map<String, Object> getAllUserToMap();

在SelectMapperTest.java测试类中修改方法

    @Test
    public void getAllUserToMap() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        SelectMapper mapper = sqlSession.getMapper(SelectMapper.class);

        //List<Map<String, Object>> list = mapper.getAllUserToMap();
        Map<String, Object> map = mapper.getAllUserToMap();
        //list.forEach(System.out::println);
        Set<Map.Entry<String, Object>> entries = map.entrySet();
        for (Map.Entry<String, Object> entry : entries) {
            System.out.println(entry);
        }
                /**
         * 1={password=123, gender=男, id=1, age=23, email=hsp@126.com, username=hsp}
         * 2={password=123456, gender=男, id=2, age=23, email=hsp@126.com, username=admin}
         * 3={password=123456, gender=男, id=3, age=23, email=hsp@126.com, username=admin}
         * 4={password=123456, gender=男, id=4, age=23, email=hsp@126.com, username=admin}
         * 5={password=111, gender=男, id=5, username=Lisa}
         * 6={password=456, gender=男, id=6, age=24, email=tony@126.com, username=tony}
         * 7={password=234, gender=女, id=7, age=21, email=Linda@126.com, username=Linda}
         */

        sqlSession.close();
    }

查询结果:
查询结果

7.特殊SQL的执行

防止出现sql注入,一般都使用#{}占位符的方式,但是如下几个特殊的sql一般使用${}的形式。

新建Mapper接口 SpecialSqlMapper
新建接口
新建配置文件SpecialSqlMapper.xml
配置namespace
保证一一对应
新建测试类SpecialSqlMapperTest.java

7.1模糊查询

在SpecialSqlMapper.java中添加方法

    /**
     * @param
     * @return java.util.List<com.atguigu.mybatis.pojo.User>
     * @description //根据mh字段(用户名)查询用户信息
     * @param: mh
     * @date 2023/1/3 23:41
     * @author wty
     **/
    List<User> getUserByLike(@Param("mh") String mh);

在SpecialSqlMapper.xml中添加sql语句

    <!-- List<User> getUserByLike(@Param("mh") String mh); -->
    <select id="getUserByLike" resultType="User">
        select *
        from t_user
        where username like '%#{mh}%'
    </select>

在SpecialSqlMapperTest.java添加测试方法

    @Test
    public void getUserByLikeTest() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        SpecialSqlMapper mapper = sqlSession.getMapper(SpecialSqlMapper.class);

        List<User> list = mapper.getUserByLike("a");

        list.forEach(System.out::println);

        sqlSession.close();
    }

发现执行结果:报错

DEBUG 01-03 23:45:52,147 ==>  Preparing: select * from t_user where username like '%?%' (BaseJdbcLogger.java:137) 
Caused by: java.sql.SQLException: Parameter index out of range (1 > number of parameters, which is 0).

报错信息
还原一下报错原因

    public void testJdbc() {
        try {
            Class.forName("");
            Connection connection = DriverManager.getConnection("", "", "");
            String sql = "select * from t_user where username like '%?%'";
            PreparedStatement preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, "a");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

报错
可以看到错误原因是单引号中的?会看成问号,而不是占位符,而实际有a作为占位符的变量,这样就导致了a超出了占位符的个数。

解决方案1
在SpecialSqlMapper.xml中更改为${}

    <!-- List<User> getUserByLike(@Param("mh") String mh); -->
    <select id="getUserByLike" resultType="User">
        select *
        from t_user
        where username like '%${mh}%'
    </select>

查询结果
查询结果
解决方案2
用mysql提供的concat函数拼接

    <!-- List<User> getUserByLike(@Param("mh") String mh); -->
    <select id="getUserByLike" resultType="User">
        select *
        from t_user
        where username like concat('%', #{mh}, '%')
    </select>

查询正确

解决方案3
双引号方式"%“#{}”%"

    <!-- List<User> getUserByLike(@Param("mh") String mh); -->
    <select id="getUserByLike" resultType="User">
        select *
        from t_user
        where username like "%"#{mh}"%"
    </select>

执行结果正确

7.2批量删除

在SpecialSqlMapper.java中添加方法

    /**
     * @param
     * @return int
     * @description //根据多个id删除多条记录
     * @param: ids
     * @date 2023/1/4 16:29
     * @author wty
     **/
    int deleteMoreUser(@Param("ids") String ids);

在SpecialSqlMapper.xml中添加sql语句

    <!-- int deleteMoreUser(@Param("ids") String ids); -->
    <delete id="deleteMoreUser">
        delete
        from t_user
        where id in (#{ids})
    </delete>

在SpecialSqlMapperTest.java添加测试方法

    @Test
    public void deleteMoreUser() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        SpecialSqlMapper mapper = sqlSession.getMapper(SpecialSqlMapper.class);

        int i = mapper.deleteMoreUser("8,9,10,11");

        System.out.println("删除了:" + i + "条记录");

        sqlSession.close();
    }

发现报错
报错
这里必须要用${}的形式,那么需要修改
修改SpecialSqlMapper.xml中的sql语句

    <!-- int deleteMoreUser(@Param("ids") String ids); -->
    <delete id="deleteMoreUser">
        delete
        from t_user
        where id in (${ids})
    </delete>

查询结果
删除结果

7.3动态设置表名

在SpecialSqlMapper.java中添加方法

    /**
     * @param
     * @return java.util.List<com.atguigu.mybatis.pojo.User>
     * @description //动态设置表名查询用户的信息
     * @param: tableName
     * @date 2023/1/4 16:46
     * @author wty
     **/
    List<User> getUserList(@Param("tableName") String tableName);

在SpecialSqlMapper.xml中添加sql语句

    <!-- List<User> getUserList(@Param("tableName") String tableName);-->
    <select id="getUserList" resultType="User">
        select *
        from #{tableName}
    </select>

在SpecialSqlMapperTest.java添加测试方法

    @Test
    public void getUserList() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        SpecialSqlMapper mapper = sqlSession.getMapper(SpecialSqlMapper.class);

        List<User> list = mapper.getUserList("t_user");

        list.forEach(System.out::println);

        sqlSession.close();
    }

发现报错
表名报错
表名两侧有单引号,是不对的,想到了用${}来写
修改SpecialSqlMapper.xml中的ql语句

    <select id="getUserList" resultType="User">
        select *
        from ${tableName}
    </select>

查询结果
查询结果

7.4添加功能获取自增的主键

使用场景:

场景模拟:
t_clazz(clazz_id,clazz_name)
t_student(student_id,student_name,clazz_id)
1、添加班级信息
2、获取新添加的班级的id
3、为班级分配学生,即将某学的班级id修改为新添加的班级的id

获取自增主键不是MyBatis特有的,其底层是JDBC的,可以看下示例代码
配置自增参数

    public void getautoincreamidTest() {
        try {
            Class.forName("");
            Connection connection = DriverManager.getConnection("", "", "");
            String sql = "insert into t_user values(?,?)";
            // 这里需要配置第2个参数,可以直接写1
            PreparedStatement preparedStatement = connection.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            preparedStatement.setString(1, "a");
            preparedStatement.setString(2, "b");
            preparedStatement.executeUpdate();
            // resultSet是单行单列的
            ResultSet resultSet = preparedStatement.getGeneratedKeys();
            resultSet.next();
            // 自动递增的主键,因为是单行单列,所以获取的时候是getInt(1)
            int id = resultSet.getInt(1);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

在SpecialSqlMapper.java中添加方法

    /**
     * @param
     * @return int
     * @description //添加一条用户信息,并且获取自增主键
     * @param: user
     * @date 2023/1/4 17:16
     * @author wty
     **/
    int insertUser(User user);

在SpecialSqlMapper.xml中添加sql语句
useGeneratedKeys:设置使用自增的主键。
keyProperty:因为增删改有统一的返回值是受影响的行数,因此只能将获取的自增的主键放在传输的参数user对象的某个属性中。

    <!--     int insertUser(User user); -->
    <!-- useGeneratedKeys是否显示自增主键  keyProperty是用于返回自增主键的字段  -->
    <insert id="insertUser" useGeneratedKeys="true" keyProperty="id">
        insert into t_user
        values (null, #{username}, #{password}, #{age}, #{gender}, #{email})
    </insert>

在SpecialSqlMapperTest.java添加测试方法

    @Test
    public void insertUser() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        SpecialSqlMapper mapper = sqlSession.getMapper(SpecialSqlMapper.class);

        User user = new User(null, "Lucy", "123", 21, "女", "Lucy@qq.com");
        System.out.println("插入前:" + user);
        int i = mapper.insertUser(user);

        System.out.println("插入成功:" + i + "条数据");
        System.out.println("插入后:" + user);

        sqlSession.close();
    }

运行测试类,结果如下:
测试类
获取到id是自增主键

8自定义映射resultMap

8.1resultMap处理字段和属性的映射关系

若字段名和实体类中的属性名不一致,则可以通过resultMap设置自定义映射

创建新的Module
创建Module
点击下一步
点击下一步
Name:mybatis-resultMap
GroupId:com.atguigu.mybatis
配置Maven
拷贝上一个pom.xml的内容

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>SSM</artifactId>
        <groupId>org.example</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.atguigu.mybatis</groupId>
    <artifactId>mybatis-resultMap</artifactId>
    <!-- 打包方式 -->
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- Mybatis核心 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.5.7</version>
        </dependency>
        <!-- junit测试 -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- MySQL驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.20</version>
        </dependency>
        <!-- log4j日志 -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>

    </dependencies>

</project>

拷贝上一个工程的jdbc.properties和log4j.xml
拷贝
用模板创建mybatis-config.xml
模板创建
从上一个工程拷贝工具类SqlSessionUtil.java
拷贝工具类
创建pojo和mapper包,并在核心配置文件mybatis-config.xml中配置包名
配置核心配置文件
创建mapper的配置文件的文件夹
mapper包
在SQL YOG中新创建2张表
t_emp
创建t_emp表

CREATE TABLE `t_emp` (
  `emp_id` INT(11) NOT NULL AUTO_INCREMENT,
  `emp_name` VARCHAR(20) DEFAULT NULL,
  `age` INT(11) DEFAULT NULL,
  `gender` CHAR(1) DEFAULT NULL,
  `dept_id` INT(11) DEFAULT NULL,
  PRIMARY KEY (`emp_id`)
) ENGINE=INNODB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

创建t_dept表
创建表

CREATE TABLE `t_dept` (
  `dept_id` INT(11) NOT NULL AUTO_INCREMENT,
  `dept_name` VARCHAR(20) DEFAULT NULL,
  PRIMARY KEY (`dept_id`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;

添加数据
添加数据1
添加数据2
写pojo实体类 Emp.java

package com.atguigu.mybatis.pojo;

/**
 * @ClassName: Emp
 * @Description:
 * @Author: wty
 * @Date: 2023/1/4
 */

public class Emp {
    private Integer empId;
    private String empName;
    private Integer age;
    private String gender;
    private Integer deptId;

    public Emp() {
    }

    public Emp(Integer empId, String empName, Integer age, String gender, Integer deptId) {
        this.empId = empId;
        this.empName = empName;
        this.age = age;
        this.gender = gender;
        this.deptId = deptId;
    }

    public Integer getEmpId() {
        return empId;
    }

    public void setEmpId(Integer empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

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

    public Integer getDeptId() {
        return deptId;
    }

    public void setDeptId(Integer deptId) {
        this.deptId = deptId;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empId=" + empId +
                ", empName='" + empName + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", deptId=" + deptId +
                '}';
    }
}

写pojo实体类 Dept.java

package com.atguigu.mybatis.pojo;

/**
 * @ClassName: Dept
 * @Description:
 * @Author: wty
 * @Date: 2023/1/4
 */

public class Dept {
    private Integer deptId;
    private String deptName;

    public Dept() {
    }

    public Dept(Integer deptId, String deptName) {
        this.deptId = deptId;
        this.deptName = deptName;
    }

    public Integer getDeptId() {
        return deptId;
    }

    public void setDeptId(Integer deptId) {
        this.deptId = deptId;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptId=" + deptId +
                ", deptName='" + deptName + '\'' +
                '}';
    }
}

创建mapper接口
mapper接口1
mapper接口2

用模板创建mapper的核心配置文件,并且配置接口的全类名
mapper接口配置文件
在EmpMapper.java中添加方法

    /**
     * @param
     * @return com.atguigu.mybatis.pojo.Emp
     * @description //根据员工ID查询员工信息
     * @param: empId
     * @date 2023/1/4 21:19
     * @author wty
     **/
    Emp getEmpByEmpId(@Param("empId") Integer empId);

在EmpMapper.xml中添加sql

    <!-- Emp getEmpByEmpId(@Param("empId") Integer empId);-->
    <select id="getEmpByEmpId" resultType="Emp">
        select *
        from t_emp
        where emp_id = #{empId}
    </select>

创建测试类 com.atguigu.mybatis.test.ResultMapTest
创建测试类
测试类ResultMapTest.java添加方法

    @Test
    public void getEmpByEmpId() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);

        Emp id = mapper.getEmpByEmpId(3);

        System.out.println("id = " + id);

        sqlSession.close();
    }

查询结果
查询结果
查询不出来的话,需要对应字段名和实体类的属性名
修改EmpMapper.xml

方法一:字段名起别名,别名是属性名
    <select id="getEmpByEmpId" resultType="Emp">
        select emp_id empId, emp_name empName, age, gender, dept_id deptId
        from t_emp
        where emp_id = #{empId}
    </select>

查询结果
查询结果

方法二:设置一个全局配置信息

找到MyBatis的官方pdf
官方pdf
拷贝pdf的方法
拷贝官方pdf
mybatis-config.xml中添加

    <!-- mapUnderscoreToCamelCase将下划线映射为驼峰 -->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

EmpMapper.xml中保持不变,最初的状态

    <select id="getEmpByEmpId" resultType="Emp">
        select *
        from t_emp
        where emp_id = #{empId}
    </select>

直接跑测试类,查看结果
可以查询出来

方法三:用自定义映射resultMap实现

更改EmpMapper.xml文件,选择使用resultMap的方式

resultMap:设置自定义映射
属性:
id:表示自定义映射的唯一标识
type:查询的数据要映射的实体类的类型
子标签:
id:设置主键的映射关系
result:设置普通字段的映射关系
association:设置多对一的映射关系
collection:设置一对多的映射关系
属性:
property:设置映射关系中实体类中的属性名
column:设置映射关系中表中的字段名

    <!-- 方式3:使用resultMap
         resultMap使用resultMap标签的信息
    -->
    <resultMap id="empResultMap" type="Emp">
        <!-- id 设置数据库主键和属性名的映射关系 -->
        <id column="emp_id" property="empId"></id>
        <!-- result 设置数据库非主键字段和属性名的映射关系 -->
        <result column="emp_name" property="empName"></result>
        <result column="age" property="age"></result>
        <result column="gender" property="gender"></result>
        <result column="dept_id" property="deptId"></result>
    </resultMap>

    <select id="getEmpByEmpId" resultMap="empResultMap">
        select *
        from t_emp
        where emp_id = #{empId}
    </select>

执行测试类,查看结果
查询结果

总结:

若字段名和实体类中的属性名不一致,但是字段名符合数据库的规则(使用_),实体类中的属性名符合Java的规则(使用驼峰)。
此时也可通过以下两种方式处理字段名和实体类中的属性的映射关系
a>.可以通过为字段起别名的方式,保证和实体类中的属性名保持一致
b>.可以在MyBatis的核心配置文件中设置一个全局配置信息mapUnderscoreToCamelCase,可以在查询表中数据时,自动将_类型的字段名转换为驼峰例如:字段名user_name,设置了mapUnderscoreToCamelCase,此时字段名就会转换为userName

8.2多对一映射处理

场景模拟:
查询员工信息以及员工所对应的部门信息

针对Emp实体类进行修改,分析deptId字段,一个员工只有一个部门是1对1,那么是用对象返回。

package com.atguigu.mybatis.pojo;

/**
 * @ClassName: Emp
 * @Description:
 * @Author: wty
 * @Date: 2023/1/4
 */

public class Emp {
    private Integer empId;
    private String empName;
    private Integer age;
    private String gender;
    /**
     * 一个员工对应一个部门,所以是1:1
     */
    private Dept dept;

    public Emp() {
    }

    public Emp(Integer empId, String empName, Integer age, String gender, Dept dept) {
        this.empId = empId;
        this.empName = empName;
        this.age = age;
        this.gender = gender;
        this.dept = dept;
    }

    public Integer getEmpId() {
        return empId;
    }

    public void setEmpId(Integer empId) {
        this.empId = empId;
    }

    public String getEmpName() {
        return empName;
    }

    public void setEmpName(String empName) {
        this.empName = empName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

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

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "empId=" + empId +
                ", empName='" + empName + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", dept=" + dept +
                '}';
    }
}

EmpMapper.java中加入方法

    /**
     * @param
     * @return com.atguigu.mybatis.pojo.Emp
     * @description //根据员工ID获取员工和部门信息
     * @param: empId
     * @date 2023/1/4 22:28
     * @author wty
     **/
    Emp getEmpAndDeptByEmpid(@Param("empId") Integer empId);

EmpMapper.xml中写入sql语句

    <!--     Emp getEmpAndDeptByEmpid(@Param("empId") Integer empId);-->
    <select id="getEmpAndDeptByEmpid" resultType="Emp">
        SELECT a.*, b.`dept_name`
        FROM t_emp a
                 LEFT JOIN
             t_dept b ON a.dept_id = b.dept_id
        WHERE a.emp_id = #{empId}
    </select>

测试类ResultMapTest.java中加入方法

  @Test
    public void getEmpAndDeptByEmpid() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);

        Emp emp = mapper.getEmpAndDeptByEmpid(3);

        System.out.println(emp);

        sqlSession.close();
    }

查看结果:
查看结果
这种方式,Emp类中dept对象是不可能赋值的,所以这种方式是错误的。
解决方式如下3种:

8.2.1、级联方式处理映射关系

在EmpMapper.xml中添加sql

    <!-- 处理多对一的映射关系 -->
    <!-- 方法1:级联 -->
    <resultMap id="empAndDeptResultMap" type="Emp">
        <id column="emp_id" property="empId"></id>
        <result column="emp_name" property="empName"></result>
        <result column="age" property="age"></result>
        <result column="gender" property="gender"></result>
        <result column="dept_id" property="dept.deptId"></result>
        <result column="dept_name" property="dept.deptName"></result>
    </resultMap>
    <select id="getEmpAndDeptByEmpid" resultMap="empAndDeptResultMap">
        SELECT a.*, b.`dept_name`
        FROM t_emp a
                 LEFT JOIN
             t_dept b ON a.dept_id = b.dept_id
        WHERE a.emp_id = #{empId}
    </select>

测试类ResultMapTest.java中执行测试方法
测试方法

8.2.2使用association处理映射关系

在EmpMapper.xml中添加sql

    <!-- 方法2:使用association处理映射关系 -->
    <resultMap id="empAndDeptResultMap" type="Emp">
        <id column="emp_id" property="empId"></id>
        <result column="emp_name" property="empName"></result>
        <result column="age" property="age"></result>
        <result column="gender" property="gender"></result>
        <result column="dept_id" property="dept.deptId"></result>
        <result column="dept_name" property="dept.deptName"></result>
    <!-- association 处理多对一的映射关系,也可以处理一对一,主要处理实体类的属性
             property 设置实体类中dept对象的映射关系
             javaType 设置实体类dept的类型Dept
        -->
        <association property="dept" javaType="Dept">
            <id column="dept_id" property="deptId"></id>
            <result column="dept_name" property="deptName"></result>
        </association>
    </resultMap>
    <select id="getEmpAndDeptByEmpid" resultMap="empAndDeptResultMap">
        SELECT a.*, b.`dept_name`
        FROM t_emp a
                 LEFT JOIN
             t_dept b ON a.dept_id = b.dept_id
        WHERE a.emp_id = #{empId}
    </select>

测试类ResultMapTest.java中执行方法,查看结果
查看结果

8.2.3分步查询
(1)查询员工信息

在EmpMapper.java中添加方法

    /**
     * @param
     * @return com.atguigu.mybatis.pojo.Emp
     * @description //分步查询:先根据员工ID查询员工信息
     * @param: empId
     * @date 2023/1/4 23:10
     * @author wty
     **/
    Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId);

在EmpMapper.xml中添加sql

    <!-- 方法3:分步查询-->
    <resultMap id="getEmpAndDeptByStepOnResultMap" type="Emp">
        <id column="emp_id" property="empId"></id>
        <result column="emp_name" property="empName"></result>
        <result column="age" property="age"></result>
        <result column="gender" property="gender"></result>
        <!-- association 处理多对一的映射关系,也可以处理一对一,主要处理实体类的属性
             property 设置实体类中dept对象的映射关系
             select 设置分布查询中dept对象的属性从另外哪个sql获取,这里取值是mapper接口中方法的全类名
             column 多表查询中外键字段的字段名
        -->
        <association property="dept" select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
                     column="dept_id">
            <id column="dept_id" property="deptId"></id>
            <result column="dept_name" property="deptName"></result>
        </association>
    </resultMap>
    <!-- Emp getEmpAndDeptByStepOne(@Param("empId") Integer empId); -->
    <select id="getEmpAndDeptByStepOne" resultMap="getEmpAndDeptByStepOnResultMap">
        select *
        from t_emp
        where emp_id = #{empId}
    </select>
(2)根据员工所对应的部门id查询部门信息

特别注意,这里要在DeptMapper.java中添加方法

   /**
     * @param
     * @return com.atguigu.mybatis.pojo.Dept
     * @description //分步查询2:根据员工所在部门的ID查询部门信息
     * @param: deptId
     * @date 2023/1/4 23:18
     * @author wty
     **/
    Dept getEmpAndDeptByStepTwo(@Param("deptId") Integer deptId);

在DeptMapper.xml中添加sql

    <!-- Dept getEmpAndDeptByStepTwo(@Param("deptId") Integer deptId); -->
    <select id="getEmpAndDeptByStepTwo" resultType="Dept">
        select *
        from t_dept
        where dept_id = #{deptId}
    </select>

测试类ResultMapTest.java中添加方法

    @Test
    public void getEmpAndDeptByStepOne() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);

        Emp emp = mapper.getEmpAndDeptByStepOne(3);

        System.out.println(emp);

        sqlSession.close();
    }

查询结果
查询结果

(3)分布查询的优势

延迟加载(懒加载)
如果当前只查询员工信息,而不需要部门信息,那么就不会查询部门信息,即:不会进行第二步的查询,可以减少内存的消耗。
如果要开启延迟加载,需要开启配置信息
查看官方文档
官方文档

lazyLoadingEnabled:延迟加载的全局开关。当设置为true时,所有关联对象都会延迟加载。
aggressiveLazyLoading:当设置为true时,任何方法的调用都会加载该对象的所有属性。设置成false的时候每个属性会按需加载。比如,如果设置成true那么无论查询什么信息,2步查询都会查,如果设置成false配合lazyLoadingEnabled设置true可以实现按需加载,即如果查询员工姓名,则不会执行部门查询的sql语句。

在mybatis-config.xml增加
懒加载

        <!-- 开启延迟加载(懒加载) -->
        <setting name="lazyLoadingEnabled" value="true"/>

修改ResultMapTest.java,只查询员工的名称

    @Test
    public void getEmpAndDeptByStepOne() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);

        Emp emp = mapper.getEmpAndDeptByStepOne(3);

        System.out.println(emp.getEmpName());

        sqlSession.close();
    }

查看运行结果
查看运行结果
反之,如果我们查询了部门名称,看下结果

    @Test
    public void getEmpAndDeptByStepOne() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);

        Emp emp = mapper.getEmpAndDeptByStepOne(3);

        System.out.println(emp.getDept().getDeptName());

        sqlSession.close();
    }

查询结果
设置另外一个参数,因为默认是false可以省略
另一个参数

    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <!-- 延迟加载由2个参数决定 lazyLoadingEnabled设置true
                                  aggressiveLazyLoading设置false
         -->
        <!-- 开启延迟加载(懒加载) -->
        <setting name="lazyLoadingEnabled" value="true"/>
        <!--aggressiveLazyLoading 设置false按需加载 -->
        <!--aggressiveLazyLoading 设置true全部加载 -->
        <setting name="aggressiveLazyLoading" value="false"/>
    </settings>

注意,这样配置的延迟加载是全局变量,MyBatis中所有的分布查询都会遵循设置,那么如果某个Mapper查询不想遵从的话,我们该怎么办呢。
修改EmpMapper.xml
在这里插入图片描述

        <!-- association 处理多对一的映射关系,也可以处理一对一,主要处理实体类的属性
             property 设置实体类中dept对象的映射关系
             select 设置分布查询中dept对象的属性从另外哪个sql获取,这里取值是mapper接口中方法的全类名
             column 多表查询中外键字段的字段名
             fetchType lazy延迟加载  eager立即加载
        -->
        <association property="dept" select="com.atguigu.mybatis.mapper.DeptMapper.getEmpAndDeptByStepTwo"
                     column="dept_id" fetchType="eager">
            <id column="dept_id" property="deptId"></id>
            <result column="dept_name" property="deptName"></result>
        </association>

可以看到fetchType如果设置了eager,当前类就遵从了全部加载
再测试一下加载员工姓名

    @Test
    public void getEmpAndDeptByStepOne() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);

        Emp emp = mapper.getEmpAndDeptByStepOne(3);

        System.out.println(emp.getEmpName());

        sqlSession.close();
    }

查看结果
加载全部类

8.3一对多映射处理

Dept.java中添加属性
添加属性

package com.atguigu.mybatis.pojo;

import java.util.List;

/**
 * @ClassName: Dept
 * @Description:
 * @Author: wty
 * @Date: 2023/1/4
 */

public class Dept {
    private Integer deptId;
    private String deptName;

    private List<Emp> emps;

    public Dept() {
    }

    public Dept(Integer deptId, String deptName) {
        this.deptId = deptId;
        this.deptName = deptName;
    }

    public Integer getDeptId() {
        return deptId;
    }

    public void setDeptId(Integer deptId) {
        this.deptId = deptId;
    }

    public String getDeptName() {
        return deptName;
    }

    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }

    public List<Emp> getEmps() {
        return emps;
    }

    public void setEmps(List<Emp> emps) {
        this.emps = emps;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "deptId=" + deptId +
                ", deptName='" + deptName + '\'' +
                ", emps=" + emps +
                '}';
    }
}

8.3.1collection

在DeptMapper.java中添加方法

    /**
     * @param
     * @return com.atguigu.mybatis.pojo.Dept
     * @description //查询部门以及部门中的员工信息
     * @param: deptId
     * @date 2023/1/6 21:12
     * @author wty
     **/
    Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId);

在DeptMapper.xml中添加sql语句

 <!-- 处理一对多的映射关系: -->
    <!-- 方法1:collection -->
    <!-- Dept getDeptAndEmpByDeptId(@Param("deptId") Integer deptId); -->
    <resultMap id="getDeptAndEmpByDeptIdResultMap" type="Dept">
        <id column="dept_id" property="deptId"></id>
        <result column="dept_name" property="deptName"></result>
        <!--collection处理一(多)对多的映射关系 集合类型  -->
        <!-- ofType设置集合中的类型,比如这里Dept实体类中有属性emp,那么该类型来自于实体类Emp,则ofTyoe是Emp -->
        <collection property="emps" ofType="Emp">
            <id column="emp_id" property="empId"></id>
            <result column="emp_name" property="empName"></result>
            <result column="age" property="age"></result>
            <result column="gender" property="gender"></result>
        </collection>
    </resultMap>
    <select id="getDeptAndEmpByDeptId" resultMap="getDeptAndEmpByDeptIdResultMap">
        select *
        from t_dept a
                 left join t_emp b on a.dept_id = b.dept_id
        where a.dept_id = #{deptId}
    </select>

在ResultMapTest.java添加方法

    @Test
    public void getDeptAndEmpByDeptId() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);

        Dept dept = mapper.getDeptAndEmpByDeptId(3);

        System.out.println(dept);

        sqlSession.close();
    }

查询结果
查询结果

8.3.2分步查询
(1)查询部门信息

在DeptMapper.java中添加方法作为分步查询的第1步

  /**
     * @param
     * @return com.atguigu.mybatis.pojo.Dept
     * @description // 分步查询第一步:部门信息以及员工员工信息
     * @param: deptId
     * @date 2023/1/6 21:39
     * @author wty
     **/
    Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId);

在DeptMapper.xml中添加方法

    <!-- 方法2:分步查询 -->
    <resultMap id="getDeptAndEmpByStepOneResultMap" type="Dept">
        <id column="dept_id" property="deptId"></id>
        <result column="dept_name" property="deptName"></result>
        <collection property="emps" select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
                    fetchType="lazy" column="dept_id">
            <id column="dept_id" property="deptId"></id>
            <result column="dept_name" property="deptName"></result>
        </collection>
    </resultMap>
    <!-- Dept getDeptAndEmpByStepOne(@Param("deptId") Integer deptId); -->
    <select id="getDeptAndEmpByStepOne" resultMap="getDeptAndEmpByStepOneResultMap">
        select *
        from t_dept
        where dept_id = #{deptId}
    </select>
(2)根据部门id查询部门中的所有员工

在EmpMapper.java中添加方法作为分步查询的第2步

    /**
     * @param
     * @return java.util.List<com.atguigu.mybatis.pojo.Emp>
     * @description //分步查询第二步:部门信息以及员工员工信息
     * @param: deptId
     * @date 2023/1/6 22:40
     * @author wty
     **/
    List<Emp> getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId);

注意接口中方法的全类名要配置进select标签中
配置进select

在EmpMapper.xml中添加sql语句

    <!-- Dept getDeptAndEmpByStepTwo(@Param("deptId") Integer deptId); -->
    <select id="getDeptAndEmpByStepTwo" resultType="Emp">
        select *
        from t_emp
        where dept_id = #{deptId}
    </select>

最后修改测试类

    @Test
    public void getDeptAndEmpByStepOneTesy() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);

        Dept dept = mapper.getDeptAndEmpByStepOne(1);

        System.out.println(dept);

        sqlSession.close();
    }

查询结果
查询结果

只查询部门信息,查看延迟加载
修改ResultMapTest.java

@Test
    public void getDeptAndEmpByStepOneTesy() {
        SqlSession sqlSession = SqlSessionUtil.getSqlSession();

        DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);

        Dept dept = mapper.getDeptAndEmpByStepOne(1);

        System.out.println(dept.getDeptName());

        sqlSession.close();
    }

查看结果
查看结果
更改配置,设置为全部加载
修改DeptMapper.xml

        <collection property="emps" select="com.atguigu.mybatis.mapper.EmpMapper.getDeptAndEmpByStepTwo"
                    fetchType="eager" column="dept_id">
            <id column="dept_id" property="deptId"></id>
            <result column="dept_name" property="deptName"></result>
        </collection>

修改配置

继续运行测试类,查看结果
查询全部的sql

分步查询的优点:可以实现延迟加载
但是必须在核心配置文件中设置全局配置信息:
lazyLoadingEnabled:延迟加载的全局开关。当开启时,所有关联对象都会延迟加载。
aggressiveLazyLoading:当开启时,任何方法的调用都会加载该对象的所有属性。否则,每个属性会按需加载。
此时就可以实现按需加载,获取的数据是什么,就只会执行相应的sql。此时可通过association和collection中的fetchType属性设置当前的分步查询是否使用延迟加载, fetchType=“lazy(延迟加载)|eager(立即加载)”

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

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

相关文章

SpringBoot+VUE前后端分离项目学习笔记 - 【16 SpringBoot集成JWT】

JWT简介 JWT是json web token缩写。用点号分为三段&#xff0c;分别表示头、信息和签名。可以使用在RESTFUL接口定义&#xff0c; 也可以使用在普通的web。它将用户信息加密到token里&#xff0c;服务器不保存任何用户信息。服务器通过密钥验证token的正确性&#xff0c;判断是…

模板的基本概念

模板函数模板泛型编程基本概念函数模板格式函数模板的实现函数模板的实例化类模板类模板格式类模板的实例化模板参数的匹配原则复数的相加函数模板 泛型编程 泛型编程是编写与类型无关的通用代码&#xff0c;是代码复用的一种手段。模板是泛型编程的基础。 基本概念 函数模…

【自学C++】C++命名空间引入

C命名空间引入 C命名空间引入教程 C 中的命名空间的引入&#xff0c;我们通常使用 using 语句后面加上命名空间名即可。 C命名空间引入详解 语法 using namespace namespaceName参数 参数描述using引入命名空间使用的关键字。namespace引入命名空间使用的关键字。namespa…

数影周报:2亿Twitter用户资料仅售2美元,微盟集团将筹约15.9亿港元

本周看点&#xff1a;黑客以2美元出售2亿Twitter用户个人资料&#xff1b;Twitter 第三轮裁员&#xff1b;京东科技成立京东云事业部&#xff1b;TikTok Shop越南收入赶超Lazada&#xff1b;微盟集团将筹资约15.9亿港元......数据安全那些事黑客以2美元出售2亿Twitter用户资料近…

2023年山东最新建筑施工架子工(建筑特种作业)模拟题库及答案

百分百题库提供特种工&#xff08;架子工&#xff09;考试试题、特种工&#xff08;架子工&#xff09;考试预测题、特种工&#xff08;架子工&#xff09;考试真题、特种工&#xff08;架子工&#xff09;证考试题库等,提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助…

mosquitto使用与openssl证书配置

开发环境&#xff1a;ubuntu18.04 64bitmqtt客户端测试工具&#xff1a;mqtt.fx 1.7.11.安装# 引入库 sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa sudo apt-get update # 安装 sudo apt-get install mosquitto #安装客户端 sudo apt-get install mosquitto-clie…

《NDT-LOAM: A Real-Time Lidar Odometry andMapping With Weighted NDT and LFA》深大学生

Abstract激光雷达同时定位和建图&#xff08;Lidar-SLAM&#xff09;从激光雷达上处理点云&#xff0c;并完成定位和建图。激光激光通常分为前端里程计和后端优化&#xff0c;可以并行运行以提高计算效率。前端里程计通过处理点云来估计激光雷达的运动&#xff0c;在点云配准中…

python自学之《21天学通Python》(6)

第9章 迭代器、生成器与装饰器 迭代器、生成器与装饰器是Python语言中常用的语法形式。 迭代器的使用简化了循环程序的代码并可以节约内存&#xff0c;生成器的使用也可以节约大量的内存&#xff0c;特别是需要生成大量序列的对象时。迭代器是一种可以从其中连续迭代的一个容器…

Shell 数组

数组中可以存放多个值。Bash Shell 只支持一维数组&#xff08;不支持多维数组&#xff09;&#xff0c;初始化时不需要定义数组大小&#xff08;与 PHP 类似&#xff09;。与大部分编程语言类似&#xff0c;数组元素的下标由 0 开始。Shell 数组用括号来表示&#xff0c;元素用…

教你如何巧妙化解SSRF漏洞攻击

SSRF是一种由攻击者构造请求&#xff0c;由服务端发起请求的安全漏洞。一般情况下&#xff0c;ssrf攻击的目标是外网无法访问的内部系统。简单来说就是利用服务器漏洞以服务器的身份发送一条构造好的请求给服务器所在内网进行攻击。 SSRF漏洞&#xff08; 服务器端请求伪造 &a…

【pandas】教程:9-如何轻松处理时间序列数据

Pandas 如何轻松处理时间序列数据 数据 本节使用的数据为 data/air_quality_no2_long.csv&#xff0c;链接为 pandas案例和教程所使用的数据-机器学习文档类资源-CSDN文库 import pandas as pd import matplotlib.pyplot as pltair_quality pd.read_csv("data/air_qua…

实战字节码-01-基础知识

开篇字节码是什么、做什么这类问题不在这里赘述&#xff0c;《实战字节码》系列旨在帮助没接触过字节码的人能够快速上手做应用开发&#xff0c;并构建字节码技术的知识骨架&#xff0c;所以不会系统地介绍字节码技术的方方面面&#xff0c;也尽量避免叙述理论和概念相关的东西…

【笔记:模拟CMOS集成电路】噪声——基本电路噪声性能(2)

【笔记&#xff1a;模拟CMOS集成电路】噪声——基本电路噪声性能&#xff08;2&#xff09;前言1 噪声——分析基础2 噪声——基本电路噪声性能2.1 MOS管噪声模型(1)电阻RG热噪声和沟道热噪声(2)衬底电阻热噪声(3)源极寄生电阻RS热噪声2.2常见组态的单级放大器噪声分析2.2.1 CS…

Python电影观众数量回归分析 随机森林 可视化 实验报告

实验报告&#xff1a;Python电影观众数量回归分析随机森林可视化-数据挖掘文档类资源-CSDN文库 前言 随着经济的发展和人民日益增长的美好生活需要的显著提升&#xff0c;看电影成为了人民群众在闲暇时光娱乐的重要途径。面对百花齐放的电影产业&#xff0c;哪些电影更能带动市…

OpenGL期末大作业——模拟太阳系(免费开源)

目录 一、项目介绍 二、配置与运行 三、项目地址 一、项目介绍 这是一个综合的openGL场景&#xff0c;模拟太阳系。场景中有光照&#xff0c;纹理等&#xff0c;并有丰富的视角控制&#xff0c;UI交互&#xff0c;比如WASD/IJKL键控制视角的移动等等。一个太阳系的场景&#…

大数据基础平台搭建-(五)Hive搭建

大数据基础平台搭建-&#xff08;五&#xff09;Hive搭建 大数据平台系列文章&#xff1a; 1、大数据基础平台搭建-&#xff08;一&#xff09;基础环境准备 2、大数据基础平台搭建-&#xff08;二&#xff09;Hadoop集群搭建 3、大数据基础平台搭建-&#xff08;三&#xff09…

Android今日头条平台隐私合规整改

头条应用管理平台开发者合规指引&#xff1a;https://open.oceanengine.com/labels/7/docs/1730079845340164头条审核合规的app&#xff0c;需要具备以下条件&#xff1a;用户协议弹窗抖音隐私政策&#xff08;模板示例&#xff09;&#xff1a;https://sf3-cdn-tos.douyinstat…

别告诉我你只知道waitnotify,不知道parkunpark???

目录 park&unpark wait,notify 和 park,unpark的区别 park unpark 原理 先调用park的情况 先调用park,在调用unpark的情况 先调用unpark,在调用park的情况 park&unpark park和unpark都是LockSupport的方法,park用于暂停当前线程的运行,而unpark用于恢复该线程的…

服务机器人“众生相”

在多种因素的共同作用下&#xff0c;早年间经常出现在科幻片中的机器人已然穿越荧屏来到了现实世界&#xff0c;为人们的日常生活增添了几分便利。比如&#xff0c;在家庭场景中&#xff0c;扫地机器人帮助人们解放双手&#xff1b;在餐饮场景中&#xff0c;送餐机器人为顾客提…

C语言--探索函数栈帧的创建与销毁

目录 为main函数开辟栈帧 创建变量 传参 为自定义函数开辟栈帧 返回 局部变量是怎么创建的&#xff1f;为什么局部变量的值是随机值&#xff1f;函数是怎么传参的&#xff1f;形参与实参的关系&#xff1f;函数怎么调用与返回&#xff1f; 我们用VS2013的环境进行探索…