Mybatis技术原理详解之:使用Mapper形式和注解驱动的复杂映射开发

news2024/12/23 14:35:27

Mybatis技术原理详解之:使用Mapper形式和注解驱动的复杂映射开发

Mapper形式的复杂映射开发

一对一查询

一对一查询的模型

⽤户表和订单表的关系为,⼀个⽤户有多个订单,⼀个订单只从属于⼀个⽤户

⼀对⼀查询的需求:查询⼀个订单,与此同时查询出该订单所属的⽤户

在这里插入图片描述

建表语句
create table user
(
  `id` int(11),
  `username` varchar(30),
  `password` varchar(30),
  `birthday` varchar(30)
)

insert into user values (1, 'lisi', '123', '2023-11-01');
insert into user values (2, 'zhangsan', '123', '2023-11-01');


create table `order`
(
  `id` int(11),
  `order_time` datetime,
  `total` float,
  `uid` int
)

insert into `order` values (1, '2023-11-03 12:00:00', 10.0, 1);
insert into `order` values (2, '2023-11-03 12:00:00', 20.0, 1);
insert into `order` values (3, '2023-11-03 12:00:00', 20.0, 2);

构造查询语句

select *, o.id oid from `user` u left join `order` o on u.id = o.uid

查询结果如下所示:

!在这里插入图片描述

创建Order和User实体
@ToString
@Data
public class Order {
    private int id;
    private Date orderTime;
    private double total;

    // 标识每个订单对应的唯一用户
    private User user;

}

@ToString
@Data
public class User {
    
    private int id;
    private String username;
    private String password;
    private Date birthday;

}
创建OrderMapper接口和OrderMapper.xml

创建OrderMapper接口:

public interface UserMapper {
    List<Order> oneToOneQuery();
}

创建OrderMapper.xml文件:

<mapper namespace="com.netease.mail.data.dao.UserMapper">
    
    <resultMap id="orderMap" type="com.netease.mail.data.pojo.Order">
        <result column="id" javaType="java.lang.Integer" property="id"></result>
        <result column="order_time" javaType="java.util.Date" property="orderTime"></result>
        <result column="total" javaType="java.lang.Double" property="total"></result>
        <association property="user" javaType="com.netease.mail.data.pojo.User">
            <result column="uid" javaType="java.lang.Integer" property="id"></result>
            <result column="username" javaType="java.lang.String" property="username"></result>
            <result column="password" javaType="java.lang.String" property="password"></result>
            <result column="birthday" javaType="java.util.Date" property="birthday"></result>
        </association>
    </resultMap>
  
      <select id="oneToOneQuery" resultMap="orderMap">
        select *, u.id uid from `order` o left join `user` u on o.uid = u.id
    </select>
  </mapper>
测试结果
public class MybatisDemo {

    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        SqlSession sqlSession = sqlSessionFactory.openSession();

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

        System.out.println("---------一对一级联查询-----------");
        // 一对一级联查询
        oneToOneMapping(userMapper);


    }

    public static void oneToOneMapping(UserMapper userMapper) {
        // 一对一关联查询
        List<Order> orders = userMapper.oneToOneQuery();
        orders.forEach(System.out::println);
    }

}

执行结果如下所示:

在这里插入图片描述

可以看到,结果打印出了每个订单与相应用户的关联信息。

一对多查询

⽤户表和订单表的关系为,⼀个⽤户有多个订单,⼀个订单只从属于⼀个⽤户

⼀对多查询的需求:查询⼀个⽤户,与此同时查询出该⽤户具有的订单

在这里插入图片描述

构造查询语句
select *, o.id oid from `user` u left join `order` o on u.id = o.uid

查询结果如下所示:

在这里插入图片描述

修改User实体
@ToString
@Data
public class Order {
    private int id;
    private Date orderTime;
    private double total;

    // 标识每个订单对应的唯一用户
    private User user;

}

@ToString
@Data
public class User {
    
    private int id;
    private String username;
    private String password;
    private Date birthday;

    // 标识当前用户具有哪些订单
    private List<Order> orderList;
}
创建UserMapper接口和xml语句

UserMapper.java

public interface UserMapper {

    List<Order> oneToOneQuery();

    List<User> oneToMultiQuery();
}

UserMapper.xml

<mapper namespace="com.netease.mail.data.dao.UserMapper">
    <resultMap id="userMap" type="com.netease.mail.data.pojo.User">
        <result column="id" javaType="java.lang.Integer" property="id"></result>
        <result column="username" javaType="java.lang.String" property="username"></result>
        <result column="password" javaType="java.lang.String" property="password"></result>
        <result column="birthday" javaType="java.util.Date" property="birthday"></result>
        <collection property="orderList" ofType="com.netease.mail.data.pojo.Order">
            <result column="oid" javaType="java.lang.Integer" property="id"></result>
            <result column="order_time" javaType="java.util.Date" property="orderTime"></result>
            <result column="total" javaType="java.lang.Double" property="total"></result>
        </collection>
    </resultMap>

    <select id="oneToMultiQuery" resultMap="userMap">
        select *, o.id oid from `user` u left join `order` o on u.id = o.uid
    </select>

</mapper>
测试结果

测试代码如下:

    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        SqlSession sqlSession = sqlSessionFactory.openSession();

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

        System.out.println("---------一对多级联查询-----------");
        // 一对多级联关系查询
        oneToMultiMapping(userMapper);

    }
    public static void oneToMultiMapping(UserMapper userMapper) {

        // 一对多级联关系查询
        List<User> users = userMapper.oneToMultiQuery();
        users.forEach( user -> {
            System.out.println(user.getUsername());
            List<Order> orderList = user.getOrderList();
            orderList.forEach(System.out::println);
        });
    }

代码执行打印信息如下所示:

在这里插入图片描述

从上面的打印信息中可以看到,一对多的映射查询,在UserMapper.xml中设置了<collection>标签后,会将查询结果中<result>标签字段相同的行进行合并,并将合并后的<collection>标签下的<result>字段转换映射到设置的实体类属性List集合中, 从而实现一对多的映射查询。

多对多映射查询

多对多查询的模型

⽤户表和⻆⾊表的关系为,⼀个⽤户有多个⻆⾊,⼀个⻆⾊被多个⽤户使⽤

多对多查询的需求:查询⽤户同时查询出该⽤户的所有⻆⾊

在这里插入图片描述

构造查询语句
select u.*,r.*,r.id rid from user u left join user_role ur on u.id=ur.user_id
left join role r on ur.role_id=r.id

查询结果如下所示:

在这里插入图片描述

创建Role实体、修改User实体
@Data
@ToString
public class Role {

    private int id;
    private String roleName;
}

@ToString
@Data
public class User {
    
    private int id;
    private String username;
    private String password;
    private Date birthday;

    // 标识当前用户具有哪些订单
    private List<Order> orderList;

    // 标识当前用户具有哪些角色
    private List<Role> roleList;
}

添加UserMapper接口方法和xml语句

UserMapper.java

public interface UserMapper {

    List<Order> oneToOneQuery();

    List<User> oneToMultiQuery();

    List<User> multiToMulti();

}

UserMapper.xml

<mapper namespace="com.netease.mail.data.dao.UserMapper">
    
    <resultMap id="orderMap" type="com.netease.mail.data.pojo.Order">
        <result column="id" javaType="java.lang.Integer" property="id"></result>
        <result column="order_time" javaType="java.util.Date" property="orderTime"></result>
        <result column="total" javaType="java.lang.Double" property="total"></result>
        <association property="user" javaType="com.netease.mail.data.pojo.User">
            <result column="uid" javaType="java.lang.Integer" property="id"></result>
            <result column="username" javaType="java.lang.String" property="username"></result>
            <result column="password" javaType="java.lang.String" property="password"></result>
            <result column="birthday" javaType="java.util.Date" property="birthday"></result>
        </association>
    </resultMap>
    
    <resultMap id="userMap" type="com.netease.mail.data.pojo.User">
        <result column="id" javaType="java.lang.Integer" property="id"></result>
        <result column="username" javaType="java.lang.String" property="username"></result>
        <result column="password" javaType="java.lang.String" property="password"></result>
        <result column="birthday" javaType="java.util.Date" property="birthday"></result>
        <collection property="orderList" ofType="com.netease.mail.data.pojo.Order">
            <result column="oid" javaType="java.lang.Integer" property="id"></result>
            <result column="order_time" javaType="java.util.Date" property="orderTime"></result>
            <result column="total" javaType="java.lang.Double" property="total"></result>
        </collection>
    </resultMap>


    <resultMap id="roleMap" type="com.netease.mail.data.pojo.User">
        <result column="id" javaType="java.lang.Integer" property="id"></result>
        <result column="username" javaType="java.lang.String" property="username"></result>
        <result column="password" javaType="java.lang.String" property="password"></result>
        <result column="birthday" javaType="java.util.Date" property="birthday"></result>
        <collection property="roleList" ofType="com.netease.mail.data.pojo.Role">
            <result column="rid" javaType="java.lang.Integer" property="id"></result>
            <result column="role_name" javaType="java.lang.String" property="roleName"></result>
        </collection>
    </resultMap>
    

    <select id="oneToOneQuery" resultMap="orderMap">
        select *, u.id uid from `order` o left join `user` u on o.uid = u.id
    </select>

    <select id="oneToMultiQuery" resultMap="userMap">
        select *, o.id oid from `user` u left join `order` o on u.id = o.uid
    </select>

    <select id="multiToMulti" resultMap="roleMap">
        select u.*,r.*,r.id rid from user u left join user_role ur on u.id=ur.user_id
        inner join role r on ur.role_id=r.id
    </select>

</mapper>
测试结果

测试代码如下所示:

public class MybatisDemo {

    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        SqlSession sqlSession = sqlSessionFactory.openSession();

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

        System.out.println("---------一对一级联查询-----------");
        // 一对一级联查询
        oneToOneMapping(userMapper);

        System.out.println("---------一对多级联查询-----------");
        // 一对多级联关系查询
        oneToMultiMapping(userMapper);

        System.out.println("---------多对多级联查询-----------");
        multiToMultiMapping(userMapper);


    }

    public static void oneToOneMapping(UserMapper userMapper) {
        // 一对一关联查询
        List<Order> orders = userMapper.oneToOneQuery();
        orders.forEach(System.out::println);
    }

    public static void oneToMultiMapping(UserMapper userMapper) {

        // 一对多级联关系查询
        List<User> users = userMapper.oneToMultiQuery();
        users.forEach( user -> {
            System.out.println(user.getUsername());
            List<Order> orderList = user.getOrderList();
            orderList.forEach(System.out::println);
        });
    }

    // 多对多级联关系查询
    public static void multiToMultiMapping(UserMapper userMapper) {
        List<User> users = userMapper.multiToMulti();
        users.forEach(user -> {
            System.out.println(user.getUsername());
            List<Role> roleList = user.getRoleList();
            roleList.forEach(System.out::println);
        });
    }

}

上面展示了一对一、一对多、多对多的整体测试代码,单独执行多对多的级联关系查询结果如下所示:

在这里插入图片描述

根据上面的查询结果看分析得到,多对多的查询结果封装与一对多的原理类似。因为在关联查询时,无论是left join还是right join,在单次查询中,实际上都是一对多的查询逻辑。比如在上面的查询案例中,以user表出发做left join,此时在上面的多对多模型中,相当于是一个用户对应多个角色,所以查询结果仍然是一对多模型的查询原理。

使用注解的形式完成复杂映射开发

这⼏年来注解开发越来越流⾏,Mybatis也可以使⽤注解开发⽅式,这样我们就可以减少编写Mapper映射⽂件了。常用的Mybatis注解:

@Insert:实现新增

@Update:实现更新

@Delete:实现删除

@Select:实现查询

@Result:实现结果集封装

@Results:可以与@Result ⼀起使⽤,封装多个结果集

@One:实现⼀对⼀结果集封装

@Many:实现⼀对多结果集封装

实现复杂关系映射之前我们可以在映射⽂件中通过配置来实现,使⽤注解开发后,我们可以使⽤@Results注解,

@Result注解,@One注解,@Many注解组合完成复杂关系的配置

在这里插入图片描述

在使用Mybatis注解的方式对上面采用Mapper的方式进行改造之前,由于我们不需要UserMapper.xml文件了,因此,需要修改MyBatis的核⼼配置⽂件,加载使⽤了注解的Mapper接⼝即可。

    <mappers>
        <mapper resource="mapper/UserMapper.xml"/>
    </mappers>
    
    替换为

    <mappers>
        <mapper class="com.netease.mail.data.dao.UserMapper"/>
    </mappers>

或者指定扫描包含映射关系的接⼝所在的包也可以:

    <mappers>
        <package name="com.netease.mail.data.dao"/>
    </mappers>

接下来,我们将使用Mybatis注解的方式来实现上面采用Mapper方式的功能,用实际案例来介绍Mybatis注解开发的基本原理和过程

一对一查询

一对一查询模型和User、Order实体类与上面案例中的一致。需要修改的是创建UserMapper.javaOrderMapper.java两个接口类:

使用注解配置Mapper

编写OrderMapper接口方法查询order表

public interface OrderMapper {
    @Select("select * from `order`")
    @Results({
            @Result(id=true, property = "id", column = "id"),
            @Result(property = "orderTime", column = "order_time"),
            @Result(property = "total", column = "total"),
            @Result(property = "user", column = "uid",
                    javaType = User.class,
                    one=@One(select = "com.netease.mail.data.dao.UserMapper.selectUserById"))
    })
    List<Order> findAll();
}

@Results注解代替的标签就相当于是<resultMap>,@Result注解代替的标签就相当于是<result>。需要注意的就是@One注解,该注解代替了<assocation>标签,利用select语句来查询关联表的信息。这里@One注解里的column属性的uid,是作为关联参数传递到UserMapper.selectUserById的sql方法中,用于替换占位符的。

编写UserMapper接口方法,根据传入的uid,查询用户信息并返回

public interface UserMapper {

    @Select("select * from user where id = #{id}")
    User selectUserById(@Param("id") int id);
}

编写测试方法
public class MybatisDemo {

    private static OrderMapper orderMapper;
    private static UserMapper userMapper;

    public static void main(String[] args) throws IOException {
        InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);

        SqlSession sqlSession = sqlSessionFactory.openSession();

        userMapper = sqlSession.getMapper(UserMapper.class);
        orderMapper = sqlSession.getMapper(OrderMapper.class);


        System.out.println("---------注解驱动的一对一级联查询-----------");
        annotationOneToOneQuery();
    }

    public static void annotationOneToOneQuery() {
        List<Order> orders = orderMapper.findAll();
        orders.forEach(System.out::println);
    }

}

执行得到输出结果如下所示:

在这里插入图片描述

可以看到,我们在OrderMapper里的findAll方法中,使用注解地方式将需要关联的uid字段传入到了UserMapper的对应方法中,替换了占位符的值。

一对多查询

模型仍然以上面一对多例子中的用户和订单的关联关系为例展开。

⽤户表和订单表的关系为,⼀个⽤户有多个订单,⼀个订单只从属于⼀个⽤户

⼀对多查询的需求:查询⼀个⽤户,与此同时查询出该⽤户具有的订单

User实体与Order实体的配置与上面Mapper形式中的一对多查询的实体类属性保持一致。

使用注解配置Mapper
public interface OrderMapper {

    @Select("select * from `order` where uid = #{id}")
    List<Order> findByUid();

}

public interface UserMapper {

    @Select("select * from user")
    @Results(value = {
            @Result(id=true, property = "id", column = "id"),
            @Result(property = "username", column = "username"),
            @Result(property = "password", column = "password"),
            @Result(property = "birthday", column = "birthday"),
            @Result(property = "orderList", column = "id",
                    javaType = List.class,
                    many=@Many(select = "com.netease.mail.data.dao.OrderMapper.findByUid"))
    })
    List<User> findUserAndOrder();
}
测试结果

在这里插入图片描述

从上图可以看到,同样利用注解的方式,将关联属性在两个方法中进行传递,实现了一对多的级联查询。只是这里用的注解是@Many注解

多对多查询

多对多查询的模型同样体现在,⽤户表和⻆⾊表的关系为,⼀个⽤户有多个⻆⾊,⼀个⻆⾊被多个⽤户使⽤

多对多查询的需求:查询⽤户同时查询出该⽤户的所有⻆⾊

数据表与实体类的修改与上面Mapper形式中的保持一致。

使用注解配置Mapper
public interface UserMapper {

    @Select("select * from user")
    @Results(value = {
            @Result(id=true, property = "id", column = "id"),
            @Result(property = "username", column = "username"),
            @Result(property = "password", column = "password"),
            @Result(property = "birthday", column = "birthday"),
            @Result(property = "roleList", column = "id",
                    javaType = List.class,
                    many=@Many(select = "com.netease.mail.data.dao.RoleMapper.findByUserId"))
    })
    List<User> findUserAndRole();
}

public interface RoleMapper {

    @Select("select * from role r left join user_role ur on r.id = ur.role_id where ur.user_id = #{id}")
    @Results({
            @Result(id=true, property = "id", column = "id"),
            @Result(property = "roleName", column = "role_name")
    })
    List<Role> findByUserId();
}
测试结果

在这里插入图片描述

至此,我们实现了利用Mapper.xml文件的方式和注解驱动的两种方式,来实现Mybatis复杂映射开发的过程。利用案例来更加清晰地展示复杂映射开发的原理和过程,便于日后忘记了,可以回过头来借鉴。

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

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

相关文章

AFL入门教学

1、AFL简介 AFL&#xff08;American Fuzzy Lop&#xff09;是一个面向安全的模糊测试工具&#xff0c;它使用了一个新的编译时插桩技术和遗传算法&#xff0c;可以自动发现触发目标二进程程序的测试用例&#xff0c;从而大大提高测试代码的功能覆盖率。 AFL官网&#xff1a;…

090基于web+springboot的中小企业设备管理系统

欢迎大家关注&#xff0c;一起好好学习&#xff0c;天天向上 文章目录 一项目简介技术介绍 二、功能组成三、效果图四、 文章目录 一项目简介 本中小企业设备管理系统管理员有个人中心&#xff0c;用户管理&#xff0c;员工管理&#xff0c;设备信息管理&#xff0c;配件信息管…

计算机报错找不到msvcp110.dll无法继续执行代码怎么解决?

msvcp110.dll文件丢失是一个相当常见的问题&#xff0c;尤其是在运行某些程序或游戏时。这个问题可能会导致程序无法正常运行&#xff0c;甚至可能导致系统崩溃。那么&#xff0c;面对这样的问题&#xff0c;我们应该如何来解决呢&#xff1f;下面&#xff0c;我将分享我解决问…

LabVIEW开发实时离子温度测量

LabVIEW开发实时离子温度测量 迈向核聚变发电的漫长旅程&#xff0c;旨在提供无限的清洁能源。离子温度是产生聚变点火条件中最重要的参数之一&#xff0c;快速简单地测量离子温度的技术至关重要。特别是对于未来的聚变反应堆来说&#xff0c;需要一种使用等离子体发出的物理现…

Python基础入门例程43-NP43 判断布尔值(条件语句)

最近的博文&#xff1a; Python基础入门例程42-NP42 公式计算器&#xff08;运算符&#xff09;-CSDN博客 Python基础入门例程41-NP41 二进制位运算&#xff08;运算符&#xff09;-CSDN博客 Python基础入门例程40-NP40 俱乐部的成员&#xff08;运算符&#xff09;-CSDN博客…

【Servlet】Servlet的生命周期

目录 一、Servlet的生命周期 二、Servlet的生命周期演示图 三、线程安全问题 四、解决线程安全问题 面试题 一、Servlet的生命周期 1.类加载和实例化 Servlet容器(如Tomcat)负责加载和实例化Servlet。当容器是首次启动或首次请求某个Servlet时&#xff0c;容器就会读取w…

英语小作文模板(10招募+通知;15通知+介绍)

10招募&#xff0b;通知&#xff1a; 题目背景及要求 第一段 第二段 第三段 翻译 15通知&#xff0b;介绍 &#xff1a; 题目背景及要求 第一段 第二段 第三段 15通知&#xff0b;介绍&#xff08;2&#xff09; 第一段 第二段 第三段 重金求子通知

Python---练习:使用循环嵌套打印正等腰三角形

案例&#xff1a; 使用循环嵌套打印正等腰三角形 如图&#xff1a; 思考&#xff1a; 首先&#xff0c;给了样式&#xff0c;有几行&#xff0c;也就是明确的次数&#xff0c;所以用while循环&#xff0c;for循环是针对没有明确次数用的。 while循环基本语法&#xff1a; 结…

Python基础入门例程45-NP45 禁止重复注册(条件语句)

最近的博文&#xff1a; Python基础入门例程44-NP44 判断列表是否为空&#xff08;条件语句&#xff09;-CSDN博客 Python基础入门例程43-NP43 判断布尔值&#xff08;条件语句&#xff09;-CSDN博客 Python基础入门例程42-NP42 公式计算器&#xff08;运算符&#xff09;-C…

【电路笔记】-谐波

谐波 文章目录 谐波1、概述2、频谱分析3、已知信号4、未知信号5、总结 周期性信号并不总是完美的正弦模式&#xff0c;例如我们之前有关 正弦波的文章之一中介绍的那样。 有时&#xff0c;信号确实可以是简单正弦波的叠加&#xff0c;它们被称为复杂波形。 在本文中&#xff0…

第一章 introduction to software testing

文章目录 基本概念validation / verificationinput domain / output domaindeterministic / non-deterministicterminate / not-terminate Testing概念testing 的目的Fault, failure, error测试三要素 (3 essential pieces of information)测试输入预期输出执行测试 test execu…

AI写作神器,轻松搞定职场公文写作!

在当今数字化时代&#xff0c;人工智能技术的快速发展为各行各业带来了许多便利&#xff0c;因为AI写作的普及&#xff0c;使许多职场人士能够更加快速地撰写出高质量的公文&#xff0c;作为一家引领智能AI写作潮流的在线平台&#xff0c;boardmix博思白板以其独特的优势在这个…

D-Link账号密码泄露

构造payload&#xff1a; /getcfg.php SERVICESDEVICE.ACCOUNT&attackture%0D%0AAUTHORIZED_GROUP%3D1漏洞证明&#xff1a; 文笔生疏&#xff0c;措辞浅薄&#xff0c;望各位大佬不吝赐教&#xff0c;万分感谢。 免责声明&#xff1a;由于传播或利用此文所提供的信息、技…

CCF-CSP真题《202305-4 电力网络》思路+python,c++满分题解

想查看其他题的真题及题解的同学可以前往查看&#xff1a;CCF-CSP真题附题解大全 试题编号&#xff1a;202305-4试题名称&#xff1a;电力网络时间限制&#xff1a;1.0s内存限制&#xff1a;512.0MB问题描述&#xff1a; 问题描述 西西艾弗岛电力公司需要修建一套电网对岛上的众…

贝叶斯网络:利用变量消除(Variable Elimination)进行推理

贝叶斯网络简介 贝叶斯网络(Bayesian network)也叫贝氏网路、信念网络&#xff08;belief network&#xff09;或是有向无环图&#xff08;DAG&#xff09;模型&#xff0c;是一种概率图模型。它利用DAG的结构&#xff0c;得到一组随机变量{X1,X2,...,Xn}的条件概率分布&#…

Java中的static

目录 static修饰成员变量 静态成员变量特征 static修饰成员方法 【静态方法特性】 static成员变量初始化 就地初始化 静态代码块初始化 注意事项 static修饰成员变量 静态成员变量特征 static修饰的成员变量&#xff0c;称为静态成员变量&#xff0c;静态成员变量最大的…

matplotlib从起点出发(10)_Tutorial_10_Layout

使用受约束的绘图干净整洁地将图形合适排列。 受约束的布局会自动调整子图&#xff0c;以便刻度标签、图例和颜色条等装饰不会重叠&#xff0c;同时仍保留用户请求的逻辑布局。 受约束布局类似于“紧密布局”&#xff0c;但它要更灵活。它处理放置在多个轴上的Axes(放置颜色条…

python 命令行界面的用户交互

背景 说一千&#xff0c;道一万&#xff0c;程序是为用户服务的&#xff0c;所以在程序运行过程&#xff0c;与用户交互以获取用户的信息输入和决策确认&#xff0c;是无法避免的编程需要考虑和解决的需求。 一个简单的demo 如下的程序中&#xff0c;程序需要生成一个新的 i…

图片批量归类:告别混乱,实现高效文件管理

在日常生活中&#xff0c;我们经常需要处理大量的图片文件。这些图片可能来自于不同的设备、不同的目录&#xff0c;甚至不同的存储介质。随着时间的推移&#xff0c;这些图片文件会越来越多&#xff0c;管理起来也会越来越困难。如何高效地整理这些图片文件&#xff0c;告别混…

初步利用Ansible实现批量服务器自动化管理

1.Ansible介绍 Ansible是一款开源的自动化运维工具, 在2012年由Michael DeHaan创建, 现在由Red Hat维护。Ansible是基于Python开发的,采用YAML语言编写自动化脚本playbook, 可以在Linux、Unix等系统上运行, 通过SSH协议管理节点, 无需在被管理节点安装agent。Ansible以其简单、…