Mybatis入门——其他查询操作和数据库连接池(4)

目录

一、多表查询

二、#{} 和 ${}

1、#{} 和 ${} 的使用

(1)Integer类型的参数

#{} 的使用

${} 的使用

(2)使用String类型的参数

#{} 的使用

${} 的使用

小结:

2、#{} 和 ${} 的区别

(1)#{} 的性能更高

(2)#{} 更安全 (防止SQL注入)

三、排序功能

四、like查询

五、数据库连接池

1、介绍

2、使用

六、总结

1、MySQL开发企业规范

2、#{} 和 ${} 区别


准备工作:

        SQL语句:

-- 创建数据库
DROP DATABASE IF EXISTS mybatis_test;

CREATE DATABASE mybatis_test DEFAULT CHARACTER SET utf8mb4;

-- 使用数据数据
USE mybatis_test;

-- 创建表[用户表]
DROP TABLE IF EXISTS userinfo;
CREATE TABLE `userinfo` (
        `id` INT ( 11 ) NOT NULL AUTO_INCREMENT,
        `username` VARCHAR ( 127 ) NOT NULL,
        `password` VARCHAR ( 127 ) NOT NULL,
        `age` TINYINT ( 4 ) NOT NULL,
        `gender` TINYINT ( 4 ) DEFAULT '0' COMMENT '1-男 2-女 0-默认',
        `phone` VARCHAR ( 15 ) DEFAULT NULL,
        `delete_flag` TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
        `create_time` DATETIME DEFAULT now(),
        `update_time` DATETIME DEFAULT now(),
        PRIMARY KEY ( `id` ) 
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4; 

-- 添加用户信息
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'admin', 'admin', 18, 1, '18612340001' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'zhangsan', 'zhangsan', 18, 1, '18612340002' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'lisi', 'lisi', 18, 1, '18612340003' );
INSERT INTO mybatis_test.userinfo ( username, `password`, age, gender, phone )
VALUES ( 'wangwu', 'wangwu', 18, 1, '18612340004' );


-- 创建文章表
DROP TABLE IF EXISTS articleinfo;
        
CREATE TABLE articleinfo (
        id INT PRIMARY KEY auto_increment,
        title VARCHAR ( 100 ) NOT NULL,
        content TEXT NOT NULL,
        uid INT NOT NULL,
        delete_flag TINYINT ( 4 ) DEFAULT 0 COMMENT '0-正常, 1-删除',
        create_time DATETIME DEFAULT now(),
        update_time DATETIME DEFAULT now() 
) DEFAULT charset 'utf8mb4';

-- 插入测试数据
INSERT INTO articleinfo ( title, content, uid ) VALUES ( 'Java', 'Java正文', 1 );

        对应实体类model:

@Data
public class ArticleInfo {
    private Integer id;
    private String title;
    private String content;
    private Integer uid;
    private Integer deleteFlag;;
    private Date createTime;
    private Date updateTime;
    //用户相关的信息
    private String username;
    private Integer gender;
}

        yml配置:

# 数据库配置
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/mybatis_test?characterEncoding=utf8&useSSL=false
    username: root
    password: 1234
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  # 配置 mybatis xml 的文件路径,在 resources/mapper 创建所有表的 xml 文件
  mapper-locations: classpath:mybatis/**Mapper.xml
  configuration: # 配置打印 MyBatis日志
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
    map-underscore-to-camel-case: true #配置驼峰自动转换

一、多表查询

        多表查询和单表查询差不多,只是SQL不同,下面是xml的配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mybatisdemo3.mapper.ArticleInfoMapper">

    <select id="selectArticleAndUserById" resultType="com.example.mybatisdemo3.model.ArticleInfo">
        select ta.*, tb.username, tb.gender from articleinfo ta
        left join userinfo tb
        on ta.uid = tb.id
        where ta.id = #{id}
    </select>

</mapper>

        ArticleInfoMapper接口代码如下:

@Mapper
public interface ArticleInfoMapper {
    List<ArticleInfo> selectArticleAndUserById(Integer id);
}

        测试类代码如下:

@SpringBootTest
class ArticleInfoMapperTest {
    @Autowired
    private ArticleInfoMapper articleInfoMapper;
    @Test
    void selectArticleAndUserById() {
        System.out.println(articleInfoMapper.selectArticleAndUserById(1));
    }
}

        articleInfo和userinfo表如下:

        运行测试类代码,结果如下:


二、#{} 和 ${}

        MyBatis 参数赋值有两种⽅式,咱们前⾯使⽤了 #{} 进⾏赋值,接下来我们看下⼆者的区别。

1、#{} 和 ${} 的使用

(1)Integer类型的参数

#{} 的使用

        ArticleInfoMapper接口代码:

@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo where id = #{id}")
    List<UserInfo> selectId(Integer id);
}

        测试类代码如下:

@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void selectId() {
        userInfoMapper.selectId(1);
    }
}

        运行测试类代码,结果如下:

        结果没有毛病。#{} 使用的是预编译SQL,通过 ? 占位的方式,提前对SQL进行编译,然后把参数填充到SQL语句中这里的 #{} 会根据参数类型,自动拼接引号 ' '

${} 的使用

        UserInfoMapper接口代码如下:

@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo where id = ${id}")
    List<UserInfo> selectId(Integer id);
}

        测试类代码如下:

@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void selectId() {
        userInfoMapper.selectId(1);
    }
}

        运行测试类代码,结果如下:

        也没有毛病。

(2)使用String类型的参数

#{} 的使用

        UserInfoMapper接口代码:

@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo where username = ${username}")
    List<UserInfo> selectUserName(String username);
}

        测试类代码如下:

@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void selectUserName() {
        userInfoMapper.selectUserName("zhangsan");
    }
}

        运行测试类代码,结果如下:

        没有毛病。

${} 的使用

        USerInfoMapper接口代码:

@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo where username = ${username}")
    List<UserInfo> selectUserName(String username);
}

        测试类代码:

@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void selectUserName() {
        userInfoMapper.selectUserName("zhangsan");
    }
}

        运行测试类,发现报错了,报错信息如下:

        是BadSql,zhangsan应该是一个字符串,但拼接SQL的时候没有加引号说明 ${} 是直接把参数传进去了,并没有添加引号 ' ',进而报错了

小结:

1#{} 使用的是预编译SQL,通过 ? 占位的方式,提前对SQL进行编译,然后把参数填充到SQL语句中。#{} 会根据参数类型,自动拼接引号 ' '

2${} 会直接进行字符替换,一起对SQL进行编译。如果参数为字符串,需要加上引号 ' ',

参数为数字类型时,也可以加上,查询结果不变,但是可能会导致索引失效,性能下降

2、#{} 和 ${} 的区别

        #{} 和 ${} 的区别就是 预编译SQL和即时SQL的区别

当客户发送一条SQL语句给服务器后,大致流程如下:

1、解析语法和语义,校验SQL语句是否正确。

2、优化SQL语句,指定执行计划。

3、执行并返回结果。

(一条SQL如果走上述流程处理,我们称之为 Immediate Statements(即时SQL) )

(1)#{} 的性能更高

        绝大多数情况下,某一条SQL语句可能会被反复调用执行,或者每次执行的时候只有个别的值不同(比如select 的 where 子句值不同,update 的 set 子句值不同,insert 的 values 值不同)。如果每次都需要经过上面的语法解析、SQL优化、SQL编译等,则效率就明显不行了。如下图:

        预编译SQL,编译一次之后会将编译后的SQL语句缓存起来,后面再次执行这条语句时,不会再次编译(只是输入的参数不同),省去了解析优化等过程,以此来提高效率

(2)#{} 更安全 (防止SQL注入)

        SQL注入是通过操作输入的数据来修改事先定义好的SQL语句,以达到执行代码对服务器进行攻击的方法

        sql注⼊代码: ' or 1='1

        USerInfoMapper接口代码:

@Mapper
public interface UserInfoMapper {
    @Select("select * from userinfo where username = '${username}'")
    List<UserInfo> selectUserName(String username);
}

        测试类代码如下:(正常访问情况

@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void selectUserName() {
        System.out.println(userInfoMapper.selectUserName("zhangsan"));
    }
}

        运行结果:

        测试类代码:(SQL注入场景

@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void selectUserName() {
        System.out.println(userInfoMapper.selectUserName("' or 1='1"));
    }
}

        运行结果如下:

        把表全部的信息都打印出来了。

        SQL注入后的SQL语句如下:

select * from userinfo where username = '' or 1='1'

        也就是说,如果username是空字符串,就打印是空字符串的,不是就为真,会打印userinfo表的全部信息。所以用于查询的字段,尽量使用 #{} 预查询的方式

        SQL注入是一种非常常见的数据库攻击手段,SQL注入漏洞也是网络世界中最普遍的漏洞之一如果发生在用户登录场景中,密码输入为 ' or 1='1,就可能完成登录(不是一定会发生的场景,需要看登录代码如何写)

控制层:UserController

@RequestMapping("user")
@RestController
public class UserController {
    @Autowired
    private UserService userService;
    @RequestMapping("/login")
    public boolean login(String name, String password) {
        UserInfo userInfo = userService.queryUserByPassword(name, password);
        if(userInfo != null) {
            return true;
        }
        return false;
    }
}

业务层:UserService

@Service
public class UserService {
    @Autowired
    private UserInfoMapper userInfoMapper;

    public UserInfo queryUserByPassword(String name, String password) {
        List<UserInfo> userInfos = userInfoMapper.queryUserByPassword(name, password);
        if(userInfos != null && userInfos.size() > 0) {
            return userInfos.get(0);
        }
        return null;
    }
}

数据层:UserInfoMapper

@Mapper
public interface UserInfoMapper {
    @Select("select username, `password`, age, gender, phone from userinfo where username= '${name}' and password='${password}' ")
    List<UserInfo> queryUserByPassword(String name, String password);
}

        运行项目,浏览器访问:127.0.0.1:8080/user/login?name=admin&password=admin

        接下来访问SQL注⼊的代码:password 设置为  ' or 1='1

        访问:http://127.0.0.1:8080/user/login?name=admin&password=' or 1='1,结果如下:

        也登录成功了。这就是SQL注入所带来的风险。


三、排序功能

        从上面的例子中,可以得出结论:${} 会有SQL注入的风险,所以我们尽量使用 #{} 完成查询。既然如此,是不是 ${} 就没有存在的必要性了呢?当然不是,接下来我们看 ${} 的使用场景。京东商品的价格排序

        UserinfoMapper接口代码如下:(使用 ${} )

@Mapper
public interface UserInfoMapper {
    @Select("select id, username, age, gender, phone, delete_flag, create_time, update_time " +
            "from userinfo order by id ${sort} ")
    List<UserInfo> queryAllUserBySort(String sort);
}

        测试类代码如下:

@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void queryAllUserBySort() {
        userInfoMapper.queryAllUserBySort("desc");
    }
}

        运行测试类代码,结果如下:(按照了id逆序方式展示)

        UserinfoMapper接口代码改变:(使用 #{} )

@Mapper
public interface UserInfoMapper {
    @Select("select id, username, age, gender, phone, delete_flag, create_time, update_time " +
            "from userinfo order by id #{sort} ")
    List<UserInfo> queryAllUserBySort(String sort);
}

        运行测试类,报错了,报错信息如下:

        可以看到,#{} 传参数是通过 ? 占位,#{} 根据参数类型判断是否拼接引号 ' ',如果参数类型是String,就会加上引号所以SQL语句传参的desc会带有引号,但是SQL语句的desc是不带引号的,所以报错了,其转换后SQL语句如下:

select id, username, age, gender, phone, delete_flag, create_time, update_time from userinfo order by id 'desc'

        除此之外,还有表名作为参数时,也只能使用 ${} 。

        使用 ${} 有SQL注入的风险,怎样解决呢?按上面的这种情况举例子

1让后端进行校验(在Controller这就直接进行规定参数的内容),传进来的参数必须是asc或者desc

2不传递参数,Mapper接口代码,@Select注解只直接使用asc或者desc,没有参数的传递,如图:

3使用第三方工具辅助


四、like查询

        UserInfoMapper接口代码如下:

@Mapper
public interface UserInfoMapper {
    @Select("select id, username, age, gender, phone, delete_flag, create_time, update_time "
            + "from userinfo where username like '%#{key}%' ")
    List<UserInfo> queryAllUserByLike(String key);
}

        直接使用 #{} 会报错,把 #{} 改成 ${} 可以正确查出来,但是 ${} 存在SQL注⼊的问题,所以不能直接使⽤ ${}
        解决办法:使⽤ mysql 的内置函数 concat() 来处理,代码如下:

@Mapper
public interface UserInfoMapper {
    @Select("select id, username, age, gender, phone, delete_flag, create_time, update_time "
            + "from userinfo where username like concat('%',#{key},'%') ")
    List<UserInfo> queryAllUserByLike(String key);
}

        测试类代码如下:

@SpringBootTest
class UserInfoMapperTest {
    @Autowired
    private UserInfoMapper userInfoMapper;
    @Test
    void queryAllUserByLike() {
        System.out.println(userInfoMapper.queryAllUserByLike2("zhangsan"));
    }
}

        执行测试类代码,结果如下:

        比直接使用 ${} 好,其代码如下:下面这种写法有SQL注入的风险。

@Mapper
public interface UserInfoMapper {
    @Select("select id, username, age, gender, phone, delete_flag, create_time, update_time "
            + "from userinfo where username like '%${key}%' ")
    List<UserInfo> queryAllUserByLike(String key);
}

五、数据库连接池

        上面的Mybatis代码练习中,我们其实使用了数据库连接池技术,避免频繁的创建连接,销毁连接,下面我们来了解数据库连接池。

1、介绍

        数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个

没有使用数据库连接池的情况每次执行SQL语句,要先创建一个新的连接对象,然后执行SQL语句,SQL语句执行完,再关闭连接对象释放资源,这种重复创建连接、消耗连接的操作,比较消耗资源

使用数据库连接池的情况程序启动时,会再数据库连接池中创建一定数量的Connection对象,当客户端请求数据库连接池,会从数据库连接池中获取Connection对象,然后执行SQL,SQL语句执行完,再把Connection归还给连接池

优点1、减少了网络开销       2、资源重用       3、提升了系统的性能

2、使用

        常见的数据库连接池:C3P0、DBCP、Druid、Hikari,目前比较流行的是Hikari、Druid。

        SpringBoot默认使用的数据库连接池就是:Hikari,如图:

        Hikari 是⽇语"光"的意思(ひかり),Hikari也是以追求性能极致为⽬标。
        如果我们想把默认的数据库连接池切换为Druid,只需要引入相关依赖即可,pom.xml代码如下:

        <!-- druid启动器的依赖  -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-3-starter</artifactId>
            <version>1.2.21</version>
        </dependency>

        再次运行上面like查询的代码,结果如下:

        参考官方地址:druid/druid-spring-boot-starter at master · alibaba/druid · GitHub

Druid连接池是阿里巴巴开源的数据库连接池项目。

功能强大,性能优秀,是Java语言最好的数据库连接池之一。

学习文档:首页 · alibaba/druid Wiki · GitHub

        二者对比,参考:Hikaricp和Druid对比_数据库_晚风暖-华为云开发者联盟 (csdn.net)


六、总结

1、MySQL开发企业规范

(1)表名,字段名使⽤小写字⺟或数字,单词之间以下划线分割尽量避免出现数字开头或者两个下划线中间只出现数字数据库字段名的修改代价很大,所以字段名称需要慎重考虑

MySQL 在 Windows 下不区分大小写,但在 Linux 下默认是区分大小写。因此,数据库名,表名,字段名都不允许出现任何大写字母,避免节外⽣枝。
正例:aliyun_admin,rdc_config,level3_name
反例:AliyunAdmin,rdcConfig,level_3_name

(2)表必备三字段id,create_time,update_time

id 为主键,类型为 bigint unsigned,单表时⾃增,步长为 1。
create_time,update_time 的类型均为 datetime 类型,create_time表示创建时间,
update_time表⽰更新时间。
有同等含义的字段即可,字段名不做强制要求。

(3)在表查询中,避免使⽤ * 作为查询的字段列表,标明需要哪些字段

1. 增加查询分析器解析成本。
2. 增减字段容易与 resultMap 配置不⼀致。
3. ⽆⽤字段增加⽹络消耗,尤其是 text 类型的字段。

2、#{} 和 ${} 区别

(1)#{}:预编译处理,${}:字符直接替换

(2)#{} 可以防止SQL注入,${} 存在SQL注入的风险,查询语句中,可以使用 #{},推荐使用 #{}

(3)但是一些场景,#{} 不能完成,比如 排序 功能,表名、字段名作为参数时,这些情况需要使用 ${}

(4)模糊查询虽然可以使用 ${} 完成,但因为存在 SQL注入 的问题,所有通常使用MySQL内置函数concat 来完成

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

3、python安装-linux系统下

安装前置依赖软件&#xff0c;安装完成后&#xff0c;打开官网&#xff0c;下载linux系统下的python安装包&#xff1a; 选择最新的版本 点击最新版本&#xff0c;进入版本对应的界面&#xff0c; 选择第一个进行源码的编译&#xff0c;右键选择复制连接地址&#xff0c; 回到终…

懒人创业秘诀揭秘:加入萤瓴优选项目,普通人也能打开财富大门

创业对于很多人来说&#xff0c;是一个艰难而复杂的过程。然而&#xff0c;时代的发展带来了新的机遇&#xff0c;懒人创业成为了一种趋势。加入萤瓴优选项目&#xff0c;普通人也能轻松打开财富大门。本文将揭秘懒人创业的秘诀&#xff0c;并分析萤瓴优选项目如何帮助普通人实…

Thingsboard规则链:Switch节点详解

在物联网&#xff08;IoT&#xff09;领域&#xff0c;数据的高效处理与自动化决策是构建智能系统的核心。作为一款强大的物联网平台&#xff0c;Thingsboard通过其规则引擎为开发者提供了高度灵活的工具&#xff0c;其中Switch节点是实现消息条件路由的关键组件。本文将全方位…

[leetcode hot 150]第五十六题,合并区间

题目&#xff1a; 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 思路&#xff1a; 这道题目要求合并一…

从技术的角度剖析Nginx框架

众所周知&#xff0c;nginx 性能高&#xff0c;而 nginx 的高性能与其架构是分不开的。 1、nginx 多进程模式架构 nginx 启动后&#xff0c;会有一个master 进程和多个 worker 进程。 master 进程用来管理 worker 进程&#xff0c;功能包含&#xff1a;接收来自外界的信号&a…

智能跳绳的产品体验与思考(一)

我&#xff0c;虽称不上跳绳高手&#xff0c;却对这项运动怀有深厚的热爱&#xff0c;也曾在某电商平台上选购过一款智能跳绳&#xff0c;希望能借此提升我的跳绳技巧。今天&#xff0c;咱们就来聊聊我和这条绳子的发生的一些故事&#xff0c;外加我的一些思考。 此刻&#xf…

如何利用 Selenium 对已打开的浏览器进行爬虫

大家好&#xff01; 在对某些网站进行爬虫时&#xff0c;如果该网站做了限制&#xff0c;必须完成登录才能展示数据&#xff0c;而且只能通过短信验证码才能登录 这时候&#xff0c;我们可以通过一个已经开启的浏览器完成登录&#xff0c;然后利用程序继续操作这个浏览器&…

K8s集群中的Pod调度约束亲和性与反亲和性

前言 在 K8s 集群管理中&#xff0c;Pod 的调度约束——亲和性&#xff08;Affinity&#xff09;与反亲和性&#xff08;Anti-Affinity&#xff09;这两种机制允许管理员精细控制 Pod 在集群内的分布方式&#xff0c;以适应多样化的业务需求和运维策略。本篇将介绍 K8s 集群中…

BookxNote Pro 宝藏 PDF 笔记软件

一、简介 1、BookxNote Pro 是一款专为电子书阅读和学习笔记设计的软件&#xff0c;支持多种电子书格式&#xff0c;如PDF和EPUB&#xff0c;能够帮助用户高效地管理和阅读电子书籍&#xff0c;同时具备强大的笔记功能&#xff0c;允许用户对书籍内容进行标注、摘录和思维导图绘…

Shell编程中的循环语句和函数

一、for循环语句 当面对各种列表重复任务时&#xff0c;使用简单的if语句已经难以满足需求&#xff0c;这时就需要for循环语句。for语句的结构为&#xff1a; for 变量 in 取值列表 do 命令序列 done 使用for循环语句时&#xff0c;需要指定一个变量及取值列表&#xff0c;针对…

【经验分享】可视化的项目管理,轻松解决资源冲突和协作困难

在数字化时代&#xff0c;高效协同逐步成为提升组织效能的重要着力点&#xff0c;同时也是企业保持竞争力、实现持续发展的关键要素。一方面可以打破部门壁垒&#xff0c;促进信息流通&#xff0c;从而提升整体工作效率&#xff1b;另一方面还能帮助企业优化资源配置和管理流程…

快团团帮卖团长怎么对供货大团长进行评分?

都说帮卖“躺赚”&#xff1f; 一旦遇团不淑&#xff0c;惨遭不靠谱团长挖坑&#xff0c;售后拖延、发货慢、产品瑕疵…… 加上顾客夺命连环催&#xff0c;双面夹击&#xff0c;夹缝生存。供货团长靠不靠谱太重要了&#xff01; 快团团供货团长评分系统上线&#xff01; 帮卖团…

什么是erp仓储管理系统?ERP系统的价值体现在哪些方面?

ERP仓储管理系统是一个帮助企业管理仓库的工具。想象一下&#xff0c;如果你是一个仓库管理员&#xff0c;里面堆满了各种各样的产品和货物&#xff0c;如何确保这些产品数量准确、摆放有序&#xff0c;以及快速找到自己需要的产品呢&#xff1f; 这时&#xff0c;如果企业引用…

GitLab项目中添加用户,并设置其角色权限等

注意&#xff1a;创建用户(new user)&#xff0c;创建完用户然后再项目邀请用户&#xff0c;选择创建过的用户 一、以管理员身份登录GitLab的WebUI并创建用户 1>.使用管理员登录GitLab 使用管理员(root)用户登录成功后&#xff0c;点击如下图所示的小扳手&#xff0c;点击…

NameSilo + Cloudflare 给网站加个域名(附 NameSilo 购买域名优惠码)

网站做好了之后,下一步就是买域名 在国内买域名的话,还需要备案,个人名下备案好像是还有限制,我就去 NameSilo 上面买的 在买之前,对比过几家 比如: godaddy/namecheap/cloudflare 本来是倾向于在 godaddy 上面买的,因为它支持支付宝支付,但是在详细看的时候,发现如果购买一年…

CLIP 源码分析:simple_tokenizer.py

tokenizer的含义 from .clip import *引入头文件时为什么有个. 正文 import gzip import html import os from functools import lru_cacheimport ftfy import regex as re# 上面的都是头文件# 这段代码定义了一个函数 default_bpe()&#xff0c;它使用了装饰器 lru_cache()。…

vue 笔记02

目录 01 事件修饰符 02 按键修饰符 03 v-bind属性 04 vue-axios的基本使用 05 vue的生命周期 06 vue生命周期涉及到的其他的知识点 01 事件修饰符 vue的事件修饰符 事件名称.修饰符1.修饰符2...事件驱动函数 stop 阻止冒泡修饰符 prevent 阻止默认行为 once 当前事件只触…

嵌入式学习记录5.18(多点通信)

一、套接字属性设置相关函数 #include <sys/types.h> /* See NOTES */#include <sys/socket.h>int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level, int optname,const void *op…

vue3学习(三)

前言 继续接上一篇笔记&#xff0c;继续学习的vue的组件化知识&#xff0c;可能需要分2个小节记录。前端大佬请忽略&#xff0c;也可以留下大家的鼓励&#xff0c;感恩&#xff01; 一、理解组件化 二、组件化知识 1、先上知识点&#xff1a; 2、示例代码 App.vue (主页面) …

人类和小鼠转录组上游分析

基础软件 conda install cutadapt, trimmomatic, samtools, hisat2, subread, deeptools -y人类转录组上游分析 # 样本名称 sample_namesample# 线程 threads4# 双端测序原始fastq1和fastq2路径 fastq1_path/path/${sample_name}_1.fq.gz fastq2_path/path/${sample_name}_2.…