MyBatis操作数据库

news2024/12/26 12:21:28

目录

MyBatis

功能架构

学习MyBatis

第一个MyBatis查询

1、创建数据库和表

2、搭建MyBatis开发环境

2.1、在项目中添加MyBatis框架

2.2、配置数据库连接信息

2.3、配置MyBatis中xml的保存路径(规则)

3、添加业务代码

3.1、创建实体类

3.2、构建Mapper层的代码实现(接口+XML)

SpringBoot单元测试

1、优点

2、执行单元测试

2.1、生成单元测试

2.2、添加单元测试的代码

1、添加用户

1.1、在接口中声明方法

1.2、在xml中提供实现

1.3、后端实现

1.4、测试

2、添加并返回用户的自增ID

2.1、在接口中声明方法

2.2、在xml中提供实现

2.3、后端实现

2.4、测试

3、修改用户信息(姓名)

3.1、在接口中声明方法

3.2、在xml中提供实现

3.3、后端实现

3.4、测试

4、删除用户信息

4.1、在接口中声明方法

4.2、在xml中提供实现

4.3、后端实现

4.4、测试

5、查询所有用户信息

5.1、在接口中声明方法

5.2、在xml中提供实现

5.3、后端实现

查询操作

1、单表查询

1.1、参数占位符#{}和{}

1.2、${}的优点

1.3、SQL注入

1.4、like查询

2、多表查询

2.1、返回类型:resultType

2.2、返回字典映射:resultMap

2.3、一对一的表映射

2.4、一对多

动态SQL使用

1、<if>标签

2、<trim>标签

3、<where>标签

4、<set>标签

5、<foreach>标签


MyBatis

MyBatis 是一款优秀的持久层框架,它支持定制化 SQL、存储过程以及高级映射。MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录。

功能架构

Mybatis的功能架构分为三层:

(1)API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。

(2)数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。

(3)基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。

学习MyBatis

1、配置MyBatis开发环境

2、使用MyBatis模式和语法操作数据库

第一个MyBatis查询

1、创建数据库和表

-- 创建数据库
drop database if exists mycnblog;
create database mycnblog DEFAULT CHARACTER SET utf8mb4;

-- 使用数据数据
use mycnblog;

-- 创建表[用户表]
drop table if exists  userinfo;
create table userinfo(
    id int primary key auto_increment,
    username varchar(100) not null,
    password varchar(32) not null,
    photo varchar(500) default '',
    createtime datetime,
    updatetime datetime,
    `state` int default 1
) default charset 'utf8mb4';

-- 创建文章表
drop table if exists  articleinfo;
create table articleinfo(
    id int primary key auto_increment,
    title varchar(100) not null,
    content text not null,
    createtime datetime,
    updatetime datetime,
    uid int not null,
    rcount int not null default 1,
    `state` int default 1
)default charset 'utf8mb4';

-- 创建视频表
drop table if exists videoinfo;
create table videoinfo(
  	vid int primary key,
  	`title` varchar(250),
  	`url` varchar(1000),
		createtime datetime,
		updatetime datetime,
  	uid int
)default charset 'utf8mb4';

-- 添加一个用户信息
INSERT INTO `mycnblog`.`userinfo` (`id`, `username`, `password`, `photo`, `createtime`, `updatetime`, `state`) VALUES 
(1, 'admin', 'admin', '', '2021-12-06 17:10:48', '2021-12-06 17:10:48', 1);

-- 文章添加测试数据
insert into articleinfo(title,content,uid)
    values('Java','Java正文',1);
    
-- 添加视频
insert into videoinfo(vid,title,url,uid) values(1,'java title','http://www.baidu.com',1);

2、搭建MyBatis开发环境

2.1、在项目中添加MyBatis框架

老项目中添加MyBatis

新项目中添加MyBatis框架

2.2、配置数据库连接信息

spring.datasource.url=jdbc:mysql://localhost:3306/mycnblog?characterEncoding=utf8&useSSL=false
spring.datasource.username=root
spring.datasource..password=19930112
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

2.3、配置MyBatis中xml的保存路径(规则)

MyBatis组成:

1、接口(表的所有操作方法)->给程序其他类的调用

2、XML实现接口->写具体SQL语句 

3、添加业务代码

实现MyBatis查询所有用户的功能

3.1、创建实体类

@Data
public class Userinfo {
    private int id;
    private String username;
    private String password;
    private String photo;
    private LocalDateTime createtime;
    private LocalDateTime updatetime;
    private int state;
}

3.2、构建Mapper层的代码实现(接口+XML)

先创建接口

@Mapper
public interface UserMapper {

    /*
    根据用户id查询
     */
    Userinfo getUserById(Integer id);

}

创建xml实现

实现服务层

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    public Userinfo getUserById(Integer id){
        return userMapper.getUserById(id);
    }
}

实现控制器

@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping("/getUserById")
    public Userinfo getUserById(Integer id){
        if (id==null) return null;
        return userService.getUserById(id);
    }
}

SpringBoot单元测试

1、优点

1、方便、快捷测试一个功能模块;

2、在打包时会运行所有的单元测试,只有所有的单元测试都通过之后才能正常的打包,这个过程可以减少问题发生的概率;

3、使用单元测试可以在不污染数据库数据的情况下,来测试某个功能的正确性

2、执行单元测试

2.1、生成单元测试

单击右键

2.2、添加单元测试的代码

后端实现 

@SpringBootTest  //表明当前单元测试是运行在Spring Boot环境中的
class UserMapperTest {

    //注入测试对象(属性注入)
    @Autowired
    private UserMapper userMapper;

    @Test
    void getUserById() {
        //添加单元测试的运行代码
        Userinfo userinfo=userMapper.getUserById(1);
        System.out.println(userinfo);
        Assertions.assertEquals("admin",userinfo.getUsername());
    }
}

前端实现

MyBatis增删改查操作

@Transactional

在不污染数据库的前提下进行测试功能是否正确

1、添加用户

1.1、在接口中声明方法

    /*
    添加用户信息
     */
    int add(Userinfo userinfo);

1.2、在xml中提供实现

    <insert id="add">
        insert into userinfo(username,password,createtime,updatetime)
        values(#{username},#{password},#{createtime},#{updatetime})
    </insert>

1.3、后端实现

    @Test
    void add() {
        //构造对象并设置相应的值
        Userinfo userinfo=new Userinfo();
        userinfo.setUsername("边伯贤");
        userinfo.setPassword("1992");
        userinfo.setCreatetime(LocalDateTime.now());
        userinfo.setUpdatetime(LocalDateTime.now());
        //调用MyBatis添加方法执行添加操作
        int result=userMapper.add(userinfo);
        System.out.println("添加:"+result);
        Assertions.assertEquals(1,result);
    }

1.4、测试

2、添加并返回用户的自增ID

2.1、在接口中声明方法

    /*
    添加并返回用户的自增ID
     */
    int addGetId(Userinfo userinfo);

2.2、在xml中提供实现

    <insert id="addGetId" useGeneratedKeys="true" keyProperty="id">
        insert into userinfo(username,password,createtime,updatetime)
        values(#{username},#{password},#{createtime},#{updatetime})
    </insert>

2.3、后端实现

    @Test
    void addGetId() {
        //构造对象并设置相应的值
        Userinfo userinfo=new Userinfo();
        userinfo.setUsername("郑秀晶");
        userinfo.setPassword("1994");
        userinfo.setCreatetime(LocalDateTime.now());
        userinfo.setUpdatetime(LocalDateTime.now());
        //调用MyBatis添加方法执行添加操作
        int result=userMapper.addGetId(userinfo);
        System.out.println("添加:"+result);
        int uid=userinfo.getId();
        System.out.println("用户id:"+uid);
        Assertions.assertEquals(1,result);
    }

2.4、测试

3、修改用户信息(姓名)

3.1、在接口中声明方法

    /*
    修改
     */
    int upUserName(Userinfo userinfo);

3.2、在xml中提供实现

    <update id="upUserName">
        update userinfo set username=#{username} where id=#{id}
    </update>

3.3、后端实现

    @Test
    void upUserName() {
        //构造对象并设置相应的值
        Userinfo userinfo=new Userinfo();
        userinfo.setId(3);
        userinfo.setUsername("嘟嘟");
        int result=userMapper.upUserName(userinfo);
        System.out.println("修改:"+userinfo);
    }

3.4、测试

4、删除用户信息

4.1、在接口中声明方法

    /*
    删除
     */
    int delById(@Param("id") Integer id);

4.2、在xml中提供实现

    <delete id="delById">
        delete from userinfo where id=#{id}
    </delete>

4.3、后端实现

    @Test
    void delById() {
        Integer id=4;
        int result=userMapper.delById(id);
        System.out.println("删除:"+result);
    }

4.4、测试

5、查询所有用户信息

5.1、在接口中声明方法

    /*
    查询全部
     */
    List<Userinfo> getAll();

5.2、在xml中提供实现

    <select id="getAll" resultType="com.example.demo.entity.Userinfo">
        select * from userinfo
    </select>

5.3、后端实现

    @Test
    void getAll() {
        List<Userinfo> list=userMapper.getAll();
        Assertions.assertEquals(1,list.size());
    }

查询操作

1、单表查询

1.1、参数占位符#{}和{}

#{}:预编译处理

${}:字符直接替换

预编译处理是指: MyBatis 在处理#()时,会将SQL中的#0}替换为?号,使用PreparedStatement的set方法来赋值。

直接替换:是MyBatis 在处理${0}时,就是把${}替换成变量的值。

区别:

1、${}存在SQL注入问题,而#{}不存在;

2、${}直接替换,#{}是预处理 

1.2、${}的优点

 它会把其内部变量解析为字符串值拼接到一条语句上,不会做其余的处理,例如加''

1.3、SQL注入

1.4、like查询

like查询要使用concat()连接

List<Userinfo> getListByName(@Param("username") String username);
    <select id="getListByName" resultType="com.example.demo.entity.Userinfo">
        select * from userinfo where username like concat('%',#{username},'%')
    </select>
    @Test
    void getListByName() {
        String username="伯";
        List<Userinfo> list=userMapper.getListByName(username);
        System.out.println("list:"+list);
    }

2、多表查询

2.1、返回类型:resultType

数据库表中的字段名和实体类中的属性完全一致时,才能使用,否则会出现数据不显示的情况

2.2、返回字典映射:resultMap

使用场景:实现程序中属性和表中字段的映射功能(当程序中的属性和表的字段不一致时,可以强行的映射到一起)

当程序中的属性和数据库的字段名不一致时的解决方案:

1、使用resultMap标签;

2、使用数据库别名as重命名 

    <select id="getAll" resultType="com.example.demo.entity.Userinfo">
        select id,username as name,password,photo,createtime,updatetime,state from userinfo
    </select>

2.3、一对一的表映射

使用<association>标签

联表查询

@Data
public class Articleinfo {
    private int id;
    private String title;
    private String content;
    private String createtime;
    private String updatetime;
    private int uid;
    private int rcount;
    private int state;
}
@Data
public class ArticleinfoVO extends Articleinfo{
    private String username;
}
@Mapper
public interface ArticleMapper {

    ArticleinfoVO getById(@Param("id") Integer id);
}
    <select id="getById" resultType="com.example.demo.entity.vo.ArticleinfoVO">
        select a.*,u.username from articleinfo a
        left join userinfo u on u.id=a.uid
        where a.id=#{id}
    </select>
@SpringBootTest
class ArticleMapperTest {

    @Autowired
    private ArticleMapper articleMapper;

    @Test
    void getById() {
        ArticleinfoVO articleinfoVO=articleMapper.getById(1);
        System.out.println(":"+articleinfoVO);
    }
}

问题:扩展类 继承了基类,但是在查询时,只展示出了扩展类的字段,而没有展示基础类的字段

在扩展类页面单击右键

@Data
public class ArticleinfoVO extends Articleinfo implements Serializable{
    private String username;

    @Override
    public String toString() {
        return "ArticleinfoVO{" +
                "username='" + username + '\'' +
                "} " + super.toString();
    }
}

2.4、一对多

使用<collection>标签

联表查询语句(left.join/inner join)+XXXVO

动态SQL使用

能够满足复杂条件的sql连接 

1、<if>标签

语法:

<if test=“参数名!=null”>

...

</if>

test会产生一个boolean类型的结果,如果是true,那么执行if标签里边的内容,如果是false,那么就不执行if标签里边的内容

    int add2(Userinfo userinfo);
    <insert id="add2">
        insert into userinfo(username,
        <if test="photo!=null">
            photo;
        </if>
        password)
        values(#{username},
        <if test="photo!=null">
            #{photo},
        </if>
        #{password})
    </insert>
    @Test
    void add2() {
        Userinfo userinfo=new Userinfo();
        userinfo.setUsername("krystal");
        userinfo.setPhoto(null);
        userinfo.setPassword("1994");
        int result=userMapper.add2(userinfo);
        System.out.println("结果是"+result);
    }

2、<trim>标签

 一般用于去除 SQL 语句中多余的 AND 关键字、逗号,或者给 SQL 语句前拼接 where、set 等后缀,可用于选择性插入、更新、删除或者条件查询等操作。 

语法:

<trim prefix="(" suffix=")" suffixOverrides=",">
    <if test="username!=null">
        username,
    </if>
    <if test="password!=null">
        password,
    </if>
    <if test="photo!=null">
        photo,
    </if>
</trim>

prefix是指在最前边加上某个内容

suffix是指在最后边加上某个内容

suffixoverrides 是指如果做后边是某个值时就去掉

    int add3(Userinfo userinfo);
    <insert id="add3">
        insert into userinfo
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username!=null">
                username,
            </if>
            <if test="password!=null">
                password,
            </if>
            <if test="photo!=null">
                photo,
            </if>
        </trim>
        values
        <trim prefix="(" suffix=")" suffixOverrides=",">
            <if test="username!=null">
                #{username},
            </if>
            <if test="password!=null">
                #{password},
            </if>
            <if test="photo!=null">
                #{photo},
            </if>
        </trim>
    </insert>
    @Test
    void add3() {
        Userinfo userinfo=new Userinfo();
        userinfo.setUsername("sehun");
        userinfo.setPassword("1994");
        userinfo.setPhoto("exo.jpg");
        int result=userMapper.add3(userinfo);
        System.out.println("添加:"+result);
    }

3、<where>标签

语法:

<where>
    <if test="username!=null">
        username=#{username}
    </if>
    <if test="password!=null">
        and password=#{password}
    </if>
</where>

特征:

1、where标签通常要配合if标签一起使用;

2、where标签会删除最前边的and关键字(不会删除最后边的);

3、where标签中如果没有内容,那么也不会生成where sql关键字 

    List<Userinfo> getListByParam(String username,String password);
    <select id="getListByParam" resultType="com.example.demo.entity.Userinfo">
        select * from userinfo
        <where>
            <if test="username!=null">
                username=#{username}
            </if>
            <if test="password!=null">
                and password=#{password}
            </if>
        </where>
    </select>

或者

        <trim prefix="where" prefixOverrides="and">
            <if test="username!=null">
                username=#{username}
            </if>
            <if test="password!=null">
                and password=#{password}
            </if>
        </trim>
    @Test
    void getListByParam() {
        List<Userinfo> list=userMapper.getListByParam("krystal","1994");
        System.out.println("list:"+list);
    }

4、<set>标签

根据传入的用户对象属性来更新用户数据,使用<set>标签来指定动态内容

语法:

<set>
    <if test="username!=null">
        username=#{username},
    </if>
    <if test="password!=null">
        password=#{password},
    </if>
    <if test="photo!=null">
        photo=#{photo}
    </if>
</set>

特征:

1、set标签通常要配合if标签一起使用;

2、set标签会自动去除最后一个英文逗号

    int update2(Userinfo userinfo);
    <update id="update2">
        update userinfo
        <set>
            <if test="username!=null">
                username=#{username},
            </if>
            <if test="password!=null">
                password=#{password},
            </if>
            <if test="photo!=null">
                photo=#{photo}
            </if>
        </set>
        where id=#{id}
    </update>
    @Test
    void update2() {
        Userinfo userinfo=new Userinfo();
        userinfo.setId(2);
        userinfo.setUsername("啵啵虎");
        userinfo.setPassword("1992");
        userinfo.setPhoto("exo.jpg");
        int result=userMapper.update2(userinfo);
        System.out.println("修改:"+result);
    }

5、<foreach>标签

对集合进行遍历时可以使用该标签

<foreach> 标签有如下属性: .

collection: 绑定方法参数中的集合,如List, Set, Map或数组对象

item:遍历时的每一个对象

open: 语句块开头的字符串

close: 语句块结束的字符串

separator: 每次遍历之间间隔的字符串

    int dels(List<Integer> ids);
    <delete id="dels">
        delete from userinfo where id in
        <foreach collection="ids" open="(" close=")" item="id" separator=",">
            #{id}
        </foreach>
    </delete>
    @Test
    void dels() {
        List<Integer> ids=new ArrayList<>();
        ids.add(4);
        ids.add(5);
        int result=userMapper.dels(ids);
        System.out.println("删除:"+result);
    }

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

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

相关文章

stack,queue

stack,queuestack的介绍和使用介绍使用模拟实现queue的介绍和使用介绍使用模拟实现priority_queue的介绍和使用介绍使用模拟实现容器适配器概念标准库中stack&#xff0c;queue的底层结构介绍deque原理缺陷deque作为stack,queue底层默认容器stack的介绍和使用 介绍 stack是适…

哪个牌子的蓝牙耳机音质好?音质比较好的蓝牙耳机排名

蓝牙耳机经过多年发展&#xff0c;无论是在外观设计还是性能配置上都有很大的进步&#xff0c;越来越多的蓝牙耳机开始注重音质表现&#xff0c;逐渐有HIFI音质、无损音质出现在大众视野。那么哪个牌子的蓝牙耳机音质好&#xff1f;接下来&#xff0c;我来给大家分享几款音质比…

【H2实践】之 SpringBoot 与 H2 数据交互

一、目标 本文是【H2实践】之认识 H2&#xff0c;【H2实践】之 SpringBoot 整合的后续。前文分别介绍了 H2 及其简单使用&#xff0c;并完成了 H2 与 SpringBoot 的整合。本文将紧接 【H2实践】之 SpringBoot 整合 探索实用 SpringBoot 结合 JPA 通过 web 接口操作 H2 数据库的…

Python数据分析案例22——财经新闻可信度分析(线性回归,主成分回归,随机森林回归)

本次案例还是适合人文社科领域&#xff0c;金融或者新闻专业。本科生做线性回归和主成分回归就够了&#xff0c;研究生还可以加随机森林回归&#xff0c;其方法足够人文社科领域的硕士毕业论文了。 案例背景 有八个自变量&#xff0c;[微博平台可信度,专业性,可信赖性,转发量,…

Java对象结构与内置锁

Java对象结构与内置锁 Java内置锁的很多重要信息都存放在对象结构中 1.Java对象结构 Java对象包括三部分&#xff1a;对象头、实例数据和对齐字节 对象头&#xff1a; 第一个字段叫做Mark Word&#xff0c;用于存储自身运行时数据&#xff0c;例如GC标志位&#xff0c;哈希…

P1120 小木棍(搜索+剪枝)

题目链接&#xff1a;P1120 小木棍 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 样例输入&#xff1a; 9 5 2 1 5 2 1 5 2 1 样例输出&#xff1a; 6 分析&#xff1a;这道题一看数据范围就知道是搜索&#xff0c;但关键是需要剪枝。 首先我们求出所有木棍的长度和&am…

什么是刺猬理念

一、什么是刺猬理念刺猬理念是指把复杂的世界简化成单个有组织性的观点&#xff0c;一条基本原则或一个基本理念&#xff0c;发挥统帅和指导作用。核心是把事情简单化&#xff0c;把所有的挑战和进退维谷的局面压缩为简单的。二、刺猬理念的寓言故事狐狸是一种狡猾的动物&#…

Maix Bit(K210)保姆级入门上手教程---自训练模型之云端训练

Maix Bit&#xff08;K210&#xff09;保姆级入门上手教程系列 Maix Bit&#xff08;K210&#xff09;保姆级入门上手教程—环境搭建 Maix Bit&#xff08;K210&#xff09;保姆级入门上手教程—外设基本使用 这是K210快速上手系列文章&#xff0c;主要内容是&#xff0c;介绍…

《机器学习》基础概念之【P问题】与【NP问题】

《机器学习》基础概念之【P问题】与【NP问题】 这里写目录标题《机器学习》基础概念之【P问题】与【NP问题】一、多项式&时间复杂度1.1. 多项式1.2.时间复杂度二、P问题 & NP问题2.1. P问题2.2.NP问题2.3.举例理解NP问题-TSP旅行商推销问题三、NP-hard问题&NP-C问题…

PMP项目管理项目成本管理

目录1 项目成本管理概述2 规划成本管理3 估算成本4 制定预算5 控制成本1 项目成本管理概述 项目成本管理包括为使项目在批准的预算内完成而对成本进行规划、估算、预测、融资、筹资、管理和控制的各个过程&#xff0c;从而确保项目在批准的预算内完工。核心概念 项目成本管理旨…

vuex getters的作用和使用(求平均年龄),以及辅助函数mapGetters

getters作用&#xff1a;派生状态数据mapGetters作用&#xff1a;映射getters中的数据使用&#xff1a;方法名自定义&#xff0c;系统自动注入参数&#xff1a;state&#xff0c;每一个方法中必须有return&#xff0c;其return的结果被该方法名所接收。在state中声明数据listst…

PyTorch深度学习实战 | 计算机视觉

深度学习领域技术的飞速发展&#xff0c;给人们的生活带来了很大改变。例如&#xff0c;智能语音助手能够与人类无障碍地沟通&#xff0c;甚至在视频通话时可以提供实时翻译&#xff1b;将手机摄像头聚焦在某个物体上&#xff0c;该物体的相关信息就会被迅速地反馈给使用者&…

【教学典型案例】21.面向对象复用、面向对象实现、立体化权限落地

目录一&#xff1a;背景介绍1、针对于激励配置的功能体现出来的&#xff1a;面向对象的思想就可以实现极大程度的复用性的问题2、脱离学习通设计图&#xff0c;过程化&#xff0c;如何用面向对象的思想来去组织管理流程图3、词云位置记录定制化二&#xff1a;思路&方案1、面…

CSDN每日一练(编程题)

目录1. 2023/1/31-非降序数组(类型&#xff1a;数组&排序 难度&#xff1a;中等)2. 2023/2/1- 走楼梯(类型&#xff1a;递归&循环 难度&#xff1a;中等)3. 2023/2/1-蛇形矩阵(难度&#xff1a;困难)4. 2023/2/2-奇偶排序(类型&#xff1a;数组&奇偶排序 难度&…

环境配置之Keepass

前言很久以前&#xff0c;就有了想要一个自己密码管理器的念头。毕竟&#xff0c;即使浏览器能记住各个网站的账号密码&#xff0c;但是在登录单独客户端的时候&#xff0c;仍然要翻找密码。为了省事&#xff0c;也曾经是一个密码走天下。然后被劫持了QQ给同学发黄色小网站&…

手写Mybatis

Mybatis总体流程 (1)加载配置并初始化触发条件:加载配置文件 配置来源于两个地方&#xff0c;一个是配置文件(主配置文件conf. xml, mapper文件*.xml),一个是java代码中的注解&#xff0c;将主配置文件内容解析封装到Configuration,将sql的配置信息加载成为一个mappedstateme…

ReentrantLock源码分析(一)加锁流程分析

一、ReetrantLock的使用示例 static ReentrantLock lock new ReentrantLock(); public static void main(String[] args) throws InterruptedException { new Thread(ClassLayOutTest::reentrantLockDemo, "threadA").start(); Thread.sleep(1000);…

Netty权威指南总结(二)

三、Netty代码相关&#xff1a;(四) EventLoop与EventLoopGroup&#xff1a;Netty的Nio线程是NioEventLoop。1. Reactor线程模型&#xff1a;Reactor模型的三个角色&#xff1a;Reactor&#xff1a;把IO事件分配给对应的Handler处理&#xff0c;功能像是调度器。Acceptor【饿渴…

【C++】C++核心编程(一)---内存四区

C程序在执行时&#xff0c;将内存大方向划分为4个区域 代码区 存放函数体的二进制代码&#xff0c;由操作系统进行管理全局区 存放全局变量和静态变量以及常量(字符串常量、全局常量)栈区 由编译器自动分配释放&#xff0c;存放函数的参数值、局部变量等堆区 由程序员分配和释…

jenkins问题

目录 python 不是内部或外部命令&#xff0c;也不是可运行的程序 ‘cmd’ 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 git 不是内部或外部命令&#xff0c;也不是可运行的程序或批处理文件。 pywintypes.com_error: (-2147024891, ‘拒绝访问。’, None,…