Mybatis操作数据库的两种方式:原生API

news2024/11/17 0:50:11

 mybatis操作数据的两种方式:原生api和mapper代理对象

1.mybatis的api提供的方法

  •         insert() 增加 delete() 删除  update() 更新
  •         selectOne() 返回一个数据
  •         selectList() 返回多个数据,结果类型为List
  •         selectMap() 返回多个数据,结果类型为Map
  •         select() 返回特殊格式的数据(策略+回调)

原生api总结:

        1.不用写开Connection,给?存值等繁琐的jdbc代码

        2.总清单文件只写一次,子清单文件可以写多个,都放的sql语句

        3.调用原生api,指定好sql语句的id,参数类型和结果类型即可

        4.修改sql语句只需要修改子清单文件,不用修改源代码

        5.针对查询而言,返回的数据结构(集合)丰富,不用程序员把ResultSet中的数据转换为集合对象。

mapper代理对象模式:底层用法还是原生api

2.连接数据库操作流程

(1)连接池池数据源关闭所有连接(关掉老连接)

(2)开启 jdbc

(3)创建连接connection,即mysql的连接对象

(4)seting autocommit to false开链接 ,开启事务

(5)根据方法ID在user.xml的找到对应id 的sql语句   

  • preparing预编译,(statement每个造执行计划,非常耗费时间)
  •         参数、返回值

(6)事务关闭

(7)关闭jdbc

(8)将连接还到连接池内

补充说明:

1.只要异常中的sqlSession为null,就一定是清单文件中有错误

2.给mybatis项目添加日志输出

        a.导入log4j.jar

        b.在项目的类路径下添加一个log4j.properties,logging初始化, ibatis日志管理实现适配器

连接数据库的时候可能存在的编码问题:

java.sql.SQLException: Unknown initial character set index ‘255‘ received from server.-CSDN博客

3.数据库操作

select语句提供了很丰富的结果数据结构

3.1 增删改查

 rowAffect=sqlSession.insert("insertUser",user);

 rowAffect=sqlSession.delete("deleteUserById",id);

 rowAffect=sqlSession.insert("insertUser",user);

红色标注部分为id, 根据对应Id在子清单文件中找到sql语句,并执行

xxDao.java

    public int addUser(User user);
    public int deleteUser(Integer id);
    public int updateUser(User user);

xxDaoImpl.java

public int addUser(User user) {
        int rowAffect=0;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            rowAffect=sqlSession.insert("insertUser",user);
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return rowAffect;
    }

    @Override
    public int deleteUser(Integer id) {
        int rowAffect=0;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            rowAffect=sqlSession.delete("deleteUserById",id);
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return rowAffect;
    }

    @Override
    public int updateUser(User user) {
        int rowAffect=0;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            rowAffect=sqlSession.update("updateUser",user);
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return rowAffect;
    }

user.xml子清单文件

    <!--插入用户-->
    <insert id="insertUser"
            parameterType="org.example.entity.User">
        insert into t_user(
            user_name,
            user_password,
            address)
        values(
            #{name},
            #{password},
            #{address}
        );
    </insert>
    <!--删除用户-->
    <delete id="deleteUserById"
            parameterType="java.lang.Integer">
        delete from t_user
        where id=#{id};
    </delete>
    <!--根据id更新用户-->
    <update id="updateUser"
            parameterType="org.example.entity.User">
        update t_user set
            user_name=#{name},
            user_password=#{password},
            address=#{address}
        where
            id=#{id}
    </update>

单元测试:

    @Test
    public void addUser() {
        UserDao userDao=new UserDaoImpl();
        //假数据
        User user=new User();
        user.setName("add");
        user.setPassword("654321");
        user.setAddress("测试用例");
        Integer rowAffect=userDao.addUser(user);
        System.out.println(rowAffect);
    }

    @Test
    public void deleteUser() {
        UserDao userDao=new UserDaoImpl();
        Integer rowAffect=userDao.deleteUser(3);
        System.out.println(rowAffect);
    }

    @Test
    public void updateUser() {
        UserDao userDao=new UserDaoImpl();
        //假数据
        User user=new User();
        user.setId(3);
        user.setName("addUser");
        user.setPassword("654321");
        user.setAddress("单元测试");
        Integer rowAffect=userDao.updateUser(user);
        System.out.println(rowAffect);
    }

结果展示:

增加一个数据User

​更新id=3的数据

删除id=3的数据

特别的:子清单文件中<insert>、<select>等标签并没有进行判断,Mybatis仅对语句进行判断然后执行。从底层调用来说update\insert调用的是同一个底层方法

3.2 selectOne

查询并返回一个结果

xxDao.java

   public User findUserById(Integer id);

xxDaoImpl.java

    @Override
    public User findUserById(Integer id) {
        User user=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            user=sqlSession.selectOne("findUserById",1);
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return user;
    }

user.xml

   <!--根据id获得用户信息-->
    <select id="findUserById"
            resultType="org.example.entity.User"
            parameterType="java.lang.Integer">
        select
            id,
            user_name as name,
            user_password as password,
            address
        from t_user
        where id = #{id}
    </select>

单元测试:

    @Test
    public void findUserById() {
        UserDao userDao=new UserDaoImpl();
        User user=userDao.findUserById(1);
        System.out.println(user);
    }

结果展示:

3.3selectList

查询并返回一个List类型的结果,List里的数据类型可以是业务对象类型,如User; 也可以以Map<Integer,Object> 形式返回对象信息,map中的key是属性名,值是属性值。

xxDao.java

    //返回list结构
    public List<User> findAllUser1();
    public List<Map<String,Object>> findAllUser2();

xxDaoImpl.java

 @Override
    public List<User> findAllUser1() {
        List<User> userList=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            userList=sqlSession.selectList("findAllUser1SqlId");
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return userList;
    }

    @Override
    public List<Map<String, Object>> findAllUser2() {
        List<Map<String, Object>> userList=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            userList=sqlSession.selectList("findAllUser2SqlId","id");
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return userList;
    }

user.xml

    <!--查所有返回list<User>-->
    <select id="findAllUser1SqlId"
            resultType="org.example.entity.User"
            >
        select
            id,
            user_name as name,
            user_password as password,
            address
        from t_user
    </select>

    <!--查所有返回list<Map>-->
    <select id="findAllUser2SqlId"
            resultType="java.util.Map"
    >
        select
            id,
            user_name,
            user_password,
            address
        from t_user
    </select>

单元测试:

    @Test
    public void findAllUser1() {
        UserDao userDao=new UserDaoImpl();
        List<User> userList=userDao.findAllUser1();
        for(User user:userList){
            System.out.println(user);
        }

    }

    @Test
    public void findAllUser2() {
        UserDao userDao=new UserDaoImpl();
        List<Map<String, Object>> userList=userDao.findAllUser2();
        for(Map<String, Object> user:userList){
            System.out.println(user.toString());
        }
    }

结果展示:

返回List<User>

返回List<Map<String,Object>>

3.4selectMap

查询并返回一个Map类型的结果,key是指定的属性,Map里的key值数据类型可以是业务对象类型,如User; 也可以以Map<Integer,Object> 形式返回对象信息,map中的key是属性名,值是属性值。

userMap=sqlSession.selectMap("findAllUser3SqlId","id");

userMap=sqlSession.selectMap("findAllUser3SqlId","id");

红色表示将id指定为最外层Map的key值, 也可将其他属性设置为key值。

xxDao.java

    //返回map结构
    public Map<Integer,User> findAllUser3();
    public Map<Integer,Map<String,Object>> findAllUser4();

xxDaoImpl.java

  @Override
    public Map<Integer, User> findAllUser3() {
        Map<Integer, User> userMap=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            //这里是将id作为key了
            userMap=sqlSession.selectMap("findAllUser3SqlId","id");
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return userMap;
    }

    @Override
    public Map<Integer, Map<String, Object>> findAllUser4() {
        Map<Integer, Map<String, Object>> userMap=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            //这里是将id作为key了
            userMap=sqlSession.selectMap("findAllUser4SqlId","id");
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return userMap;
    }

user.xml

   <!--查所有返回Map<User>-->
    <select id="findAllUser3SqlId"
            resultType="org.example.entity.User"
    >
        select
            id,
            user_name as name,
            user_password as password,
            address
        from t_user
    </select>

    <!--查所有返回Map<Map>-->
    <select id="findAllUser4SqlId"
            resultType="java.util.Map"
    >
        select
            id,
            user_name,
            user_password,
            address
        from t_user
    </select>

单元测试:

    @Test
    public void findAllUser3() {
        UserDao userDao=new UserDaoImpl();
        Map<Integer,User> userMap=userDao.findAllUser3();
        for(Integer key:userMap.keySet()){
            System.out.println(key+"——>"+userMap.get(key).toString());
        }
    }

    @Test
    public void findAllUser4() {
        UserDao userDao=new UserDaoImpl();
        Map<Integer,Map<String,Object>> userMap=userDao.findAllUser4();
        for(Integer key:userMap.keySet()){
            System.out.println(key+"——>"+userMap.get(key).toString());
        }
    }

结果展示:

Map<String,Object>

Map<String,Map<String,Object>>

3.5select返回自定义数据结构

select()是mybatis留给程序员的自定义接口,其可以返回程序员自定义的数据结构,可以回一个map,也可以是实体对象

这里以JsonString 为指定数据结果为例进行实现

select()可以处理自定义的特殊结构,

ResultHandler<> 是带泛型的接口,我们自定义的resultHandler,如JsonResultHandler 均实现ResultHandler<>接口

其中:

@Override

public void handleResult(ResultContext<? extends User> resultContext) {}

handleResult没有返回值,通过额外的方法将结果进行返回,如 public String getJson(){}

resultHandler处理数据结构的过程:

        resultHandler中handleResult每调用一次,处理一个对象

        返回一个数据,将数据处理为指定类型

        循环调用处理结果集中的所有对象

xxDao.java

    //自定义结构返回
    public String findAllUser5();

xxDaoImpl.java

为了返回指定的数据结构,我们在resultHandler里设定返回格式。

    @Override
    public String findAllUser5() {
        String users=null;
        SqlSession sqlSession=null;
        try {
            sqlSession=MybatisUtil.getSession();
            //循环多次
            JsonResultHandler resultHandler=new JsonResultHandler();
            sqlSession.select("findAllUser5SqlId",resultHandler);
            users=resultHandler.getJson();
            sqlSession.commit();
        }catch (Exception e){
            e.printStackTrace();
            sqlSession.rollback();
        }finally {
            if(sqlSession!=null){
                sqlSession.close();
            }
        }
        return users;
    }
    //内部类
    class JsonResultHandler implements ResultHandler<User>{
        //用于追加内容
        StringBuilder sb=new StringBuilder("[");

        //回调一次,返回一个对象
        //结构:  ["1":{1:2,2:3},"2":{1:2,2:3}]
        @Override
        public void handleResult(ResultContext<? extends User> resultContext) {
            //获取用户数据
            User user=resultContext.getResultObject();
            //封装成json串
            sb.append("{");
            sb.append("\"id\":");
            sb.append(user.getId()+",");
            sb.append("\"name\":");
            sb.append("\""+user.getName()+"\",");
            sb.append("\"password\":");
            sb.append("\""+user.getPassword()+"\",");
            sb.append("\"address\":");
            sb.append("\""+user.getAddress()+"\"");
            sb.append("}");
            sb.append(",");
        }

        public String getJson(){
            String temp=sb.toString();
            //前包后不包
            String temp1= temp.substring(0,temp.length()-1)+"]";
            return temp1;
        }
    }

user.xml

    <!--查所有返回自定义格式-->
    <select id="findAllUser5SqlId"
            resultType="org.example.entity.User"
    >
        select
            id,
            user_name as name,
            user_password as password,
            address
        from t_user
    </select>

单元测试

    @Test
    public void findAllUser5() {
        UserDao userDao=new UserDaoImpl();
        String usersJson=userDao.findAllUser5();
        System.out.println(usersJson.toString());
    }

结果展示

总结:

  • Mybatis 中的 ResultHandler 相当于数据结果集的处理器,它是一个回调函数(Callback),用来处理每一行数据的结果,这个回调函数可以在查询结果处理到一定量时触发,对结果集数据进行定制化处理。
  • ResultHandler 的使用可以大幅提升数据处理的效率,当我们需要处理大量的数据时,一般会使用 ResultHandler 来进行结果的处理,避免一次查询就全部返回结果,浪费内存资源或造成 OOM。

摘自《5.7 mybatis之ResultHandler流式处理数据_resulthandler 修改导出数据-CSDN博客》

  • mybatis中的原生 api 方法,select(),实现原理是策略模式 + 方法回调,select可以返回我们自定义的数据格式,例如json

摘自《面向接口编程+策略模式+方法回调一起使用_面向接口编程中接口回调怎么写-CSDN博客》

4.设计模式

策略模式: Mybatis的select()方法底层实现是策略模式+回调

策略模式

  • 策略模式(Strategy Pattern)属于对象的行为模式。其用意是针对一组算法,将每一个算法封装到具有共同接口的独立的类中,从而使得它们可以相互替换。策略模式使得算法可以在不影响到客户端的情况下发生变化。
  • 其主要目的是通过定义相似的算法,替换if else 语句写法,并且可以随时相互替换。

摘自《https://www.cnblogs.com/xuwujing/p/9954263.html》

5.补充

数据库的游标是什么,有什么用?

1.什么是游标?
        游标Cursor是处理数据的一种方法,用来查看或者处理结果集中的数据,游标提供了在结果集中一次一行或者多行向前或向后浏览数据的能力;
        游标相当于一个指针,它可以指定结果中的任何位置,允许用户对指定位置的数据进行处理;
        游标可以被看作是一个临时文件,提供了在查询结果集中向前或向后浏览护具、处理结果集中数据的能力。
2.游标的作用是什么?
        游标实际上是一种能从包括多条数据记录的结果集中每次提取一条记录进行处理的机制。
        用户可以访问结果集中任意一行数据,在将游标放置到某行之后可以在该行或从该位置的行块上执行操作。
        其实就是用于存放查询出来的多条记录的一个临时变量,我们可以从这个变量中取出我们需要的信息字段。

摘自《https://www.cnblogs.com/wanyuy/p/17098457.html》

类的内部类?

内部类可以访问该类定义所在操作域的所有数据,包括私有操作域
内部类可以对该包下的其他类隐藏
内部类可以“破解”java单继承的缺陷

摘自《java----内部类(四种内部类详解)-CSDN博客》

为什么说Mybatis是面向接口编程?

面向接口编程:就是为了处理对象之间的协作关系,去实现类之间的通信,模块之间的交互等等而设计出来的编程思想。

MyBatis在采用面向接口编程时,采用实体+接口+映射文件的方式。其中接口是不需要实现类的。

摘自《Mybatis学习笔记5:面向接口编程、注解开发_面向对象编程 mybatis-CSDN博客》

摘自《MyBatis学习总结(三)---面向接口编程_mybatis技术-接口编程 实验总结-CSDN博客》

注意:

  • sql书写时,列名和属性名对应
  • 同一个命名空间下,id不同相同
  • preparedStatement可以防止sql注入
  • springjdbc同结构——rowMapper

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

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

相关文章

YOLOv5-7.0改进(四)添加EMA注意力机制

前言 关于网络中注意力机制的改进有很多种&#xff0c;本篇内容从EMA注意力机制开始&#xff01; 往期回顾 YOLOv5-7.0改进&#xff08;一&#xff09;MobileNetv3替换主干网络 YOLOv5-7.0改进&#xff08;二&#xff09;BiFPN替换Neck网络 YOLOv5-7.0改进&#xff08;三&…

net 7部署到Linux并开启https

1.修改代码设置后台服务运行 安装nuget包 Install-Package Microsoft.Extensions.Hosting.WindowsServices Install-Package Microsoft.Extensions.Hosting.Systemd在Program代码中设置服务后台运行 var builder WebApplication.CreateBuilder(args);if (System.OperatingS…

x6.js bug记录-流程图json数据导入进来之后拖拽节点,节点直接飞走了

添加josn数据进来之后虽然能正常渲染&#xff0c;但是只要一拖拽&#xff0c;则节点就直接飞走了&#xff0c;看不到了。 找了一下午的问题&#xff0c;最后发现。保存的json坐标位置是字符串类型&#xff0c;而这边的位置必须是数字类型。如下&#xff1a; {position: { x: &…

词令蚂蚁新村今日答案:微信小程序怎么查看蚂蚁新村今天问题的正确答案?

微信小程序怎么查看蚂蚁新村今天问题的正确答案&#xff1f; 1、打开微信&#xff0c;点击搜索框&#xff1b; 2、打开搜索页面&#xff0c;选择小程序搜索&#xff1b; 3、在搜索框&#xff0c;输入词令搜索点击进入词令微信小程序&#xff1b; 4、打开词令微信小程序关键词口…

基于Matplotlib的模型性能可视化工作

一、项目简介 本项目是科技考古墓葬识别工作的中间过程&#xff0c;因为需要大量复用所以另起一章好了。 主要涉及到数据读取、数据可视化和少量的数据处理过程。 二、相关知识 PandasMatplotlib 三、实验过程 1. 数据探索性分析 1.1 准备工作–导入模块 import pandas…

考研入门55问---基础知识篇

考研入门55问---基础知识篇 01 &#xff1e;什么是研究生入学考试&#xff1f; 研究生是指大专和本科之后的深造课程。以研究生为最高学历, 研究生毕业后&#xff0c;也可称研究生&#xff0c;含义为研究生学历的人。在中国大陆地区&#xff0c;普通民众一般也将硕士毕业生称…

JavaSE基础小知识Ⅱ(很容易错!!!)

1. 变量被final修饰后不能再指向其他对象&#xff0c;但可以重写 如果是引用变量被final修饰&#xff0c;那么的确如此&#xff1b; 基本变量不能重写 2. 下列代码的输出结果是&#xff1f; public class Test {static {int x 5; }static int x,y; public static void ma…

conan2 基础入门(01)-介绍

conan2 基础入门(01)-介绍 文章目录 conan2 基础入门(01)-介绍⭐什么是conan官网Why use Conan? ⭐使用现状版本情况个人知名开源企业 ⭐ConanCenter包中心github ⭐说明文档END ⭐什么是conan 官网 官网&#xff1a;Conan 2.0: C and C Open Source Package Manager 一句话来…

【Linux:lesson1】的基本指令

&#x1f381;个人主页&#xff1a;我们的五年 &#x1f50d;系列专栏&#xff1a;Linux课程学习 &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 目录 &#x1f697;打开Xshell&#xff0c;登陆root…

个人网站快速搭建手册:低成本,高效率,轻松发布

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;React篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来-快速构建个人站|博客|系统,低成本发布上线 目录 前言 博主主页搭建案例 虚拟主机|服务器|域名 使用免费二级…

python实现九宫格图片切割

欢迎关注我👆,收藏下次不迷路┗|`O′|┛ 嗷~~ 目录 一.前言 二.代码 三.使用 四.分析 一.前言 朋友圈九宫格是一种在社交媒体上展示图片或内容的常见布局方式,特别是在微信朋友圈中非常流行。这种布局由九个相同大小的格子组成,通常用于展示一组相关的图片或内容。&…

线程知识点

一、线程 1.定义 线程&#xff1a;是一个进程并发执行多种任务的机制。 串行&#xff1a;多个任务有序执行&#xff0c;一个任务执行完毕后&#xff0c;再去执行下一个任务 并发&#xff1a;多个任务在单个CPU上运行&#xff0c;同一个时间片上只能运行一个任务&#xff0c;c…

数据的均匀化分割算法(网格划分法、四叉树法(含C++代码))

数据的均匀化分割主要是指在分割过程中尽可能均匀地将数据点分布在各个子区域中&#xff0c;以保持数据分布的平衡和优化数据结构的性能。以下是几种可以实现数据均匀化分割的方法&#xff1a; 一. 网格划分法 1. 基本概念 虽然传统的网格划分法不是动态调整的&#xff0c;但通…

软件验收计划书-验收规程(Word原件)

编写软件验收计划是软件开发过程中的一个关键步骤&#xff0c;其重要性体现在以下几个方面&#xff1a; 明确验收标准&#xff1a;软件验收计划详细列出了验收的标准、测试方法、测试环境等&#xff0c;确保所有相关人员对验收的期望和要求有清晰的认识。这有助于避免在验收阶段…

Ansible---自动化运维工具

一、Ansible概述 1.1 Ansible简介 Ansible是一款自动化运维工具&#xff0c;通过ssh对目标主机进行配置、应用部署、任务执行、编排调度等操作。它简化了复杂的环境管理和自动化任务&#xff0c;提高了工作效率和一致性&#xff0c;同时&#xff0c;Ansible的剧本(playbooks)…

centos7.9升级4.19内核

centos默认的内核版本是3.10 通过命令 uname -a 输出系统的详细信息 在部署k8s集群时使用默认的3.10版本的内核&#xff0c;容易出各种奇奇怪怪的问题、可以理解为docker和k8s与该内核版本不兼容&#xff0c;所以在部署k8s集群时&#xff0c;务必要升级内核&#xff0c;这里…

【论文笔记 | 异步联邦】FedSA

FedSA&#xff1a;一种处理 non-IID 数据 的 过时感知 异步联邦算法 1. 论文信息 FedSA&#xff1a;A staleness-aware asynchronous Federated Learning algorithm with non-IID data&#xff0c;Future Generation Computer Systems&#xff0c;2021.7&#xff0c;ccfc 是…

即插即用篇 | YOLOv8引入局部自注意力 HaloAttention | 为参数高效的视觉主干网络扩展局部自注意力

本改进已集成到 YOLOv8-Magic 框架。 我们提出了Axial Transformers,这是一个基于自注意力的自回归模型,用于图像和其他组织为高维张量的数据。现有的自回归模型要么因高维数据的计算资源需求过大而受到限制,要么为了减少资源需求而在分布表达性或实现的便捷性上做出妥协。相…

05-10 周五 FastBuild 容器启动引起超时问题定位与解决

05-10 周五 FastBuild 容器启动超时问题 时间版本修改人描述2024年5月11日16:45:33V0.1宋全恒新建文档2024年5月11日22:37:21V1.0宋全恒完成解决方案的撰写&#xff0c;包括问题分析&#xff0c;docker命令 简介 关于FastBuild的优化&#xff0c;已经撰写了多个博客&#xff0…

C#知识|无边框的WinForm窗体,如何拖动位置?

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 上一节时练习做了一个简单的登录窗体界面&#xff0c;为了美观设置成了无边框&#xff0c; 当运行起来&#xff0c;发现无边框的窗体无法用鼠标拖动位置&#xff0c; 本节记录通过添加代码实现无边框窗体实现移动&…