MyBaits(单独使用,与整合无关)小白版

文章目录

  • 概述
  • 比较
  • 配置
    • 写xml
    • 加载上面配置并执行
      • 加载配置的方法
        • 方式一
      • 执行方法
        • 方式一
        • 方式二(MyBatis映射器)
    • 写配置文件的映射文件
    • 设置对象的别名(简写)
    • 获取自动生成的主键
  • 查询结果和java的映射规则
    • 基本类型映射:
    • 简单对象映射:
    • 嵌套对象映射:
      • 忽略大小写:
      • 下划线转驼峰:
    • 构造器映射:
    • 注解映射:
      • 方式一
      • 方式二
  • 三个关键类的生命周期
    • 1.1.SqlSessionFactoryBuilder
    • 1.2.SqlSessionFactory
    • 1.3.SqlSession
  • 日志
    • 日志等级
    • 配置
    • 打印入参
  • #{}与${}比较
    • 使用的场景
  • 动态SQL
    • if
    • choose、when、otherwise
    • trim、where、set
    • foreach(批量操作)
    • bind
  • java API_MyBatis
    • SqlSessionFactoryBuilder
    • Resources 工具类
    • SqlSessionFactory
    • SqlSession
  • SQL类
  • 踩坑

概述

前生IBatis,现在很多包都是IBatis。

比较

MyBatis与JPA
MyBatis更加灵活,自己写sql,可以Sql优化,
JPA不行,因为自己生成SQL

配置

写xml

取名mybatis-config.xml,连接数据库

<?xml version="1.0" encoding="UTF-8" ?>  声明
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">  约束
<!--根元素,里面就是Mybatis配置-->
<configuration>
<!--    环境配置:数据库的配置环境(怎么连接数据库) ,可以配置多个环境对象 environment,多个数据库的连接配置,可以通过  default="development" 来切换默认的环境
--><environments default="development"><environment id="development">
<!--            事务管理器,type="JDBC"使用JDBC的事务管理 "JdbcTransaction"  --><transactionManager type="JDBC"/>
<!--            数据源配置 POOLED 连接池,对应 PooledDataSource--><dataSource type="POOLED"><property name="driver" value="com.mysql.jdbc.Driver"/><property name="url" value="jdbc:mysql:///mybatis"/><property name="username" value="root"/><property name="password" value="123456"/></dataSource></environment><!--        <environment id="test">-->
<!--  		...	-->
<!--        </environment>--></environments>
<!--映射配置,标注清楚sql语句写在哪里--><mappers><mapper resource="自己映射文件的目录,xml文件"/></mappers>
</configuration>
  1. 环境可以设置多个,连接不同的数据库,起不同的作用,可以将不同的用途设置给id,如测试,开发,生产环境等。
  2. 事务简称tx。

改进一下
数据库的连接配置可以提出来
写成一个jdbc.properties配置,配置加一个

<!--    加载properties--><properties resource="jdbc.properties" /><transactionManager type="JDBC"/><dataSource type="POOLED"><!--通过k取value--><property name="driver" value="${jdbc.driver}"/><property name="url" value="${jdbc.url}"/><property name="username" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></dataSource></environment>

再改进一下 3.5.2开始之后可用
如果属性 ‘username’ 没有被配置,‘username’ 属性的值将为 ‘ut_user’
原理: ${tableName != null ? tableName : ‘global_constants’})

 <dataSource type="POOLED"><property name="username" value="${username:ut_user}"/> </dataSource><properties resource="org/mybatis/example/config.properties"><!-- 开启上面的功能 ,可在value中自定义修改分隔符,写了就换--><property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/> <!-- 启用默认值特性 -->
</properties>

加载上面配置并执行

会话工厂建造者建造会话工厂,会话工厂又生产会话,用会话去操作,
会话执行的方法,通过命名空间+id获取。
执行的的各种方法都是在sqlSession类中

命名空间可以提出去,设置成常量
建造工厂可以提出去,创建一个utils
sqlSession用完要关掉,其他的不用
openSession()无参就需要手动提交 .commit(),如果传了true那么就自动提交,不用commit()

加载配置的方法

方式一

在这里插入图片描述

执行方法

方式一

在这里插入图片描述
注意:方式一,namespace和Xxxmapper可以不同,但是在sqlssion.xxx,中和xml文件一致就可以了

方式二(MyBatis映射器)

加一个接口和命名空间一样,与xml文件相连

public interface CustomerMapper {List<Customer>  selectCustomer();
}

或者注解

public interface CustomerMapper {@Select(" SELECT id,user_name,age,pwd,money  from users")List<Customer>  selectCustomer();
}
    //selectList = sqlSession.selectList(NAMESPACE + "selectCustomer");//替换成下面的这个语句CustomerMapper mapper = sqlSession.getMapper(CustomerMapper.class);selectList = mapper.selectCustomer();

原理 :动态代理,用cglib动态代理实现的。
在这里插入图片描述
service层中的改变
在这里插入图片描述

写配置文件的映射文件

写了这个还需要写一个命名空间接口,其中的方法对应id的值,那个接口也可以不用写,写是为了和service结合,这里不用结合,就可以不用写,这个命名空间在这里可以写此个xml文件名,
还需要写一个实体类,对应查询回来的数据对应resultType的值
没有配置简写,就要写完全。

Mapper文件

<?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">
<!--namespace:命名空间 ,sql坐标(SQL在哪儿)规范写法:一般写这个mapper.xml所在的包的路径
-->
<mapper namespace="接口,需要实现的方法的接口MxxMapper,">
<!-- 查询语句 id是sql的id,在同一个mapper.xml中必须唯一如何精准的找到一个SQL     namespace+idresultType:返回的结果的实体类
--><select id="唯一标识符,对应的是命名空间接口中的某个方法"       resultType="返回的实体类路径" ParameterType="参数类型"></select></mapper>

设置对象的别名(简写)

自己写的类配置别名
在MyBatis-Config.xml配置

<!--    加载properties--><properties resource="jdbc.properties" /><typeAliases><!--给单个类设置别名 alias的值可以任意写--><typeAlias type="com.ronghuanet.mybatis.domain.Product" alias="Product" /><!--扫描包,这个包下面的所有类都设置一个别名-->
<!--        <package name="com.ronghuanet.mybatis.domain"/>--></typeAliases>.........

框架含有的
在这里插入图片描述

获取自动生成的主键

先设置这个

   <!--自动生成主键赋值给对象的对应的成员变量,再插入进去--><insert ...... useGeneratedKeys="true" 开启自动生成主键  keyColumn="id" 数据库主键列,告诉框架id列  keyProperty="id" 与数据库对应主键的成员变量></insert>

再插入之后,在获取主键,就可以获取到。
在这里插入图片描述

查询结果和java的映射规则

注意:查询返回的类型必须要有无参构造。

可以映射的东西: Java 基本数据类型、自定义的 Java 类,以及 java.util.Map(HashMap)等

基本类型映射:

当查询的结果只有一个列时,MyBatis 可以将该列的值直接映射到一个基本数据类型或包装类(如 int、String、Long 等)。

简单对象映射:

当查询的结果包含多个列时,可以通过在映射文件中使用 标签来定义对象映射规则。通过指定结果列和 Java 对象属性的对应关系,MyBatis 将查询结果映射到一个简单对象(POJO)中。

 <resultMap id="baseResultMap(唯一表示符)" type="映射的java类型"><id column="id" 数据库列  property="id" 对象属性 /><result column="product_name" 数据库列 property="productName" 对象属性/></resultMap>

将resultType改成resultMap

嵌套对象映射:

如果查询的结果包含多个表的数据,可以使用 和 标签来进行嵌套对象映射。通过在映射文件中定义关联关系,MyBatis 可以将查询结果映射到一个复杂的对象图中,包含多个对象之间的关联关系。
注意: 最好逐步建立结果映射。单元测试可以在这个过程中起到很大帮助。 从最简单的形态开始,逐步迭代。而且别忘了单元测试! 有时候,框架的行为像是一个黑盒子(无论是否开源)。因此,为了确保实现的行为与你的期望相一致,最好编写单元测试。 并且单元测试在提交 bug 时也能起到很大的作用。

使用时避免使用 n+1
原理:list肯很大,list是主要 需要展示的对象
在这里插入图片描述

忽略大小写:

MyBatis 在进行列名和属性名的匹配时,默认是忽略大小写的。这意味着列名和属性名在大小写上不区分,可以自动匹配成功。
原理:MyBatis 在进行自动映射时,会根据 Java 对象中的 Setter 方法(即属性的设置方法)来确定属性名,并将查询结果集中的列值赋给该属性。具体来说,MyBatis 会按照以下规则生成属性名:
setName(去掉set)->Name(N变小写)->name 与数据库的字段列一样就好了

下划线转驼峰:

MyBatis 支持将下划线分隔的列名转换为驼峰式命名的属性名。例如,如果查询结果的列名是 user_name,而对象中的属性名是 userName,
则 MyBatis 可以自动将其映射起来。这个需要开启

<settings><setting name="mapUnderscoreToCamelCase" value="true"/></settings>
  1. 类型处理器:在自动映射时,如果数据库中的数据类型和 Java 对象属性的类型不匹配,MyBatis 会尝试使用类型处理器进行转换。

构造器映射:

除了使用默认的无参构造器来创建对象,MyBatis 还支持使用带参构造器来创建对象,并通过列值来调用相应的构造器。

  1. Java 对象必须具有带参构造器:要使用构造器映射,Java 对象必须定义了带参数的构造器。

  2. 构造器的参数顺序和类型要与查询结果的列对应:构造器的参数顺序和类型必须和查询结果的列一一对应。MyBatis 会根据列名和构造器参数名的匹配关系来确定调用哪个构造器。

<resultMap id="userResultMap" type="User"><constructor><idArg column="id" javaType="Long" /><arg column="username" javaType="String" /><arg column="age" javaType="Integer" /></constructor>
</resultMap>

注解映射:

方式一

除了 XML 配置文件外,MyBatis 还支持使用注解来定义对象映射规则。通过在 Java 对象上添加 @Results 和 @Result 注解,可以实现对象与查询结果的映射。

public class User {@Result(column = "user_id", property = "userId")private Long userId;@Result(column = "username", property = "username")private String username;// 省略 getter 和 setter 方法
}或者
@Results({@Result(column = "user_id", property = "userId"),@Result(column = "username", property = "username")
})
@Select("SELECT user_id, username FROM users")
List<User> getUsers();

方式二

在注解映射中,我们可以使用注解来描述实体类(Java 对象)与数据库表的对应关系,以及实体类的属性与表字段的对应关系。通过这些注解的配置,框架可以自动完成数据库的增删改查操作,并将查询结果映射到对应的 Java 对象中。

  1. @Entity:用于标识实体类,表示该类与数据库表对应。
  2. @Table:用于指定实体类与数据库表的映射关系,可以指定表名、schema 等信息。
  3. @Column:用于指定实体类的属性与数据库表字段的映射关系,可以指定字段名、长度、默认值等信息。
  4. @Id:用于指定实体类的主键属性,表示该属性是数据库表的主键。
  5. @GeneratedValue:用于指定主键的生成策略,如自增长、UUID 等。
  6. @Transient:用于指定实体类的属性不与数据库表字段进行映射,即忽略该属性。
@Entity
@Table(name = "user")
public class User {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id;@Column(name = "username")private String username;@Column(name = "age")private Integer age;// 省略 getter 和 setter 方法
}

三个关键类的生命周期

1.1.SqlSessionFactoryBuilder

​ 这个类可以被实例化,使用和丢弃。一旦你创建了 SqlSessionFactory 后,这个类就不需要存在了。(因为工厂创建了,工人就不需要了)

1.2.SqlSessionFactory

​ 一旦被创建,SqlSessionFactory 应该在你的应用执行期间都存在,因为是工厂,需要不断创建sqlsession,它应该是单例的也是线程安全的,并且随着应用的创建而创建,随着应用的销毁而销毁。SqlSessionFactory 中存储了:1.xml基本信息,2.连接池对象, 3.二级缓存。SqlSession是通过SqlSessionFactory来创建的。

1.3.SqlSession

​ 每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不能被共享,也是线程不安全的。因此最佳的范围是请求或方法范围。它内部存储的东西**:1.连接对象 , 2.一级缓存。**

日志

日志等级

trace(最小,全部都要打印) ,debug(调试) , info(提示) , warn(警告) ,error(错误)

配置

创建一个log4j的配置文件
将配置文件放置在类路径下:将创建好的 Log4j 配置文件放置在项目的类路径下,MyBatis 会在初始化过程中自动加载类路径下的 Log4j 配置文件,并根据配置文件中的设置来进行日志输出
一部分配置配什么查什么

#全局日志配置
log4j.rootLogger = info,console#输出局部的日志信息(自己的包中的日志打印方式)
log4j.logger.com.wj=TRACE  自己哪里的数据操作需要打印操作### 配置输出到控制台
log4j.appender.console = org.apache.log4j.ConsoleAppender
### 使用System.out打印日志
log4j.appender.console.Target = System.out
### 指定日志的格式布局(日志是有格式的)
log4j.appender.console.layout = org.apache.log4j.PatternLayout
### 日志的打印格式
log4j.appender.console.layout.ConversionPattern =  %d{ABSOLUTE} %5p %c{1}:%L - %m%n

打印入参

进入每一个方法时都可以写,这样可以更好的理解程序的执行过程和传入的数据情况
在这里插入图片描述

#{}与${}比较

实#{}的底层就是使用的 “?”占位符的方式来拼接SQL,而${}使用的是直接把拼接到SQL中

看看有什么不一样

  <select id="selectById" parameterType="long" resultType="...Employee">select * from employee where id = #{id}</select>
-----------------------------------------------------------------------------------------------------<select id="selectById" parameterType="long" resultType="...Employee">select * from employee where id = ${id}</select>

直接拼接会调用 g e t t e r 方法去获取值,会用属性值用于 D D L 可以用再 {} 直接拼接 会调用getter方法去获取值,会用属性值 用于DDL 可以用再 直接拼接会调用getter方法去获取值,会用属性值用于DDL可以用再{group by}
#{} 占位符 不用要用getter方法获取 DQL

使用的场景

${} 适用于静态的表名、列名等,以及一些需要进行复杂表达式的参数替换,使用时需要注意 SQL 注入风险。

#{} 主要用于替换动态生成的参数值,通常在查询条件、插入或更新的参数中使用。提高安全和速度。

@Select("select * from user where ${column} = #{value}")
User findByColumn(@Param("column") String column, @Param("value") String value);

动态SQL

if

可以匹配多个分支

 <if test="title != null">AND title like #{title}</if>

注意
如果用 < 这是一个标签开始符号,
要改成 转义符
在这里插入图片描述
如果用要用where
解决一:
在第一个if标签中加where
再在最开始的表名后面 1+1 但是这样就不会用索引了
解决二:
直接用where标签把他们嵌套进去

choose、when、otherwise

只会选择最先匹配的一个分支执行,匹配后不会再进行匹配了

<select id="findActiveBlogLike"resultType="Blog">SELECT * FROM BLOG WHERE state = ‘ACTIVE’<choose><when test="title != null">AND title like #{title}</when><when test="author != null and author.name != null">AND author_name like #{author.name}</when><otherwise>AND featured = 1</otherwise></choose>
</select>

trim、where、set

where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除
trim:通过自定义 trim 元素来定制 where 和set元素的功能。
set 元素可以用于动态包含需要更新的列,忽略其它不更新的列。
例如:set

这个set 元素会动态地在行首插入 SET 关键字,并会删掉额外的逗号<set><if test="username != null">username=#{username},</if><if test="password != null">password=#{password},</if><if test="email != null">email=#{email},</if><if test="bio != null">bio=#{bio}</if></set>等价<trim prefix="SET" suffixOverrides=",">...
</trim>

例如:WHERE

 若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。<where><if test="state != null">state = #{state}</if><if test="title != null">AND title like #{title}</if><if test="author != null and author.name != null">AND author_name like #{author.name}</if></where>等价
<trim prefix="WHERE" prefixOverrides="AND |OR ">...
</trim>

foreach(批量操作)

数据最多不能超过4M
如 批量删除

常见使用场景是对集合进行遍历(尤其是在构建 IN 条件语句的时候)
注意当使用 Map 对象(或者 Map.Entry 对象的集合)时,index 是键,item 是值。

它允许你指定一个集合,声明可以在元素体内使用的集合项(集合里的对象)(item)和索引(index)变量
。它也允许你指定开头与结尾的字符串以及集合项迭代之间的分隔符
WHERE ID in<foreach item="item" index="index" collection="list"open="(" separator="," close=")">#{item}</foreach>

在这里插入图片描述

如 批量插入需求
在这里插入图片描述
上下不匹配
在这里插入图片描述

bind

给一段语句设置一个变量
bind 元素允许你在 OGNL 表达式以外创建一个变量,并将其绑定到当前的上下文
OGNL 表达式的作用:可以存取对象的属性和调用对象的方法,通过OGNL 表达式可以迭代获取对象的结构图

<select id="selectBlogsLike" resultType="Blog"><bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />SELECT * FROM BLOGWHERE title LIKE #{pattern}
</select>

java API_MyBatis

SqlSessionFactoryBuilder

自我感觉这个类不太重要
SqlSessionFactoryBuilder 有五个 build() 方法,每一种都允许你从不同的资源中创建一个 SqlSessionFactory 实例。
第一种方法是最常用的,它接受一个指向 XML 文件

SqlSessionFactory build(InputStream inputStream)
SqlSessionFactory build(InputStream inputStream, String environment)
SqlSessionFactory build(InputStream inputStream, Properties properties)
SqlSessionFactory build(InputStream inputStream, String env, Properties props)
SqlSessionFactory build(Configuration config)

Resources 工具类

URL getResourceURL(String resource)
URL getResourceURL(ClassLoader loader, String resource)
InputStream getResourceAsStream(String resource)
InputStream getResourceAsStream(ClassLoader loader, String resource)
Properties getResourceAsProperties(String resource)
Properties getResourceAsProperties(ClassLoader loader, String resource)
Reader getResourceAsReader(String resource)
Reader getResourceAsReader(ClassLoader loader, String resource)
File getResourceAsFile(String resource)
File getResourceAsFile(ClassLoader loader, String resource)
InputStream getUrlAsStream(String urlString)
Reader getUrlAsReader(String urlString)
Properties getUrlAsProperties(String urlString)
Class classForName(String className)

SqlSessionFactory

SqlSessionFactory 有六个方法创建 SqlSession 实例。通常来说,当你选择其中一个方法时,你需要考虑以下几点:

  1. 事务处理:你希望在 session 作用域中使用事务作用域,还是使用自动提交(auto-commit)?(对很多数据库和/或 JDBC 驱动来说,等同于关闭事务支持)
  2. 数据库连接:你希望 MyBatis 帮你从已配置的数据源获取连接,还是使用自己提供的连接?
  3. 语句执行:你希望 MyBatis 复用 PreparedStatement 和/或批量更新语句(包括插入语句和删除语句)吗?
SqlSession openSession()
SqlSession openSession(boolean autoCommit)
SqlSession openSession(Connection connection)
SqlSession openSession(TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level)
SqlSession openSession(ExecutorType execType)
SqlSession openSession(ExecutorType execType, boolean autoCommit)
SqlSession openSession(ExecutorType execType, Connection connection)
Configuration getConfiguration();

ExecutorType.SIMPLE:该类型的执行器没有特别的行为。它为每个语句的执行创建一个新的预处理语句
ExecutorType.REUSE:该类型的执行器会复用预处理语句
ExecutorType.BATCH该类型的执行器会批量执行所有更新语句,如果 SELECT 在多个更新中间执行,将在必要时将多条更新语句分隔开来,以方便理解

SqlSession

游标(Cursor)与列表(List)返回的结果相同,不同的是,游标借助迭代器实现了数据的惰性加载。

try (SqlSession sqlSession = sqlSessionFactory.openSession()) {try (Cursor<User> cursor = sqlSession.selectCursor("com.example.UserMapper.getAllUsers")) {Iterator<User> iterator = cursor.iterator();while (iterator.hasNext()) {User user = iterator.next();// 处理 user 数据}}
}

游标:使用游标,查询结果不会一次性全部加载到内存中,而是通过迭代器逐行获取,这可以减少内存占用,尤其在处理大型结果集时更为有效。
列表:列表返回的方式是将查询结果集全部加载到内存的 List 集合中,这使得你可以立即访问整个结果集,但也可能导致内存占用较大,尤其是在处理大量数据时。列表方式适合于小规模的结果集,可以一次性加载并在内存中进行操作。

select 方法的三个高级版本,它们允许你限制返回行数的范围,或是提供自定义结果处理逻辑,通常在数据集非常庞大的情形下使用

<E> List<E> selectList (String statement, Object parameter, RowBounds rowBounds)
<T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds)
<K,V> Map<K,V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowbounds)
void select (String statement, Object parameter, ResultHandler<T> handler)
void select (String statement, Object parameter, RowBounds rowBounds, ResultHandler<T> handler)

RowBounds 参数会告诉 MyBatis 略过指定数量的记录,并限制返回结果的数量。RowBounds 类的 offset 和 limit 值**只有在构造函数**时才能传入,其它时候是不能修改的。

int offset = 100;  开始的点
int limit = 25;		限制的行
RowBounds rowBounds = new RowBounds(offset, limit);

数据库驱动决定了略过记录时的查询效率。为了获得最佳的性能,建议将 ResultSet 类型设置为 SCROLL_SENSITIVE 或 SCROLL_INSENSITIVE
SCROLL_SENSITIVE:滚动敏感,可以接收其他事务对数据的更改
SCROLL_INSENSITIVE:滚动不敏感

SQL类

JAVA生成代码

public class UserSqlProvider {
public String getUsers(String username, String email) {return new SQL().SELECT("id, username, email").FROM("users").WHERE().<if test="username != null">AND username = #{username}</if>.<if test="email != null">AND email = #{email}</if>.toString();}
}//使用
@SelectProvider(type = UserSqlProvider.class, method = "getUsers")
List<User> getUsers(@Param("username") String username, @Param("email") String email);

踩坑

这样写IStudentService studentService = new StudentServiceImpl();static {try {SqlSession sqlSession = MyBatisUtils.getSqlSession();IDepartmentMapper departmentMapper = sqlSession.getMapper(IDepartmentMapper.class);} catch (Exception e) {e.printStackTrace();}}
不能
会报错,excutor。。被关闭了IStudentService studentService = new StudentServiceImpl();static {try( SqlSession sqlSession = MyBatisUtils.getSqlSession()) {IDepartmentMapper departmentMapper = sqlSession.getMapper(IDepartmentMapper.class);} catch (Exception e) {e.printStackTrace();}}

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

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

相关文章

加盐加密算法

MD5加密加盐加密项目密码升级 MD5加密 MD5一系列公式进行复杂数学运算&#xff1b;特点&#xff1a;&#xff08;用途校验和、计算hash值方式、加密&#xff09; 1&#xff1a;定长&#xff1b;无论原始数据多长&#xff1b;算出的结果都是4或者8字节的版本。 2&#xff1a;冲…

Java多线程实战

Java多线程实战 java多线程&#xff08;超详细&#xff09; java自定义线程池总结 Java创建线程方式 方法1&#xff0c;继承Thread类 方法2&#xff0c;实现Runable接口 方法2-2&#xff0c;匿名内部类形式lambda表达式 方法3&#xff0c;实现Callable接口&#xff0c;允许…

【深入理解Linux内核锁】三、原子操作

我的圈子: 高级工程师聚集地 我是董哥,高级嵌入式软件开发工程师,从事嵌入式Linux驱动开发和系统开发,曾就职于世界500强企业! 创作理念:专注分享高质量嵌入式文章,让大家读有所得! 文章目录 1、原子操作思想2、整型变量原子操作2.1 API接口2.2 API实现2.2.1 原子变量结…

log4j:WARN No appenders could be found for logger问题

本文将idea场景下的使用。 IDEA中&#xff0c;将配置文件命名为log4j.properties&#xff08;该命名才会被自动加载&#xff09;&#xff0c; 并放到某个目录下&#xff08;通常放到resources目录&#xff09;&#xff0c;并在resources上右键&#xff0c;找到Mark Directory a…

微信程序 自定义遮罩层遮不住底部tabbar解决

一、先上效果 二 方法 1、自定义底部tabbar 实现&#xff1a; https://developers.weixin.qq.com/miniprogram/dev/framework/ability/custom-tabbar.html 官网去抄 简单写下&#xff1a;在代码根目录下添加入口文件 除了js 文件的list 需要调整 其他原封不动 代码&#xf…

【路由协议】使用按需路由协议和数据包注入的即时网络模拟传递率(PDR)、总消耗能量和节点消耗能量以及延迟研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

斯坦福「小镇」开源AI智能体;小米应用商店将要求AI应用符合资质标准

&#x1f989; AI新闻 &#x1f680; 斯坦福「小镇」开源AI智能体 摘要:斯坦福研究人员开源了一个类似《西部世界》的数字化「小镇」,里面有25个AI智能体可以生活、工作、社交。这项研究被视为AGI的重要开端,可能会改变游戏、企业应用领域。网友期待这项技术改善游戏NPC的交互…

PyMuPDF`库实现PDF旋转功能

本文介绍了一个简单的Python应用程序&#xff0c;用于将PDF文件转换为旋转90度的PDF文件。主要用于csdn网站中导出的博客pdf是横向的&#xff0c;看起来不是很方便&#xff0c;才想到用python编制一个将pdf从横向转为纵向的功能。 功能 该PDF转换工具具有以下功能&#xff1a…

信息安全:防火墙技术原理与应用.

信息安全&#xff1a;防火墙技术原理与应用. 防火墙是网络安全区域边界保护的重要技术。为了应对网络威胁&#xff0c;联网的机构或公司将自己的网络与公共的不可信任的网络进行隔离&#xff0c;其方法是根据网络的安全信任程度和需要保护的对象&#xff0c;人为地划分若干安全…

C#工程建立后修改工程文件名与命名空间

使用之前的项目做二次开发&#xff0c;项目快结束的时候&#xff0c;需要把主项目的名称修改成我们想要的。 之前从来没有这么干过&#xff0c;记录一下。 步骤如下&#xff1a; 1&#xff1a;打开vs2010项目解决方案&#xff0c;重命名&#xff0c;如下图所示&#xff1a; …

设计模式之原型模式Prototype的C++实现

1、原型模式提出 在软件功能设计中&#xff0c;经常面临着“某些结构复杂的对象”的创建工作&#xff0c;且创建的对象想拥有其他对象在某一刻的状态&#xff0c;则可以使用原型模型。原型模型是通过拷贝构造函数来创建对象&#xff0c;并且该对象拥有其他对象在某一刻的状态。…

Docker基础入门:镜像、容器导入导出与私有仓库搭建

Docker基础入门&#xff1a;镜像导入导出与私有仓库搭建 一、 Docker镜像、容器的导入和导出1.1、Docker镜像的导出1.2、Docker镜像的载入1.3、Docker容器的导出1.4、Docker容器的导入 二、 镜像和容器导出和导入的区别:三、commit操作_本地镜像发布到阿里云3.1、commit操作有关…

ppt中线材相交接的地方,如何绘画

ppt中线材相交接的地方&#xff1a; 在ppt中绘画线材相互交接的地方&#xff1a; 1.1绘图工具中的“弧形” 1.2小技巧 “弧形”工具点一下&#xff0c;在ppt中如下 1.3拖动活动点进行调整图形 1.4绘画圆弧 1.5调整“圆弧”的大小&#xff0c;鼠标放在“黄色点”位置&#xf…

【JVM】垃圾回收算法

目录 一、判断对象已“死” 1.1、引用计数算法 1.2、可达性分析算法 1.3、引用的概念 二、垃圾收集算法理论 2.1、分代收集理论 三、垃圾收集算法 3.1、标记--清除算法 3.2、标记--复制算法 3.3、标记--整理算法 一、判断对象已“死” 在堆里面存放着Java世界中几乎所…

【数据结构】二叉搜索树

&#x1f680; 作者简介&#xff1a;一名在后端领域学习&#xff0c;并渴望能够学有所成的追梦人。 &#x1f40c; 个人主页&#xff1a;蜗牛牛啊 &#x1f525; 系列专栏&#xff1a;&#x1f6f9;数据结构、&#x1f6f4;C &#x1f4d5; 学习格言&#xff1a;博观而约取&…

亿赛通电子文档安全管理系统任意文件上传漏洞复现

0x01 产品简介 亿赛通电子文档安全管理系统&#xff08;简称&#xff1a;CDG&#xff09;是一款电子文档安全加密软件&#xff0c;该系统利用驱动层透明加密技术&#xff0c;通过对电子文档的加密保护&#xff0c;防止内部员工泄密和外部人员非法窃取企业核心重要数据资产&…

excel隔行取数求和/均值

问题描述 如图有好多组数据&#xff0c;需要求每组数据对应位置的平均值 解决方法 SUM(IF(MOD(ROW(C$2:C$81), 8) MOD(ROW(C2), 8), C$2:C$81, 0))/10然后下拉右拉扩充即可&#xff0c;其中需要根据自身需要修改一些数据 SUM(IF(MOD(ROW(起始列$起始行:结束列$结束行), 每…

MATLAB图论合集(一)基本操作基础

本帖总结一些经典的图论问题&#xff0c;通过MATLAB如何计算答案。近期在复习考研&#xff0c;以此来巩固一下相关知识——虽然考研肯定不能用MATLAB代码哈哈&#xff0c;不过在实际应用中解决问题还是很不错的&#xff0c;比C易上手得多~ 图论中的图&#xff08;Graph&#xf…

FOSSASIA Summit 2023 - 开源亚洲行

作者 Ted 致歉&#xff1a;本来这篇博客早就该发出&#xff0c;但是由于前几个月频繁差旅导致精神不佳&#xff0c;再加上后续我又参加了 Linux 基金会 7/27 在瑞士日内瓦举办的 Open Source Congress&#xff0c;以及 7/29-30 台北的 COSCUP23&#xff0c;干脆三篇连发&#x…