当前位置: 首页 > news >正文

mybatise全接触-面试宝典-知识大全

1 . 简述什么是Mybatis和原理 ?

Mybatis工作原理:

(1)Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,加载驱动、创建连接、创建statement等繁杂的过程,开发者开发时只需要关注如何编写SQL语句,可以严格控制sql执行性能,灵活度高。
(2)作为一个半ORM框架,MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
称Mybatis是半自动ORM映射工具,是因为在查询关联对象或关联集合对象时,需要手动编写sql来完成。不像Hibernate这种全自动ORM映射工具,Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取。
(3)通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)。
(4)由于MyBatis专注于SQL本身,灵活度高,所以比较适合对性能的要求很高,或者需求变化较多的项目,如互联网项目。

2 . 请简述Mybaits的优缺点 ?

【Mybaits优点】
① 与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;
② 基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。
③ 很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)。
④ 能够与Spring很好的集成;
⑤ 提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。

【Mybaits缺点】
① SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
② SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。

3 . Mybatis是如何将SQL执行结果封装为目标对象并返回的?

方式一、

select * from user where id = #{id}

方式二

方式三
@Select(“select * from user”)
List selectAllUsers();

4 . Mybatis动态SQL作用 ?如何封装 ?有哪些动态SQL?

Mybatis动态SQL可以在Xml映射文件内,以标签的形式编写动态sql,执行原理是根据表达式的值 完成逻辑判断 并动态拼接sql的功能。Mybatis提供了9种动态sql标签:trim | where | set | foreach | if | choose | when | otherwise | bind。
映射方式

1、当列名和封装查询结果的类的属性名一一对应时:
这时MyBatis 有自动映射功能,将查询的记录封装到resultType 指定的类的对象中去

2、当列名和封装查询结果的类的属性名不对应时:
使用resultMap 标签,在标签中配置属性名和列名的映射关系

5 . MyBatis #{}和${}的区别是什么?

KaTeX parse error: Expected 'EOF', got '#' at position 10: {}是字符串替换,#̲{}是预处理;使用#{}可以有…{}时,就是把${}直接替换成变量的值。而Mybatis在处理#{}时,会对sql语句进行预处理,将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值

6 . Mybatis是如何进行分页的?

Mybatis 内部使用 RowBounds 对象进行分页,需要注意的是,它是针对 ResultSet 结果集执行的内存分页,而非数据库分页。

所以,生产环境中,不适合直接使用 MyBatis 原有的 RowBounds 对象进行分页。而是使用如下两种方案:

在 SQL 内手动书写数据库分页的参数来完成分页功能,样例代码如下:
select * from t_user limit #{start}, #{pageSize}
也可使用开源的分页插件来完成数据库分页, 如:
Mybatis-PageHelper
MyBatis-Plus ():

7 . 通常一个mapper.xml文件,都会对应一个Dao接口,这个Dao接口的工作原理是什么?

Mapper 接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Mapper接口生成代理对象 MappedProxy,代理对象会拦截接口方法,根据类的全限定名+方法名,唯一定位到一个MapperStatement并调用执行器执行所代表的sql,然后将sql执行结果返回。

Mapper接口里的方法,是不能重载的,因为是使用 全限名+方法名 的保存和寻找策略。

(1)Dao接口,就是Mapper接口。
(2)接口的全限名,就是映射文件中的namespace的值;
(3)接口的方法名,就是映射文件中Mapper的Statement的id值;
(4)接口方法内的参数,就是传递给sql的参数。
当调用接口方法时,通过 “接口全限名+方法名”拼接字符串作为key值,可唯一定位一个MapperStatement,因为在Mybatis中,每一个SQL标签,都会被解析为一个MapperStatement对象。

举例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面 id 为 findStudentById 的 MapperStatement。

8 . Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?

不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;原因就是namespace+id是作为Map的key使用的,如果没有namespace,就剩下id,那么,id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也就不同。

备注:在旧版本的Mybatis中,namespace是可选的,不过新版本的namespace已经是必填项

9 . 简述MyBatis 编程一般步骤( 重要 )?

第一步,创建 SqlSessionFactory 对象。
通过 SqlSessionFactory 获取 SqlSession 对象。
通过 SqlSession 获得 Mapper 代理对象。
通过 Mapper 代理对象,执行数据库操作。
执行成功,则使用 SqlSession 提交事务。
执行失败,则使用 SqlSession 回滚事务。
最终,关闭 session 会话。

10 . 简述MyBatis XML 映射文件中,都有哪些常见的标签?

以下列举 Mybatis 中常见的标签:

  • 映射查询语句。
  • 映射插入语句。
  • 映射更新语句。
  • 映射删除语句。
  • 对给定命名空间的缓存配置。
  • 对其他命名空间缓存配置的引用。。
  • 是最复杂也是最强大的元素,用来描述如何从数据库结果集中来加载对象。
    已被废弃!老式风格的参数映射。更好的办法是使用内联参数,此元素可能在将来被移除。文档中不会介绍此元素。
    可被其他语句引用的可重用语句块。
    标签,引用 标签的语句。
    标签,不支持自增的主键生成策略标签。
    PS: 关于 Mybatis 标签,可参见《MyBatis 官方文档 —— Mapper XML 文件》
    以下关于动态 SQL 相关的标签:

、、
、、
:集合遍历
:bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。

11 . MyBatis 是如何将 sql 执行结果转换为目标对象并返回的?有哪些映射形式?

方式一、

select * from user where id = #{id}

方式二

方式三
@Select(“select * from user”)
List selectAllUsers();

12 . 简述使用MyBatis的mapper接口调用时有哪些要求?

1)Mapper接口方法名和mapper.xml中定义的每个sql的id相同
2)Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同
3)Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同
4)Mapper.xml文件中的namespace即是mapper接口的类路径。

13 . MyBatis如何在Mapper中如何传递多个参数?

(1)第一种:
//DAO层的函数
Public UserselectUser(String name,String area);
//对应的xml,#{0}代表接收的是dao层中的第一个参数,#{1}代表dao层中第二参数,更多参数一致往后加即可。

(2)第二种: 使用 @param 注解:
public interface usermapper {
user selectuser(@param(“username”) string username,@param(“hashedpassword”) string hashedpassword);
}
然后,就可以在xml像下面这样使用(推荐封装为一个map,作为单个参数传递给mapper):

(3)第三种:多个参数封装成map
try{
//映射文件的命名空间.SQL片段的ID,就可以调用对应的映射文件中的SQL
//由于我们的参数超过了两个,而方法中只有一个Object参数收集,因此我们使用Map集合来装载我们的参数
Map map = new HashMap();
map.put(“start”, start);
map.put(“end”, end);
return sqlSession.selectList(“StudentID.pagination”, map);
}catch(Exception e){
e.printStackTrace();
sqlSession.rollback();
throw e; }
finally{
MybatisUtil.closeSqlSession();
}

14 . MyBatis实现一对一有几种方式?具体怎么操作的?

有联合查询和嵌套查询:
(1)联合查询是几个表联合查询,只查询一次, 通过在resultMap里面配置association节点配置一对一的类就可以完成;

(2)嵌套查询是先查一个表,根据这个表里面的结果的外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置

15 . MyBatis实现一对多有几种方式,怎么操作的?

有联合查询和嵌套查询。联合查询是几个表联合查询,只查询一次,通过在resultMap里面的collection节点配置一对多的类就可以完成;嵌套查询是先查一个表,根据这个表里面的 结果的外键id,去再另外一个表里面查询数据,也是通过配置collection,但另外一个表的查询通过select节点配置

16 . 简述Mapper编写有哪几种方式?

第一种:接口实现类继承SqlSessionDaoSupport:使用此种方法需要编写mapper接口,mapper接口实现类、mapper.xml文件。
(1)在sqlMapConfig.xml中配置mapper.xml的位置:

(2)定义mapper接口:
(3)实现类集成SqlSessionDaoSupport:mapper方法中可以this.getSqlSession()进行数据增删改查。

(4)spring 配置:

第二种:使用org.mybatis.spring.mapper.MapperFactoryBean:
(1)在sqlMapConfig.xml中配置mapper.xml的位置,如果mapper.xml和mappre接口的名称相同且在同一个目录,这里可以不用配置

(2)定义mapper接口:
① mapper.xml中的namespace为mapper接口的地址
② mapper接口中的方法名和mapper.xml中的定义的statement的id保持一致
③ Spring中定义:

第三种:使用mapper扫描器:

(1)mapper.xml文件编写:
mapper.xml中的namespace为mapper接口的地址;
mapper接口中的方法名和mapper.xml中的定义的statement的id保持一致;
如果将mapper.xml和mapper接口的名称保持一致则不用在sqlMapConfig.xml中进行配置。
(2)定义mapper接口:
注意mapper.xml的文件名和mapper的接口名称保持一致,且放在同一个目录
(3)配置mapper扫描器:

(4)使用扫描器后从spring容器中获取mapper的实现对象。

17 . MyBatis 模糊查询like语句该怎么写?

第1种:在Java代码中添加sql通配符。
string wildcardname = “%smi%”;
list names = mapper.selectlike(wildcardname);

第2种:在sql语句中拼接通配符,会引起sql注入
string wildcardname = “smi”;
list names = mapper.selectlike(wildcardname);

18 . 简述MyBatis的一级、二级缓存?

(1)一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。

(2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;

(3)对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear 掉并重新更新,如果开启了二级缓存,则只根据配置判断是否刷新

19 . MyBatis是否支持延迟加载?如果支持,它的实现原理是什么?

Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,association指的就是一对一,collection指的就是一对多查询。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。

延迟加载的基本原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。

当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的

20 . 简述 Mybatis 的 Xml 映射文件和 Mybatis 内部数据结构之间的映射关系?

Mybatis 将所有 Xml 配置信息都封装到 All-In-One 重量级对象 Configuration 内部。在
Xml 映射文件中,标签会被解析为 ParameterMap 对象,其每个子元素会
被解析为 ParameterMapping 对象。标签会被解析为 ResultMap 对象,其每个子
元素会被解析为 ResultMapping 对象。每一个

21 . MyBatis动态SQL语句(OGNL语法) ?

1、if

resultType=“Blog”>
SELECT * FROM BLOG
WHERE state = ‘ACTIVE’

AND title like #{title}

AND name like #{title}

2、where
像上面的那种情况,如果where后面没有条件,然后需要直接写if判断(开头如果是 and / or 的话,会去除掉)

resultType=“Blog”>
SELECT * FROM BLOG

AND title like #{title}

AND name like #{title}

3、choose(when、otherwise)
choose 相当于 java 里面的 switch 语句。otherwise(其他情况)

resultType=“Blog”>
SELECT * FROM BLOG WHERE state = ‘ACTIVE’

AND title like #{title}

AND author_name like #{author.name}

AND featured = 1

4、trim
prefix:前缀prefixoverride:去掉第一个and或者是or

select * from test

AND a=#{a}
AND a=#{a}

5、set
set 元素主要是用在更新操作的时候,如果包含的语句是以逗号结束的话将会把该逗号忽略,如果set包含的内容为空的话则会出错。

update t_blog

title = #{title},

content = #{content},

owner = #{owner}

where id = #{id}

6、foreach
foreach主要用在构建in条件中

open separator close

相当于是in (?,?,?)

如果是个map怎么办

collection对应map的键,像这样

List ids = new ArrayList();
ids.add(1);
ids.add(2);
ids.add(3);
ids.add(6);
ids.add(7);
ids.add(9);
Map params = new HashMap();
params.put(“ids”, ids);

22 . 解释MyBatis是否可以映射到枚举类 ?

Mybatis 可以映射枚举类。

不单可以映射枚举类,Mybatis 可以映射任何对象到表的一列上。映射方式为自定义一个 TypeHandler ,实现 TypeHandler 的 ​setParameter()​ 和 ​getResult()​ 接口方法。

TypeHandler 有两个作用,一是完成从 javaType 至 jdbcType 的转换,二是完成 jdbcType 至 javaType 的转换,体现为 ​setParameter() ​和 ​getResult()​ 两个方法,分别代表设置 sql 问号占位符参数和获取列查询结果。

23 . 简述MyBatis如何使用时间timestamp做条件进行查询 ?

首先要将条件 转换为 时间戳

long startTime = TimeUtil.parseTimestamp(start);
long endTime = TimeUtil.parseTimestamp(end);

/对应工具类/
public static long parseTimestamp(String datetime){
try{
SimpleDateFormat dateformat = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
Date date = dateformat.parse(datetime);
return date.getTime()/1000;
}catch(Exception e){
e.printStackTrace();
}
return 0;
}
然后Mapper.xml中 使用BETWEEN and 和 to_timestamp

AND tdnm.create_time BETWEEN to_timestamp(#{startDate}) AND to_timestamp(#{endDate})

24 . 简述什么情况下用注解绑定,什么情况下用 xml 绑定?

当 Sql 语句比较简单时候,用注解绑定;当 SQL 语句比较复杂时候,用 xml 绑定,一般用xml 绑定的比较多

25 . Mybatis都有哪些Executor执行器?它们之间的区别是什么?

Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。

SimpleExecutor:每执行一次update或select,就开启一个Statement对象,用完立刻关闭Statement对象。

ReuseExecutor:执行update或select,以sql作为key查找Statement对象,存在就使用,不存在就创建,用完后,不关闭Statement对象,而是放置于Map内,供下一次使用。简言之,就是重复使用Statement对象。

BatchExecutor:执行update(没有select,JDBC批处理不支持select),将所有sql都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个Statement对象,每个Statement对象都是addBatch()完毕后,等待逐一执行executeBatch()批处理。与JDBC批处理相同。

作用范围:Executor的这些特点,都严格限制在SqlSession生命周期范围内

26 . MyBatis 如何获取自动生成的主键id?

1、XML配置文件

insert into person(name,pswd) values(#{name},#{pswd})

2、Mapper中的方法
int insert(Person person);
注意在调用这个方法时,返回的int值并不是主键,而是插入的记录数。主键id会被赋值到输入的person对象里,自动赋值给person对象的id属性。比如:

Person person = new Person(“name”,“psw”);
//num是插入的记录数
int num = PersonMapper.insert(person);
//person对象的id属性会变成自生成的id
int id = person.getId();

27 . 简述MyBatis中ResultType 和 ResultMap 的区别 ?

ResultMap和ResultType都是用于设置mybatis增删改查后返回的数据类型。那么什么时候用ResultMap,什么时候用ResultType呢?
如果你搜索只是返回一个值,比如说String ,或者是int,那你直接用resultType就行了。
例如:
//dao中的接口
int addArticleThumbs(String id);

update

art_thumbs = art_thumbs+1

where
id = #{id}

该SQL返回的是int型,那么ResultType定义成int型即可直接与Java进行绑定(基本数据类型默认可不写)。

  1. 但是你如果是返回一个复杂的对象,就可以使用ResultMap(当然ResultType也是可以的)。
    例如:
    创建User 对象, 拥有两个字段id,userName。
    //dao中的接口
    User queryUser(String id);

从代码中可以清晰的看出,resultMap可以对返回的参数进行配置,mybatis默认会进行驼峰转换,当数据库字段和Java对象字段不满足驼峰(列名不匹配),可以通过这里来配置,进行字段匹配

28 . 解释MyBatis中Mapper接口中的方法支持重载么?

在MyBatis中,Mapper接口中的方法不支持重载。
在MyBatis源码中有这么几行代码,我们可以看到,在解析XML配置文件创建Mapper接口对应方法的时候,采用了【 接口全类名+方法名】的方式作为 StrictMap(MappedStatement数据存放的Map集合)的key值,而源码中对于StrictMap的put方法进行了判断,如果存入的数据key已重复,则会抛出异常,所以,Mapper接口中的方法不支持重载

29 . MyBatis中动态SQL的执行原理是什么?

在MyBatis中,动态SQL的执行原理大致可以分为三个阶段:初始化阶段、代理阶段、数据读写阶段,每个阶段都在做不同的事情。

初始化阶段:通过 XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder 来解析XML配置文件中的信息 存储到Configuration类中的。
代理阶段:首先从Configuration配置类MapperRegistry对象中获取Mapper接口和对应的代理对象工厂信息,然后再利用代理对象工厂MapperProxyFactory创建实际代理类,最后在MapperProxy类中通过MapperMethod类对象内保存的对应方法的信息,以及对应的SQL语句的信息进行分析,最终确定对应的增强方法的调用。
数据读写阶段:通过四种Executor调用四种Handler进行数据查询和数据封装返回

30 . MyBatis如何在配置多数据源 ?

先将spring boot自带的DataSourceAutoConfiguration禁掉,因为它会读取application.properties文件的spring.datasource.*属性并自动配置单数据源。在@SpringBootApplication注解中添加exclude属性即可

@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
public class XxlJobExecutorApplication {
public static void main(String[] args) {
SpringApplication.run(XxlJobExecutorApplication.class, args);
}
}
连接配置。
properties
########################## 主数据源 ##################################
spring.datasource.primary.jdbc-url=jdbc:mysql://127.0.0.1:3306/oppo?characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.primary.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.primary.username=root
spring.datasource.primary.password=123456

########################## 第二个数据源 ###############################
spring.datasource.datasource2.jdbc-url=jdbc:mysql://127.0.0.1:3306/demo?characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.datasource2.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.datasource2.username=root
spring.datasource.datasource2.password=123456

#####sql打印#####
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
logging.level.com.xxl.job.executor.mapper=debug
注意,配置中的数据源连接 url 末尾使用的是 jdbc-url.

因为使用了 Mybatis 框架,所以 Mybatis 框架的配置信息也是少不了的,指定扫描目录 mapper 下的mapper xml 配置文件。

多数据源配置
上面你应该看到了,到目前为止和 Mybatis 单数据源写法唯一的区别就是 Mapper 接口使用不同的目录分开了,那么这个不同点一定会在数据源配置中体现。

主数据源
开始配置两个数据源信息,先配置主数据源,配置扫描的 MapperScan 目录为 com.wdbyte.mapper.primary

java
@Configuration
@MapperScan(basePackages = {“com.xxl.job.executor.mapper.primary”}, sqlSessionFactoryRef = “sqlSessionFactory”)
public class PrimaryDataSourceConfig {

@Bean(name = “dataSource”)
@ConfigurationProperties(prefix = “spring.datasource.primary”)
@Primary
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}

@Bean(name = “sqlSessionFactory”)
@Primary
public SqlSessionFactory sqlSessionFactory(@Qualifier(“dataSource”) DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(“classpath:com/xxl/job/executor/mapper/primary/*.xml”));
return bean.getObject();
}

@Bean(name = “transactionManager”)
@Primary
public DataSourceTransactionManager transactionManager(@Qualifier(“dataSource”) DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}

@Bean(name = “sqlSessionTemplate”)
@Primary
public SqlSessionTemplate sqlSessionTemplate(@Qualifier(“sqlSessionFactory”) SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}

}
和单数据源不同的是这里把

dataSource
sqlSessionFactory
transactionManager
sqlSessionTemplate
都单独进行了配置,简单的 bean 创建,下面是用到的一些注解说明。

@ConfigurationProperties(prefix = “spring.datasource.primary”):使用spring.datasource.primary 开头的配置。
@Primary :声明这是一个主数据源(默认数据源),多数据源配置时必不可少。
@Qualifier:显式选择传入的 Bean。
第二个数据源
第二个数据源和主数据源唯一不同的只是 MapperScan 扫描路径和创建的 Bean 名称,同时没有 @Primary 主数据源的注解。

java
/**

  • 第二个数据源配置
    */
    @Configuration
    @MapperScan(basePackages = {“com.xxl.job.executor.mapper.second”}, sqlSessionFactoryRef = “sqlSessionFactory2”)
    public class SecondDataSourceConfig {

@Bean(name = “dataSource2”)
@ConfigurationProperties(prefix = “spring.datasource.datasource2”)
public DataSource dataSource() {
return DataSourceBuilder.create().build();
}

@Bean(name = “sqlSessionFactory2”)
public SqlSessionFactory sqlSessionFactory(@Qualifier(“dataSource2”) DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(“classpath:com/xxl/job/executor/mapper/second/*.xml”));
return bean.getObject();
}

@Bean(name = “transactionManager2”)
public DataSourceTransactionManager transactionManager(@Qualifier(“dataSource2”) DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}

@Bean(name = “sqlSessionTemplate2”)
public SqlSessionTemplate sqlSessionTemplate(@Qualifier(“sqlSessionFactory2”) SqlSessionFactory sqlSessionFactory) {
return new SqlSessionTemplate(sqlSessionFactory);
}
}
注意:因为已经在两个数据源中分别配置了扫描的 Mapper 路径,如果你之前在 SpringBoot 启动类中也使用了 Mapper 扫描注解,需要删掉。

31 . 简述Mybatis 和 Hibernate 持久层框架之间的区别 ?

一、Mybatis
MyBatis 支持通过 XML 或注解的方式来配置需要运行的 SQL 语句,并且,最终由框架本身将 Java 对象和 SQL 语句映射生成最终执行的 SQL ,执行后,再将结果映射成 Java 对象返回。

相较于 Hibernate, Mybatis 因为可以编写原生的 SQL ,也就是说,能够严格控制 SQL 执行性能,灵活度高。但是灵活的前提是 MyBatis 无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套 SQL 映射文件,工作量大。

PS: 现在一般借助于一些自动化的插件,来帮我们自动生成相关代码,极大地提升了开发效率。还可以使用 MyBatis-Plus 框架,内部集成了常用的 SQL 操作,也是非常不错的。

二、Hibernate
再来说说 Hibernate, 它对象/关系映射能力强,能做到数据库无关性。如果用 Hibernate 开发,无需关系 SQL 编写(不会写 SQL 的人都可以操作数据库),能节省很多代码,提高效率。但是 Hibernate 的缺点是学习门槛高,要精通门槛更高,而且怎么设计 O/R 映射,在性能和对象模型之间如何权衡,以及怎样用好 Hibernate 需要具有很强的经验和能力才行。

插一句: JPA 是基于 Hibernate 的一层封装,也就是说底层还是 Hibernate.

三、如何选型
结合公司业务,选取最适合的框架,不要为了技术而技术,否则都是耍流氓。

比如说,你所在的是相对来说较小的公司,数据量并不大,且公司开发人员的技术栈偏 Hibernate 多一些,推荐使用 JPA、Hibernate 这些无需手动编写 SQL 的持久层框架,提高开发效率、版本迭代速度。

如果说,你所在的是一家互联网公司,用户数较大,对相关 SQL 执行性能要求较为严格,则推荐使用 Mybatis。

总之,按照用户的需求在有限的资源环境下只要能做出维护性、扩展性良好的软件架构都是好架构,所以框架只有适合才是最好。

四、总结
Hibernate 属于全自动 ORM 映射工具,使用 Hibernate 查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取。 Mybatis 属于半自动 ORM 映射工具,在查询关联对象或关联集合对象时,需要手动编写 SQL 来完成。

32 . MyBatis 如何获取自增主键的?

MySQL 有两种方式获取自增主键,代码如下:

// 方式一: 使用 useGeneratedKeys + keyProperty 属性,这种在项目中比较常用

INSERT INTO user(name, password)
VALUE (#{name}, #{password})

// 方式二: 使用 `` 标签

SELECT LAST_INSERT_ID()

INSERT INTO user(name, password)
VALUE (#{name}, #{password})

Oracle 也有两种方式,分别是:

序列 (推荐使用)
触发器 (不太推荐使用)。
这里仅说下推荐使用的序列方式,根据 执行的时机, 分以下两种,示例代码如下:

// 这个是创建表的自增序列
CREATE SEQUENCE student_sequence
INCREMENT BY 1
NOMAXVALUE
NOCYCLE
CACHE 10;

// 方式一,使用 `` 标签 + BEFORE

select student_sequence.nextval FROM dual

INSERT INTO student(student_id, student_name, student_age)
VALUES (#{student_id},#{student_name},#{student_age})

// 方式二,使用 `` 标签 + AFTER

SELECT SEQ_ZONE.CURRVAL AS id FROM dual

INSERT INTO TBL_ZONE (ID, NAME )
VALUES (SEQ_ZONE.NEXTVAL, #{name,jdbcType=VARCHAR})

33 . 简述Mybatis的插件运行原理,以及如何编写一个插件?

Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这4种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这4种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。

编写插件:实现Mybatis的Interceptor接口并复写intercept()方法,然后再给插件编写注解,指定要拦截哪一个接口的哪些方法即可,最后在配置文件中配置你编写的插件

34 . MyBatis当实体类中的属性名和表中的字段名不一样 ,怎么办 ?

第1种: 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。

第2种: 通过来映射字段名和实体类属性名的一一对应的关系。

35 . 请用MyBatis代码显示一对一、一对多的关联查询 ?

36 . 简述什么是MyBatis的接口绑定?有哪些实现方式?

接口绑定,就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句绑定,我们直接调用接口方法就可以,这样比起原来了SqlSession提供的方法我们可以有更加灵活的选择和设置。

接口绑定有两种实现方式,一种是通过注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定;另外一种就是通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。当Sql语句比较简单时候,用注解绑定, 当SQL语句比较复杂时候,用xml绑定,一般用xml绑定的比较多

37 . 详细简述什么是 MyBatis 的接口绑定 ?

Mybatis的接口绑定,就是把接口里面的方法和SQL语句绑定,以及 SQL 执行的结果与方法的返回值进行转换匹配。
接口绑定有两种实现方式 :

  1. 通过注解绑定,就是在接口的方法上面加上 @Select、@Update等注解,里面包含Sql语句来绑定;
  2. 通过xml里面写SQL来绑定, 在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名

38 . MyBatis映射文件中A标签引用B标签,如果B标签在A的后面定义,可以吗?

虽然 Mybatis 解析 Xml 映射文件是按照顺序解析的,但是,被引用的 B 标签依然可以定义在任何地方,Mybatis 都可以正确识别。

原理:
Mybatis 解析 A 标签时,发现引用了 B 标签,未解析到 B 标签,此时会把 A 标签标记为未解析状态;
继续解析下面内容,把剩下解析完之后,再解析标记为未解析的标签;
此时已解析到 B 标签,此时再解析A标签时,B标签已经存在,A 标签也就顺利解析完成。

39 . MyBatis不同映射文件中的id是否可以重复?

可以重复,但是需要映射文件的namespace不同
不同的 Xml 映射文件,如果配置了 namespace,那么 id 可以重复;如果没有配置 namespace,那么 id 不能重复。
原因就是 namespace+id 是作为 Map的 key使用的,如果没有 namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。
有了 namespace,自然 id 就可以重复,namespace 不同,namespace+id 自然也就不同

40 . 简述MyBatis如何使用日志记录分析 ?

Mybatis内置的日志工厂提供日志功能,具体的日志实现有以下几种工具:
SLF4J
Apache Commons Logging
Log4j 2
Log4j
JDK logging
具体选择哪个日志实现工具由MyBatis的内置日志工厂确定。它会使用最先找到的(按上文列举的顺序查找)。 如果一个都未找到,日志功能就会被禁用。
不少应用服务器的classpath中已经包含Commons Logging,如Tomcat和WebShpere, 所以MyBatis会把它作为具体的日志实现。记住这点非常重要。这将意味着,在诸如 WebSphere的环境中——WebSphere提供了Commons Logging的私有实现,你的Log4J配置将被忽略。 这种做法不免让人悲催,MyBatis怎么能忽略你的配置呢?事实上,因Commons Logging已经存 在了,按照优先级顺序,Log4J自然就被忽略了!不过,如果你的应用部署在一个包含Commons Logging的环境, 而你又想用其他的日志框架,你可以根据需要调用如下的某一方法:

org.apache.ibatis.logging.LogFactory.useSlf4jLogging();
org.apache.ibatis.logging.LogFactory.useLog4JLogging();
org.apache.ibatis.logging.LogFactory.useJdkLogging();
org.apache.ibatis.logging.LogFactory.useCommonsLogging();
org.apache.ibatis.logging.LogFactory.useStdOutLogging();
如果的确需要调用以上的某个方法,请在其他所有MyBatis方法之前调用它。另外,只有在相应日志实现中存在 的前提下,调用对应的方法才是有意义的,否则MyBatis一概忽略。如你环境中并不存在Log4J,你却调用了 相应的方法,MyBatis就会忽略这一调用,代之默认的查找顺序查找日志实现。

41 . 简述Mybatis中如何指定使用哪一种Executor执行器?

1.在Mybatis配置文件中,在设置(settings)可以指定默认的ExecutorType执行器类型,也可以手动DefaultSqlSessionFactory的创建SqlSession的方法传递ExecutorType类型参数,如SqlSession openSession(ExecutorType execType)。

2.配置默认的执行器。SIMPLE就是普通的执行器;REUSE执行器会重用预处理语句(preparedstatements); BATCH 执行器将重用语句并执行批量更新。

42 . 简述什么是MyBatis 流式查询 ?

流式查询指的是查询成功后不是返回一个集合而是返回一个迭代器,应用每次从迭代器取一条查询结果。流式查询的好处是能够降低内存使用。

如果没有流式查询,我们想要从数据库取 1000 万条记录而又没有足够的内存时,就不得不分页查询,而分页查询效率取决于表设计,如果设计的不好,就无法执行高效的分页查询。因此流式查询是一个数据库访问框架必须具备的功能。

流式查询的过程当中,数据库连接是保持打开状态的,因此要注意的是:执行一个流式查询后,数据库访问框架就不负责关闭数据库连接了,需要应用在取完数据后自己关闭

43 . MyBatis 如何防止 SQL 注入?

MyBatis框架作为一款半自动化的持久层框架,其SQL语句都要我们自己手动编写,这个时候当然需要防止SQL注入。其实,MyBatis的SQL是一个具有“输入+输出”的功能,类似于函数的结构,参考上面的两个例子。其中,parameterType表示了输入的参数类型,resultType表示了输出的参数类型。回应上文,如果我们想防止SQL注入,理所当然地要在输入参数上下功夫。上面代码中使用#的即输入参数在SQL中拼接的部分,传入参数后,打印出执行的SQL语句,会看到SQL是这样的:

select id, username, password, role from user where username=? and password=?
不管输入什么参数,打印出的SQL都是这样的。这是因为MyBatis启用了预编译功能,在SQL执行前,会先将上面的SQL发送给数据库进行编译;执行时,直接使用编译好的SQL,替换占位符“?”就可以了。因为SQL注入只能对编译过程起作用,所以这样的方式就很好地避免了SQL注入的问题。

【底层实现原理】MyBatis是如何做到SQL预编译的呢?其实在框架底层,是JDBC中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的SQL语句。这种“准备好”的方式不仅能提高安全性,而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需再编译。

//安全的,预编译了的
Connection conn = getConn();//获得连接
String sql = “select id, username, password, role from user where id=?”; //执行sql前会预编译号该条语句
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setString(1, id);
ResultSet rs=pstmt.executeUpdate();

//不安全的,没进行预编译
private String getNameByUserId(String userId) {
Connection conn = getConn();//获得连接
String sql = “select id,username,password,role from user where id=” + id;
//当id参数为"3;drop table user;"时,执行的sql语句如下:
//select id,username,password,role from user where id=3; drop table user;
PreparedStatement pstmt = conn.prepareStatement(sql);
ResultSet rs=pstmt.executeUpdate();

}
【 结论:】

#{}:相当于JDBC中的PreparedStatement

${}:是输出变量的值

简单说,#{}是经过预编译的,是安全的;${}是未经过预编译的,仅仅是取变量的值,是非安全的,存在SQL注入。

如果我们order by语句后用了${},那么不做任何处理的时候是存在SQL注入危险的。你说怎么防止,那我只能悲惨的告诉你,你得手动处理过滤一下输入的内容。如判断一下输入的参数的长度是否正常(注入语句一般很长),更精确的过滤则可以查询一下输入的参数是否在预期的参数集合中。

44 . 请列举说明Mapper.xml中statement中属性含义 ?

id:sql语句唯一标识
parameterType:指定输入参数类型,mybatis通过ognl从输入对象中获取参数值拼 接在sql中。
resultType:指定输出结果类型,mybatis将sql查询结果的一行记录数据映射为resultType指定类型的对象。
resultMap:resultType可以指定pojo将查询结果映射为pojo,但需要pojo的属性名和sql查询的列名一致方可映射成功。如果sql查询字段名和pojo的属性名不一致,可以通过resultMap将字段名和属性名作一个对应关系 resultMap实质上还需要将查询结果映射到pojo对象中。
resultMap可以实现将查询结果映射为复杂类型的pojo,比如在查询结果映射对象中包括pojo 和list实现一对一查询和一对多查询。

#{}表示一个占位符号,通过#{}可以实现preparedStatement向占位符中设置值,自动进行java类型和jdbc类型转换,#{}可以有效防止sql注入。 #{}可以接收简单类型值或pojo属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。一般能用#的就别用$.
表示拼接 s q l 串,通过 {}表示拼接sql串,通过 表示拼接sql串,通过{}可以将parameterType 传入的内容拼接在sql中且不进 行jdbc类型转换, 可以接收简单类型值或 p o j o 属性值,如果 p a r a m e t e r T y p e 传输单个简单类型值, {}可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值, 可以接收简单类型值或pojo属性值,如果parameterType传输单个简单类型值,{}括号中只能是value。

45 . 简述 MyBatis-Plus 是什么框架?

Mybatis的增强框架,帮助开发人员更加简化开发。这些框架提供了大部分的简单SQL语句封装的API,提供了分页插件,简化了配置流程。不过只对单表有好的支持,多表关联查询支持差,一般需要手动编写多表的SQL,不过可以原生和增强一起使用

相关文章:

mybatise全接触-面试宝典-知识大全

1 . 简述什么是Mybatis和原理 ? Mybatis工作原理: (1)Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,加载驱动、创建连接、创建statement等繁杂的过程,开发者…...

Catalyst优化器:让你的Spark SQL查询提速10倍

目录 1 逻辑优化阶段 2.1 逻辑计划解析 2.2 逻辑计划优化 2.2.1 Catalys的优化过程 2.2.2 Cache Manager优化 2 物理优化阶段 2.1 优化 Spark Plan 2.1.1 Catalyst 的 Join 策略 2.1.2 如何决定选择哪一种 Join 策略 2.2 Physical Plan 2.2.1 EnsureRequirements 规则 3 相关文…...

【Hot100】LeetCode—416. 分割等和子集

目录 题目1- 思路2- 实现⭐152. 乘积最大子数组——题解思路 3- ACM 实现 题目 原题连接:416. 分割等和子集 1- 思路 理解为背包问题 思路: 能否将均分的子集理解为一个背包,比如对于 [1,5,11,5],判断能否凑齐背包为 11 的容量…...

前端开发知识-vue

大括号里边放键值对,即是一个对象。 一、vue可以简化前端javascript的操作。 主要特点是可以实现视图、数据的双向绑定。 使用vue主要分为三个步骤: 1.javascript中引入vue.js 可以src中可以是vue的网址,也可以是本地下载。 2.在javasc…...

【嵌入式硬件】快衰减和慢衰减

1.引语 在使用直流有刷电机驱动芯片A4950时,这款芯片采用的是PWM控制方式,我发现他的正转、反转有两种控制方式,分别是快衰减和慢衰减。 2.理解 慢衰减:相当于加在电机(感性原件)两端电压消失,将电机两端正负短接。 快衰减:相当于加在电机(感性原件)两端电压消失,将电机…...

C语言 | Leetcode C语言题解之第275题H指数II

题目&#xff1a; 题解&#xff1a; int hIndex(int* citations, int citationsSize) {int left 0, right citationsSize - 1;while (left < right) {int mid left (right - left) / 2;if (citations[mid] > citationsSize - mid) {right mid - 1;} else {left mi…...

速盾:网络安全和 CDN 之间的关系是怎样的?

网络安全和内容交付网络&#xff08;CDN&#xff09;之间有着密切的关系。网络安全主要涉及保护网络和系统免受各种威胁和攻击&#xff0c;而CDN是一种用于提供更快速、高效和可靠的内容交付服务的技术。在当今数字化和云计算时代&#xff0c;网络安全和CDN之间的关系变得更加紧…...

数据库安全:MySQL安全配置,MySQL安全基线检查加固

「作者简介」:冬奥会网络安全中国代表队,CSDN Top100,就职奇安信多年,以实战工作为基础著作 《网络安全自学教程》,适合基础薄弱的同学系统化的学习网络安全,用最短的时间掌握最核心的技术。 这一章节我们需要知道MySQL的安全基线标准和加固方式。 MySQL基线检查 1、更新…...

【SpringBoot】参数传递

1.定义URL变量 RequestMapping("/user/{username}") ResponseBody public String userProfile(PathVariable String username){ return "user:"username; } 2.定义多个URL变量 RequestMapping("/user/{username}/blog/{blogId}") Response…...

Unity 骨骼动画(Skinned Mesh Renderer): 角色动画的高级渲染

在Unity中&#xff0c;骨骼动画(Skinned Mesh Renderer)是一种用于高级角色动画渲染的组件。它允许开发者将复杂的3D模型和动画应用到游戏角色上&#xff0c;实现逼真的视觉效果。本文将探讨Skinned Mesh Renderer的基本概念、使用方法以及如何优化性能。 Skinned Mesh Render…...

花几千上万学习Java,真没必要!(三十四)

1、泛型类&#xff1a; 测试代码&#xff1a; 创建一个Box类; package settest.com; public class Box<T> { // T stands for "Type" - T是一个占位符&#xff0c;用于表示具体的类型 // 类的内部可以使用T作为类型声明变量 private T t; // 构造方法&am…...

【代码】Python3|Scrapy框架初探(汽车之家大连市二手车车辆数据爬取、清洗与可视化)

本篇主要是整个项目的介绍&#xff0c;没提到太多琐碎的技术细节&#xff0c;以后有空的话会整理一下 Scrapy 和原生爬虫的差异&#xff0c;还有它坑人的一些地方&#xff0c;单发出来。 开源地址&#xff1a;https://github.com/shandianchengzi/car_home_spider 使用说明&a…...

C#中的new以及类

new关键字的用法 实例化对象&#xff1a;使用 new 关键字可以创建一个类的实例。例如&#xff1a; ​ MyClass obj new MyClass(); 指定构造函数&#xff1a;如果类有多个构造函数&#xff0c;可以使用 new 关键字指定使用哪一个构造函数来创建对象。例如&#xff1a; ​ MyC…...

Hbase简介和快速入门

一 Hbase简介 1 HBase定义 Apache HBase™ 是以hdfs为数据存储的&#xff0c;一种分布式、可扩展的NoSQL数据库。 2 HBase数据模型 HBase的设计理念依据Google的BigTable论文&#xff0c;论文中对于数据模型的首句介绍。Bigtable 是一个稀疏的、分布式的、持久的多维排序map…...

【AI落地应用实战】Amazon Bedrock +Amazon Step Functions实现链式提示(Prompt Chaining)

一、链式提示 Prompt Chaining架构 Prompt Chaining 是一种在生成式人工智能&#xff08;如大型语言模型&#xff09;中广泛使用的技术&#xff0c;它允许用户通过一系列精心设计的提示&#xff08;Prompts&#xff09;来引导模型生成更加精确、丰富且符合特定需求的内容。 P…...

vue Ref 和 Reactive 原理解析

文章目录 RefReactive Ref ref 的语义是指向一个值的引用&#xff0c;主要用于处理基本数据类型和单一值对象&#xff0c;即对值的引用进行包装和管理&#xff0c;而不是对对象的操作进行拦截&#xff0c;对于基础类型通过 getter 和 setter 实现拦截使用 Proxy 拦截对象的所有…...

【人工智能】Transformers之Pipeline(六):图像分类(image-classification)

目录 一、引言 二、图像分类&#xff08;image-classification&#xff09; 2.1 概述 2.2 技术原理 2.3 应用场景 2.4 pipeline参数 2.4.1 pipeline对象实例化参数 2.4.2 pipeline对象使用参数 2.4 pipeline实战 2.5 模型排名 三、总结 一、引言 pipeline&#x…...

编程语言漫谈之「初始化与赋值」——以C++和汇编语言为示例

编程语言漫谈之「初始化与赋值」——以C和汇编语言为示例 1. 赋值时汇编做了什么2. 在变量定义时做初始化, 与在使用时才进行初始化, 有区别吗? 1. 赋值时汇编做了什么 当我们在C中写下如下代码: int main() {int a 10;return 0; }这是一个简单的整数类型变量a的初始化赋值…...

windows使用ssh-agent管理私钥

主要有以下几个方面: 开启openssh 的 ssh-agent 服务 打开powershell 输入 Get-Service -Name ssh-agent 查看服务是否起来Start-Service ssh-agent 启动服务Stop-Service ssh-agent 关闭服务将私钥添加到ssh-agent 添加私钥 ssh-add ~/.ssh/id_rsa查询添加哪些私钥 ssh-add -…...

PostgreSQL 之 to_timestamp函数

to_timestamp 是 PostgreSQL 中的一个函数,用于将字符串或数字转换为时间戳。以下是关于 to_timestamp 的详细介绍: 引入版本 to_timestamp 函数在 PostgreSQL 7.3 版本中引入。 语法 to_timestamp 有两种主要的用法: 1.将字符串转换为时间戳 to_timestamp(text, text)第…...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

大语言模型如何处理长文本?常用文本分割技术详解

为什么需要文本分割? 引言:为什么需要文本分割?一、基础文本分割方法1. 按段落分割(Paragraph Splitting)2. 按句子分割(Sentence Splitting)二、高级文本分割策略3. 重叠分割(Sliding Window)4. 递归分割(Recursive Splitting)三、生产级工具推荐5. 使用LangChain的…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...