史上最详细mybatis与spring整合教程

2023-11-01

点击上方"田守枝的技术博客",关注我

mybatis本身使用比较灵活,和spring整合也有多种方式。本文一网打尽mybatis与spring整合所有方式,让你彻底掌握mybatis与spring整合原理,堪称史上最全面的mybatis与spring整合教程。内容较多,可以先收藏,耐心看完,必定有所收获。

本文总共分为以下10个部分:

  • 整合一:基础回顾

  • 整合二:SqlSessionFactoryBean

  • 整合三:SqlSessionTemplate

  • 整合四:SqlSessionDaoSupport

  • 整合五:MapperFactoryBean

  • 整合六:MapperScannerConfigurer

  • 整合七:@MapperScan

  • 整合八:事务

  • 整合九:springboot

  • 整合十:多数据源

1 基础回顾

mybatis可以单独使用,也可以与spring进行整合。在整合之后,各组件的之间的依赖关系如下图所示:

通常,我们需要在pom.xml文件中引入上述所有依赖。其中:

  • mysql-connector-java:mysql数据库驱动,用于与mysql建立真实连接。

  • datasource:数据库连接池。将建立的mysql连接维护到一个连接池中,进行链接复用。典型的连接池如druid、c3p0、tomcat-jdbc、dbcp2、hicaricp等。

  • mybatis:半自动的orm框架,无需多说。

  • mybatis-spring:mybatis本身可以单独使用,如果需要与spring进行整合,则需要额外引入mybatis-spring。

  • spring:mybatis与spring整合后,可以直接在业务层通过@Autowired注解注入Mapper,也会利用spring提供的事务管理机制。

在单独使用mybatis的情况下,我们通常是通过SqlSessionFactory创建SqlSession,然后通过SqlSession来进行增删查操作,如:

String resource = "org/mybatis/example/mybatis-config.xml";
InputStream in = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession session = sqlSessionFactory.openSession();
try {
  BlogMapper mapper = session.getMapper(BlogMapper.class);
  Blog blog = mapper.selectBlog(1);
} finally {
  session.close();
}

这里不做过多介绍,只是为接下来的内容做铺垫。

2 SqlSessionFactoryBean

SqlSessionFactory是mybatis的核心,当与spring进行整合时,我们使用mybatis-spring提供的SqlSessionFactoryBean 来创建其实例,SqlSessionFactoryBean实现了FactoryBean 接口。SqlSessionFactoryBean的配置有2种风格:

  • 保留mybatis的核心配置文件

  • 不保留mybatis的核心配置文件

1、 保留mybatis的核心配置文件

mybatis的配置依然保留在mybatis的核心配置文件mybatis-config文件中,以下是一个示例:

<?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">
<configuration>
    <settings>
        <setting name="cacheEnabled" value="true"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="defaultExecutorType" value="SIMPLE"/>
    </settings>
    <typeAliases>
        <package name="com.tianshouzhi.mybatis.entity"/>
    </typeAliases>
    <mappers>
        <mapper resource="mybatis/mappers/UserMapper.xml"/>
    </mappers>
</configuration>

细心的读者注意到,在mybatis-config.xml文件中并没有配置<environment>、<dataSource>、<transactionManager>等元素。即使配置了,也会被SqlSessionFactoryBean忽略。我们需要显式的为SqlSessionFactoryBean的dataSource属性引用一个数据源配置,如果不指定,在其初始化时就会抛出异常。通过configLocation属性,指定mybatis核心配置文件的路径。

此时SqlSessionFactoryBean配置方式如下:

<!—-SqlSessionFactoryBean-—>
<bean id="sqlSessionFactory" class=“org.mybatis.spring.SqlSessionFactoryBean">
     <!--数据源配置-->
     <property name="dataSource" ref=“dataSource"/>
     <!--通过configLocation属性指定mybatis核心配置文件mybatis-config.xml路径-->
     <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"/>
</bean>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="username" value="root"/>
        <property name="password" value="your password"/>
        <property name="url" value="jdbc:mysql://localhost:3306/mybatis"/>
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <!--其他配置-->
</bean>

2、不保留mybatis的核心配置文件

从mybatis-spring 1.3.0之后,我们可以移除mybatis-config.xml文件,将所有关于myabtis的配置都通过SqlSessionFactoryBean来指定。

以下配置案例演示了与上述等价的配置:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="typeAliasesPackage" value="com.tianshouzhi.zebracost.entity”/>
        <!--从类路径下加载在mybatis/mappers包和它的子包中所有的 MyBatis 映射器 XML 文件-->
        <property name="mapperLocations" value="classpath*:mybatis/mappers/**/*.xml"></property>
        <property name="configuration">
            <bean class="org.apache.ibatis.session.Configuration">
                <property name="mapUnderscoreToCamelCase" value="true"/>
                <property name="cacheEnabled" value="true"/>
                <property name="defaultExecutorType" value="SIMPLE"/>
            </bean>
        </property>
 </bean>

在mybatis与spring整合后, 通常我们不会再直接使用SqlSessionFactory,这种方式用起来比较麻烦。

mybatis-spring提供了易于使用的类,如SqlSessionTemplate、SqlSessionDaoSupport等,当然也有大多数读者都已经非常熟悉的MapperScannerConfigurer、MapperFactoryBean等。

3 SqlSessionTemplate

SqlSessionTemplate 是 mybatis-spring 的核心,其实现了SqlSession接口,且线程安全。使用了SqlSessionTemplate之后,我们不再需要通过SqlSessionFactory.openSession()方法来创建SqlSession实例;使用完成之后,也不要调用SqlSession.close()方法进行关闭。另外,对于事务,SqlSessionTemplate 将会保证使用的 SqlSession 是和当前 Spring 的事务相关的

SqlSessionTemplate依赖于SqlSessionFactory,其配置方式如下所示:

<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
     <constructor-arg index="0" ref="sqlSessionFactory"/>
</bean>
<bean id="userDao" class="com.tianshouzhi.mybatis.dao.UserDao"/>

之后我们可以在UserD类中直接进行注入。SqlSessionTemplate 是线程安全的, 可以被多个 DAO 所共享使用,以下是一个示例:

public class UserDao {
    private static String NAMESPACE = "com.tianshouzhi.zebracost.UserMapper";
    @Autowired
    SqlSessionTemplate sqlSession;
    public User selectById(int id) {
        User user = sqlSession.selectOne(NAMESPACE + ".selectById",id);
        return user;
    }
}

4 SqlSessionDaoSupport

除了直接注入SqlSessionTemplate,也可以编写一个Dao类继承SqlSessionDaoSupport,调用其getSqlSession()方法来返回 SqlSessionTemplate。

SqlSessionDaoSupport 需要一个 sqlSessionFactory 或 sqlSessionTemplate 属性来设置 。如果两者都被设置了 , 那么SqlSessionFactory是被忽略的。

事实上,如果你提供的是一个SqlSessionFactory,SqlSessionDaoSupport内部也会使用其来构造一个SqlSessionTemplate实例。

<bean id="userDao" class="com.tianshouzhi.zebracost.dao.UserDao">
      <property name="sqlSessionFactory" ref="sqlSessionFactory"/>
 </bean>
 或:
<bean id="userDao" class="com.tianshouzhi.zebracost.dao.UserDao">
     <property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>
</bean>

由于我们的UserDao类继承了SqlSessionDaoSupport,所以你可以在UserDao类中这样使用:

public class UserDao extends SqlSessionDaoSupport{
    private static String NAMESPACE = "com.tianshouzhi.zebracost.UserMapper";
    public User selectById(int id) {
        User user = getSqlSession().selectOne(NAMESPACE + ".selectById",id);
        return user;
    }
}

5 MapperFactoryBean

无论是使用SqlSessionTemplate,还是继承SqlSessionDaoSupport,我们都需要手工编写DAO类的代码。熟悉mybatis同学知道,SqlSession有一个getMapper()方法,可以让我们通过映射器接口的方式来使用mybatis。如:

SqlSession session = sqlSessionFactory.openSession();
try {
  UserMapper mapper = session.getMapper(UserMapper.class);
  User user = mapper.selectById(1);
} finally {
  session.close();
}

但是在与spring进行整合时,是否有更加简单的使用方法呢?能否通过@Autowired注解直接注入Mapper呢?我们期望的使用方式是这样:

public class UserService {
    @Autowired
    private UserMapper userMapper;
    public void insert(User user){
        userMapper.insert(user);
    }
}

在没有进行任何配置的情况下,直接这样操作显然是会报错的,因为UserMapper是一个接口,且不是spring管理的bean,因此无法直接注入

     这个时候,MapperFactoryBean则可以登场了,通过如下配置,MapperFactoryBean会针对UserMapper接口创建一个代理,并将其变成spring的一个bean。

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
  <property name="mapperInterface" value="com.tianshouzhi.mybatis.mapper.UserMapper" />
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

MapperFactoryBean继承了SqlSessionDaoSupport类,这也是为什么我们先介绍SqlSessionDaoSupport的原因。

        通过上述配置,我们就可以在一个业务bean中直接注入UserMapper接口了:   

public class UserService{
   @Autowired
   private UserMapper userMapper;
   ...
}

        你可能想知道MapperFactoryBean为什么具有这样的魔力,通过配置就可以使用@Autowired注解了。事实上,其底层是通过对UserMapper接口进行JDK动态代理,内部使用SqlSessionTemplate完成CRUD操作。但是这不是本文的重点,本文讲解的是mybatis是如何spring进行整合的。笔者将其会在其他文章分析MapperFactoryBean的源码。

6 MapperScannerConfigurer

通过MapperFactoryBean配置,已经是mybatis与spring进行时理想的方式了,我们可以简单的通过@Autowired注解进行注入。

但是如果有许多的Mapper接口要配置,针对每个接口都配置一个MapperFactoryBean,会使得我们的配置文件很臃肿。关于这一点,mybatis-spring包中提供了MapperScannerConfigurer来帮助你解决这个问题。

MapperScannerConfigurer可以指定扫描某个包,为这个包下的所有Mapper接口,在Spring上下文中都MapperFactoryBean。如:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="org.tianshouzhi.mybatis.user.mappers" />
</bean>

basePackage 属性是用于指定Mapper接口的包路径。如果的Mapper接口位于不同的包下,可以使用分号”;”或者逗号”,”进行分割。如:

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="aa.bb.mapper;aa.dd.mapper" />
</bean>

注意,如果某个路径还包含子包,子包中的Mapper接口递归地被搜索到。因此对于上述配置,我们可以通过公共的包名进行简化。如:

 <property name="basePackage" value="aa" />

你可能想到了,如果指定的公共的包名下面还包含了一些其他的接口,这些接口是你作为其他用途使用到的,并不能作为mybatis的Mapper接口来使用。此时,你可以通过markerInterface属性或者annotationClass属性来进行过滤。

markerInterface属性,顾名思义,通过一个标记接口(接口中不需要定义任何方法),来对Mapper映射器接口进行过滤,如:

public interface MapperInterface{}

接着,你需要将你的映射器接口继承MapperInterface,如:

public interface UserMapper implements MapperInterface{
   public void insert(User user);
}

此时你可以为MapperScannerConfigurer指定只有继承了MapperInterface接口的子接口,才为其自动注册MapperFactoryBean,如:

<property name="markerInterface" value=“com.tianshouzhi.mybatis.MybatisMapperInterface"/>

annotationClass属性的作用是类似的,只不过其是根据注解进行过滤。你不需要自定义注解,mybatis已经提供了一个@Mapper注解直接使用即可。配置如下:

<property name="annotationClass" value="org.apache.ibatis.annotations.Mapper"/>

如果同时指定了markerInterface和annotationClass属性,那么只有同时满足这两个条件的接口才会被注册为MapperFactoryBean。

细心的读者可能意识到了,前面配置MapperFactoryBean的时候,我们需要为其指定SqlSessionFactory,或者SqlSessionTemplate。

现在通过MapperScannerConfigurer来自动注册MapperFactoryBean,我们可以为MapperScannerConfigurer指定sqlSessionFactory或sqlSessionTemplate,然后由MapperScannerConfigurer在内部设置到MapperFactoryBean中,如下:

<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
<!--<property name="sqlSessionTemplate" ref="sqlSessionTemplate"/>-->

sqlSessionFactory和sqlSessionTemplate属性已经不建议使用了。原因在于,这两个属性不支持你使用spring提供的PropertyPlaceholderConfigurer的属性替换。

例如:你配置了SqlSessionFactoryBean来创建SqlSessionFactory实例,前面已经看到必须为其指定一个dataSource属性。很多用户习惯将数据源的配置放到一个独立的配置文件,如jdbc.properties文件中,之后在spring配置中,通过占位符来替换,如:

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
     <property name="username" value="${jdbc.username}"/>
     <property name="password" value="${jdbc.password}"/>
     <property name="url" value="${jdbc.url}"/>
     <property name="driverClassName" value="${jdbc.driver}"/>
</bean>

对于这样的配置,spring在初始化时会报错,因为MapperScannerConfigurer会在PropertyPlaceholderConfigurer初始化之前,就加载dataSource的配置,而此时PropertyPlaceholderConfigurer还未准备好替换的占位符的内容,所以抛出异常。

        我们可以使用另外2个属性来替代:

  • sqlSessionFactoryBeanName

  • sqlSessionTemplateBeanName

如下:

<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--<property name="sqlSessionTemplateBeanName" value="sqlSessionTemplate"/>-->

此时,你依然可以放心大胆的在你的数据源配置中,使用占位符了。

7 @MapperScan

如果读者习惯使用注解,而不是xml文件的方式进行配置,mybatis-spring提供了@MapperScan注解,其可以取代MapperScannerConfigurer。一些读者可能在springboot中也使用过@MapperScan注解,需要注意的是,@MapperScan注解是mybatis-spring中提供的,并不是mybatis-springboot-starter中提供的。

以下演示了如何通过@MapperScan注解的方式来配置mybatis与spring整合,注解中的属性可以与MapperScannerConfigurer相对应。

@Configuration
@MapperScan(
        //等价于MapperScannerConfigurer的basePackage属性 
        basePackages = “com.tianshouzhi.security.mapper”,
        //等价于MapperScannerConfigurer的markerInterface属性 
        markerInterface = MybatisMapperInterface.class,
        //等价于MapperScannerConfigurer的annotationClass属性
        annotationClass = MybatisMapper.class,
        //等价于MapperScannerConfigurer的sqlSessionFactoryBeanName属性
        sqlSessionFactoryRef = "sqlSessionFactory")
        
public class DatabaseConfig {
    //定义数据源
    @Bean
    public DataSource dataSource() {
        SimpleDriverDataSource dataSource = new SimpleDriverDataSource();
        dataSource.setUsername(“your username");
        dataSource.setPassword(“you password");
        dataSource.setUrl("jdbc:mysql://localhost:3306/mybatis?characterEncoding=UTF-8");
        dataSource.setDriverClass(com.mysql.jdbc.Driver.class);
        return dataSource;
    }
    //定义SqlSessionFactoryBean
    @Autowired
    @Bean("sqlSessionFactory")
    public SqlSessionFactoryBean sqlSessionFactory(DataSource dataSource) throws Exception {
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        ssfb.setDataSource(dataSource);
        return ssfb;
    }
}

8 事务    

上述所有的配置,还没有涉及到mybatis与spring进行整合另一个核心要点,即事务。整合后,我们需要将事务委派给spring来管理。spring提供了声明式事务管理的功能,可以让我们的事务代码变得非常简单。

        以下是事务管理器的一个配置案例:

<!--spring 事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <!--默认事务超时时间-->
        <property name="defaultTimeout" value="30000"/>
        <!--数据源-->
        <property name="dataSource" ref="dataSource" />
        <!--提交失败的话,也进行回滚-->
        <property name="rollbackOnCommitFailure" value="true"/>
    </bean>
<!--开启声明式事务-->
<tx:annotation-driven transaction-manager="transactionManager"/>

之后,在业务bean的方法上添加@Transactional注解,此时这个方法就自动具备了事务的功能,如果出现异常,会自动回滚,没有出现异常则自动交。

@Transactional  
public void transfer(final String out,final String in,final Double money) {  
            accountMapper.outMoney(out, money);  
            int i=1/0;  
            accountMapper.inMoney(in, money);  
    }

基于注解的形式的声明式事务管理器,是最为简单的,也是建议使用的方式。

然而,这里好像并没有看到mybatis与spring事务整合的相关代码,事实上,这里对开发者屏蔽了。mybatis自身提供了一个TransactionFactory接口,当通过mybatis-spring与spring进行整合后,引入了另外一个TransactionFactory接口实现SpringManagedTransactionFactory,如下图:

SpringManagedTransactionFactory,顾名思义,作用就是讲事务委托给spring进行管理。前面提到的SqlSessionFacoryBean有一个transactionFactory属性,如果没有指定的情况下,默认就是使用SpringManagedTransactionFactory。如下:

9 springboot 

mybatis开发团队为Spring Boot 提供了 mybatis-spring-boot-starter。你需要引入如下依赖:

<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>1.1.1</version>
</dependency>

使用了该starter之后,最简单的情况下,你只需要在application.yml中进行数据源的相关配置即可,不需要对mybatis进行任何配置。

spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/mybatis
    username: root
    password: your password

会自动利用该DataSource自动完成以下工作:

  • 创建SqlSessionFactoryBean

  • 创建SqlSessionTemplate

  • 扫描Mapper接口,为其注册MapperFactoryBean

 这实际上是一种"契约优先"的思想,通过默认的行为为简化复杂的配置。

作为有追求的程序员,我们想知道,mybatis-spring-boot-starter是如何帮我们完成这些默认行为。这里需要简单分析一下源码,源码很少,总共就几个类。

MybatisAutoConfiguration类中包含了自动注册的主要逻辑,这里不进行详细分析,只通过源码片段介绍其作用,注意1、2、3

org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration

@org.springframework.context.annotation.Configuration
@ConditionalOnClass({ SqlSessionFactory.class, SqlSessionFactoryBean.class })
@ConditionalOnSingleCandidate(DataSource.class)
@EnableConfigurationProperties(MybatisProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MybatisAutoConfiguration implements InitializingBean {
   //1、如果用户没有提供SqlSessionFactory,就自动创建一个SqlSessionFactory
   @Bean
   @ConditionalOnMissingBean
   public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
    ...
  }
  
  //2、如果用户没有提供SqlSessionTemplate,就自动创建利用SqlSessionFactory自动创建一个SqlSessionTemplate
  @Bean
  @ConditionalOnMissingBean
  public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
  ...
  } 
  
  //3、如果用户没有提供MapperFactoryBean,就通过AutoConfiguredMapperScannerRegistrar来自动注册MapperFactoryBean
  //注意,如果使用了@MapperScan注解,也不会生效 
  //另外,需要注意的是,默认情况下,只会对添加了@Mapper注解的映射器接口进行注册。
  @org.springframework.context.annotation.Configuration
  @Import({ AutoConfiguredMapperScannerRegistrar.class })
  @ConditionalOnMissingBean(MapperFactoryBean.class)
  public static class MapperScannerRegistrarNotFoundConfiguration implements InitializingBean {
   ...
  }
}

敏锐的读者立即发现了,mybatis-spring-boot-starter看似具有魔力,实际上只是在我们前面介绍的SqlSessionFactory、SqlSessionTemplate、MapperFactoryBean等基础知识之上,利用了springboot的扩展点,进行了一些默认的配置行为而已

另外一点需要注意的是,需要注意的是,一旦你自己提供了MapperScannerConfigurer,或者配置了MapperFactoryBean,那么mybatis-spring-boot-starter的自动配置功能将会失效。细心的读者可能发现了,这些自动配置代码上都有一个@ConditionalOnMissingBean注解,也就是我们不提供的情况下, 才会帮我们自动配置。例如,你自己通过@Bean注解,配置了MapperScannerConfigurer。

@Configuration
public class MyBatisMapperScannerConfig {
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer();
        mapperScannerConfigurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        mapperScannerConfigurer.setBasePackage(“com.tianshouzhi.mybatis.mapper");
        return mapperScannerConfigurer;
    }
}

当然,spring-boot-starter也支持在application.yml中对mybatis进行配置,如

mybatis:
  # mapper映射xml文件的所在路径
  mapper-locations: classpath:mapping/*.xml  
  # 应实体类的路径
  type-aliases-package: com.winter.model 

10 多数据源 

关于多数据源,配置麻烦一点。笔者在之前的文章剖析Spring多数据源,提供了一个多数据源实现,发布到了maven中央仓库,你可以在pom.xml中直接引用。

这个组件可以简化多数据源的开发,减少出错的可能。不过目前并未支持与springboot整合,欢迎有兴趣的读者加入开发一下这个功能。

识别二维码关注我

   扫码进群

近期发表:

源码剖析 Mybatis 映射器(Mapper)工作原理

剖析Spring多数据源

Mysql分支选择:Percona Or MariaDB

异地多活场景下的数据同步之道

分布式事务概述

数据库中间件详解

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

史上最详细mybatis与spring整合教程 的相关文章

  • c++类与对象——封装

    1 封装的意义 类和对象 C 面对对象三大特性 封装 继承 多态 C 认为万事万物都皆为对象 对象上有其属性和行为 例如 人可以作为对象 属性有姓名 年龄 身高 行为有走 跑 吃饭 唱歌 车也可以作为对象 属性有轮胎 方向盘 行为有载入 放
  • charles代理设置与数据劫持

    1 安装charles 点击帮助 ssl代理 在移动设备或远程浏览器上安装charles root证书 看到如下界面 2 在手机保证和电脑连接同一个wifi的前提下 开启手机代理 输入服务器地址 192 168 5 252 端口号为 888
  • Anaconda创建虚拟环境

    题外话 对自己最近一年多的学习做一个总结 方便日后查看 也希望可以帮助到需要的人 所有内容亲测有效 win10系统下 1 win r 然后输入cmd 打开终端窗口 2 输入命令 conda env list 可以查看当前已经安装的pytho
  • Shell中的括号、方括号、花括号、双括号和双方括号使用场景总结

    前言 最近在学习Shell脚本编程时 发现别人程序的 if then代码块 中if的条件语句中存在 双括号 双中括号 的使用 因而查阅了相关资料 同时也看到了一篇不错的博文 对Shell脚本中括号的使用作出了总结 特此记录和分享 1 括号
  • 【C++】二维数组中数组名及其&、*操作

    目录 简介 场景 结语 简介 Hello 非常感谢您阅读海轰的文章 倘若文中有错误的地方 欢迎您指出 昵称 海轰 标签 程序猿 C 选手 学生 简介 因C语言结识编程 随后转入计算机专业 获得过国家奖学金 有幸在竞赛中拿过一些国奖 省奖 已
  • 使用matlab随机森林进行数据分类预测

    当使用MATLAB进行随机森林数据分类预测时 以下是一般的步骤 准备数据集 将数据集划分为特征和标签 确保数据集已经清洗并做好特征工程 拆分数据集 将数据集分为训练集和测试集 训练集用于建立随机森林模型 测试集用于评估模型性能 建立随机森林
  • 华为机试:胡杨树补种

    沙漠种植N棵胡杨树 编号1 N 一个月后有M棵未成活 现补种K棵 如何补种 只能补种 不能新种 可以得到最多连续胡杨树 int main N 总种植数量 M 未成活胡杨数量 M 个空格分隔的数 按编号从小到大 K 最多可以补种的数量 int
  • 使用timedatectl命令修改时间和时区

    使用timedatectl命令修改时间和时区 timedatectl是Linux下的一条命令 用于控制系统时间和日期 可以用来查询和更改系统时间设定 同时可以设定和修改时区信息 1 查看当前时间 日期 时区 命令 timedatectl或者
  • Chrome打印台输入就报错Uncaught EvalError: Possible side-effect in debug-evaluate

    问题 使用devtools调试console输入报错 解决方法 关闭chrome调试台中立即求值来解决 关闭此项
  • CDH安装常见问题

    为什么80 的码农都做不了架构师 gt gt gt 1 Intall Parcel 的时候 hash verification failure 首先使用命令以下命令查看其hash值 sha1sum CDH 5 12 0 1 cdh5 12
  • REW声学测试(一):麦克风校准

    更多文章请关注微信公众号 智能音箱设计 最近按照Room EQ Wizard 软件的推荐 购买了其推荐的麦克风 miniDSP UMIK 1 这款麦克风的优点在于它是一款USB麦克风 而非卡侬头麦克风 也就是说 它可以直插电脑 而不需要外接
  • MACOS 如何使用 MSSQL(SQL server)?

    文章目录 一 如何启动SQL Server 2012 数据库服务 记录运行情况和处理方法 二 用界面工具创建自己的数据库 名称自定 试着用界面工具在该数据库 一 如何启动SQL Server 2012 数据库服务 记录运行情况和处理方法 由
  • 数据分析岗位需求分析

    本文爬取了某招聘网站数据分析职位的相关数据 基于SQL和python分析数据分析的岗位需求 了解各个行业对数据分析岗位的招聘需求分布 增进对职业前景的了解 1 爬取数据 首先 基于python的requests get json爬取某招聘网
  • 梦想世界2014年5月29日服务器维护公告,《新梦想世界》8月6日更新:药包系统上线 服务器开放等级加快...

    梦想逍遥侠 带你仗剑走天涯 在2020 ChinaJoy结束之后 多益网络于本周四对 新梦想世界 的游戏内容进行了一波内容更新 此次的更新中最主要内容就是一直受玩家们期待的新收纳系统 并且官方还改进了经验果的使用规则 加快开放服务器等级的进
  • [OpenWRT系列]一、LUCI开发之luci.http.formvalue获取表单数据

    OpenWRT系列 一 LUCI开发之luci http formvalue获取表单数据 1 前言 2 luci http formvalue 3 实现思路 4 程序代码 1 前言 开发项目过程中需要获取页面的按钮点击动作并且通过传入的值进
  • flask多线程下,连接泄露的bug【转载】

    flask多线程下 连接泄露的bug 架构图 如图所示 底层使用mysql web服务使用flask SqlAlchemy的连接池 复用连接 减少创建销毁开销 逻辑层代码使用线程池 异步IO操作 如果要异步cpu操作 可以很方便改成进程池
  • 魔兽实名好友怎么显示服务器,跨服实名组队正式开启 可邀请实名好友

    跨服实名组队正式开启 可邀请实名好友 新浪游戏 2011 10 12 10 22 国服4 2 2版本已经开放 而其中有一项大家都比较关心的功能也悄悄的开放了 那就是跨服实名好友组队系统 当你挣扎在艾泽拉斯最惨无人道副本的深处时 身边能有几个
  • Flink原理与调优

    Flink提交流程 Yarn Per Job 1 client运行脚本提交命令 2 CliFrontend实例化CliFrontendParser进行参数解析 3 CliFrontend实例化YarnJobClusterExecutor并创
  • 【EI会议】2022年国际土木与海洋工程联合会议(JCCME 2022)

    2022年国际土木与海洋工程联合会议 JCCME 2022 重要信息 会议网址 www jccme org 会议邮箱 jccme iased org 会议时间 2022年10月21 23日 召开地点 中国 上海 截稿时间 2022年9月15
  • 动态网站开发学习笔记01:网页开发基础

    目录 一 HTML基础 一 HTML简介 1 HTML 2 HTML语言的基本格式 3 声明 4 html标签 5 head标签 6 body标签 7 编写第一个网页 8 关于编写HTML文件的工具 9 HTML标签概述 1 单标签 2 双

随机推荐

  • 微信小程序实现原生导航栏和自定义头部导航栏

    原生导航栏 可以在 app json 的 window 属性中或页面的 JSON 文件中设置 navigationBarTitleText 导航栏标题内容 navigationBarTextStyle 导航栏标题颜色 navigationB
  • AD修改铜皮的透明度

    AD软件有时候铺完铜皮后 无法知道焊盘的位置 这样在打孔时候 可能会打到焊盘上 这时后可以通过修改铜皮的透明度来解决这个问题 方法 1 快捷键L 找到Transparency 然后选择Polygons 拖动进度条 修改透明比例 完成效果如下
  • PCIe热插拔:通知试热插拔&暴力热插拔

    PCIE热插拔 某些特殊的应用场合可能要求PCIe设备能够以高可靠性持续不间断运行 为此 PCIe总线采用热插拔 Hot Plug 和热切换 Hot Swap 技术 来实现不关闭系统电源的情况下更换PCIe卡设备 热切换和热插拔的主要区别是
  • TortoiseGit和Git如何使用相同的密钥

    Git密钥配置 TortoiseGit密钥配置 TortoiseGit和Git密钥配置图文教程 TortoiseGit和Git如何使用相同的密钥 使用 TortoiseGit 的 PuTTYgen 生成的私钥和使用Git的 ssh keyg
  • GVIM配置文件

    给大家分享一下我的vim的配置文件 关闭兼容模式 set nocompatible 模仿快捷键 如Ctrl A全选 Ctrl C复制等 source VIMRUNTIME vimrc example vim source VIMRUNTIM
  • 【c++】指针

    目录 1 1指针的基本概念 1 2指针变量的定义和使用 1 3指针所占内存空间 1 4空指针和野指针 1 5const修饰指针 1 6指针和数组 1 7指针和函数 1 8指针 数组 函数 1 1指针的基本概念 作用 可以通过指针间接访问内存
  • 使用Selenium和Python自动预订车票

    在本文中 我们将探讨如何使用Selenium和Python自动预订车票 我们将以12306 cn网站为例 演示自动化预订车票的过程 通过阅读本文 您将更好地了解如何使用Selenium与网页进行交互 准备工作 首先 我们需要安装Seleni
  • 信息学奥赛一本通(C++版)

    信息学奥赛一本通 C 版 总目录 1 信息学奥赛一本通 C 版 刷题 记录 2 信息学奥赛一本通 C 版 第一部分 C 语言 第一章 C 语言入门 3 信息学奥赛一本通 C 版 第一部分 C 语言 第二章 顺序结构程序设计 4 信息学奥赛一
  • sqlmap -u -r参数的使用

    SQLMAP基本使用实例 u参数 直接输入目标URL 命令实例 sqlmap u http 127 0 0 1 sql Less 1 id 1 验证过程 判断可注入的参数 判断可以用哪种SQL注入技术来注入 识别出所有存在的注入类型 尝试去
  • hbase compaction

    minor compaction 删除TTL过期数据 major compaction 被删除的数据 打了Delete标记的数据 TTL过期数据 版本号超过设定版本号的数据 Minor Compaction 指选取一些小的 相邻的HFile
  • 20个解决日常问题的Python代码片段

    在本文中 将分享20 个 Python 代码片段 以帮助你应对日常编程挑战 你可能已经知道其中一些片段 但有些其他片段对你来说可能是新的 赶紧使用这些有用的 Python 代码片段提升你的编程技能吧 1 简单的 HTTP Web 服务器 简
  • CSS 布局(一)

    到目前为止 我们已经了解了CSS基础知识 如何设置文本样式 以及如何设置和操作内容所在的框 现在是时候看看如何根据视口以及彼此之间的关系正确地安排你的盒子了 我们已经介绍了必要的先决条件 所以让我们深入了解CSS布局 查看各种功能 不同的显
  • 接上一篇 对多个模型环形旋转进行优化 指定旋转位置

    using System Collections using System Collections Generic using UnityEngine using DG Tweening public class ModelAnimal M
  • Vue全局日期格式化(过滤器式)

    设置 main js文件下 全局日期时间过滤器 Vue filter dateFormat function v let date new Date v if Number isNaN Number date date new Date l
  • 问答专场

    作为一名产品经理 或许你刚刚进入某个领域 或许你在为管理头疼 或许你在为创业辗转 或许你还不知如何拥抱移动互联网 那么 我们来聊聊吧 本期PMCAFF 问答专场 邀请到阿里巴巴无线创始人 费杰 擅长领域 创业 管理 电商 供应链 移动互联网
  • javascript--BOM(browser object model)五大对象

    浏览器对象模型 作用 访问 控制 修改浏览器 与浏览器进行交互 打开新的窗口 回退历史记录 获取url BOM与的DOM区别 JS通过BOM与浏览器进行交互 BOM的window对象包含了document对象 document对象是DOM的
  • JavaScript教程-空值合并运算符 ‘??‘优先级,循环,while,for,for...of..,for..in,do...while循环,跳出循环,break,continue

    空值合并运算符 最近新增的特性 这是一个最近添加到 JavaScript 的特性 旧式浏览器可能需要 polyfills 空值合并运算符 nullish coalescing operator 的写法为两个问号 由于它对待 null 和 u
  • 《深入理解计算机系统》实验二Bomb Lab下载和官方文档机翻

    前言 深入理解计算机系统 官网 http csapp cs cmu edu 3e labs html 该篇文章是实验二Bomb Lab的Writeup机翻 原文 http csapp cs cmu edu 3e bomblab pdf 阅读
  • 各种开源协议对比

    开源协议允许对比 Name Commercial use Modification Distribution Private use Patent use BSD Zero Clause License Academic Free Lice
  • 史上最详细mybatis与spring整合教程

    点击上方 田守枝的技术博客 关注我 mybatis本身使用比较灵活 和spring整合也有多种方式 本文一网打尽mybatis与spring整合所有方式 让你彻底掌握mybatis与spring整合原理 堪称史上最全面的mybatis与sp