说明:基于 MyBatis 有很多第三方功能插件,这些插件可以完成数据操作方法的封装、数据库逆向工程的生成等。

tkMapperMyBatis-plus 都是基于 MyBatis 提供的第三方插件,功能类似,下面介绍 tkMapper 的使用。

简介

tkMapper 就是一个 MyBatis 插件,基于 MyBatis 提供很多工具,提高开发效率,主要有以下两个功能。

  • 提供针对单表通用的数据库操作方法
  • 逆向工程(根据数据表自动生成实体类、Dao 接口、Mapper 映射文件)

MyBatis 基础环境

tkMapper 的使用需要基于 MyBatis。

  1. 创建 Spring Boot 项目,选中 Lombok、Spring Web、MyBatis Framework、MySQL Driver 依赖

  2. application.yml 配置文件中配置相关信息

    spring:
    datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springdb?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8
    username: root
    password: luis mybatis:
    type-aliases-package: com.luis.beans
    mapper-locations: classpath:mappers/*Mapper.xml

    注意:配置后,手动创建 beans 和 mappers 文件夹

  3. 创建 dao 文件夹,在启动类上添加 dao 的包扫描器 @MapperScan(basePackages = {"com.luis.dao"})

tkMapper 环境搭建

  1. 添加依赖

    <!-- tkMapper -->
    <dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper-spring-boot-starter</artifactId>
    <version>2.1.5</version>
    </dependency>

    如果自己在 maven 仓库中搜索,注意搜索关键词:mapper starter

    PS:添加后,注意手动刷新 pom

  2. 更换启动类上 dao 包的包扫描器来源,不使用原先的 @MapperScan,要使用新添加的 tkMapper 的 @MapperScan

    import tk.mybatis.spring.annotation.MapperScan;
    
    @SpringBootApplication
    @MapperScan(basePackages = {"com.luis.dao"}) //使用tkMapper的包扫描器注解
    public class SpringbootTkMapperDemoApplication { public static void main(String[] args) {
    SpringApplication.run(SpringbootTkMapperDemoApplication.class, args);
    } }

    PS:注意注解的包来源 import tk.mybatis.spring.annotation.MapperScan

  3. 以上,tkMapper 环境已经搭建完成

tkMapper 对数据的通用操作

tkMapper 提供针对单表通用的数据库操作方法。

数据准备

1. 创建数据库表
DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
`user_id` int(11) NOT NULL AUTO_INCREMENT,
`user_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`user_pwd` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`user_realname` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`user_img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
PRIMARY KEY (`user_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
2. 创建实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "users") //数据库表名和实体类类名不一致需要指定映射关系!
public class User { @Id //指定主键
private Integer userId;
private String userName;
private String userPwd;
private String userRealname;
private String userImg; }
3. 创建 Dao 接口【重点】

注意:创建的 Dao 接口需要继承 tkMapper 中提供的 MapperMySqlMapper 两个接口,这两个接口提供了对单表的通用操作。

public interface UserDao extends Mapper<User>, MySqlMapper<User> {
}

可选优化策略【建议使用】:

如果不想每次创建 dao 接口时都继承 tkMapper 中的两个接口,可以自己写一个通用的接口模板,只需要让这个通用的接口模板继承 tkMapper 中的两个接口,然后自己创建的 dao 接口只需要继承这个通用的接口模板即可!

但是,需要注意的是,这个通用的接口模板千万不能写在 dao 目录下!因为 dao 目录下的接口会被扫描到,有固定的功能用处;而我们自定义的通用接口模板只是为了继承,没有其他特殊功能!

使用示例:

1、可在 dao 目录同级创建 general 目录,在 general 目录下创建 GeneralDao 接口,并继承 tkMapper 中的两个接口。

package com.luis.general;

import tk.mybatis.mapper.common.Mapper;
import tk.mybatis.mapper.common.MySqlMapper; /**
* @Author: Luis
* @date: 2022/11/9 14:39
* @description: 自定义的通用接口模板
*/
public interface GeneralDao<T> extends Mapper<T>, MySqlMapper<T> {
}

2、创建 dao 接口,继承 GeneralDao 即可!

public interface UserDao extends GeneralDao<User> {
}
4. 测试

添加 Junit 和 springboot test 两个测试依赖:

<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!-- springboot test -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>

写测试类进行测试:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
public class UserDaoTest { @Autowired
private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解) @Test
public void test() { User user = new User();
user.setUserName("mike");
user.setUserPwd("123");
user.setUserRealname("zhangsan");
user.setUserImg("user/default.jpg"); int i = userDao.insert(user);
System.out.println("========> i = " + i);
}
}

tkMapper 常用方法之增删改

  • insert:普通添加
  • insertUseGeneratedKeys:可返回自增 id 的添加
  • updateByPrimaryKey:根据主键修改
  • deleteByPrimaryKey:根据主键删除
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
public class UserDaoTest { @Autowired
private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解) @Test
public void testInsert() { User user = new User();
user.setUserName("juno4");
user.setUserPwd("321");
user.setUserRealname("lin");
user.setUserImg("user/default.jpg"); /**
* insert: 添加(自增的id不会返回)
*/
int i = userDao.insert(user);
System.out.println("========> i = " + i);
System.out.println(user.getUserId()); //null
} @Test
public void testInsertUseGeneratedKeys() { User user = new User();
user.setUserName("juno3");
user.setUserPwd("321");
user.setUserRealname("lin");
user.setUserImg("user/default.jpg"); /**
* insertUseGeneratedKeys: 添加(自增的id可以返回)
* 注意:
* 1. 数据库中主键字段需要设置为自增
* 2. 实体类中主键属性需要使用@Id注解指定;并且需要使用包装类型Integer,不要使用int
*/
int i = userDao.insertUseGeneratedKeys(user);
System.out.println("========> i = " + i);
System.out.println(user.getUserId()); //10
} @Test
public void testUpdateByPrimaryKey() { User user = new User();
user.setUserId(10); //必须指定要修改的id
user.setUserName("juno new");
user.setUserPwd("000");
user.setUserRealname("lin new");
user.setUserImg("new.jpg"); /**
* updateByPrimaryKey:根据主键修改
*/
int i = userDao.updateByPrimaryKey(user);
System.out.println("========> i = " + i);
System.out.println(user);
} @Test
public void testDeleteByPrimaryKey() {
/**
* deleteByPrimaryKey:根据主键删除
*/
int i = userDao.deleteByPrimaryKey(9);
System.out.println("========> i = " + i);
}
}

PS:其实还有根据自定义条件修改或删除的方法(使用方法参考带条件的查询示例)

tkMapper 常用方法之查询

  • selectAll:查所有
  • selectByPrimaryKey:根据主键查所有
  • selectByExample:根据条件查所有
  • selectByRowBounds:分页查询
  • selectByExampleAndRowBounds:带条件的分页查询
  • selectCount:查总记录数
  • selectCountByExample:根据条件查总记录数
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
public class UserDaoTest { @Autowired
private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解) @Test
public void testSelectAll() {
/**
* selectAll:查询所有
*/
List<User> users = userDao.selectAll();
for (User user : users) {
System.out.println(user);
}
} @Test
public void testSelectByPrimaryKey() {
/**
* selectByPrimaryKey:根据主键查询
*/
User user = userDao.selectByPrimaryKey(10);
System.out.println(user);
} @Test
public void testSelectByExample() { //封装查询条件
Example example = new Example(User.class);
Example.Criteria criteria = example.createCriteria();
//条件信息(根据Criteria对象的各种方法进行设置)
criteria.andEqualTo("userRealname", "lin");
// criteria.orEqualTo("userPwd", "123");
// criteria.andLike("userName", "%i%"); /**
* selectByPrimaryKey:根据条件查询(PS:根据条件修改或删除与此类似)
* 注意:需要设置查询条件信息,并传入条件对象
*/
List<User> users = userDao.selectByExample(example);
for (User user : users) {
System.out.println("========> " + user);
}
} @Test
public void testSelectByRowBounds() { //分页查询信息
int pageNum = 2; //第几页
int pageSize = 3; //每页显示多少行
int start = (pageNum - 1) * pageSize; //起始显示的下标
RowBounds rowBounds = new RowBounds(start, pageSize); /**
* selectByRowBounds:查所有的分页查询
*/
List<User> users = userDao.selectByRowBounds(new User(), rowBounds);
for (User user : users) {
System.out.println("========> " + user);
} /**
* selectCount:查询总记录数
*/
int count = userDao.selectCount(new User());
System.out.println("========> count = " + count);
} @Test
public void testSelectByExampleAndRowBounds() { //封装查询条件
Example example = new Example(User.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("userRealname", "lin"); //分页查询信息
int pageNum = 2; //第几页
int pageSize = 2; //每页显示多少行
int start = (pageNum - 1) * pageSize; //起始显示的下标
RowBounds rowBounds = new RowBounds(start, pageSize); /**
* selectByExampleAndRowBounds:带条件的分页查询
*/
List<User> users = userDao.selectByExampleAndRowBounds(example, rowBounds);
for (User user : users) {
System.out.println("========> " + user);
} /**
* selectCountByExample:根据条件查询总记录数
*/
int count = userDao.selectCountByExample(example);
System.out.println("========> count = " + count);
}
}

tkMapper 关联/多表查询

说明:所有的关联/多表查询都可以由多个单表查询组成

关联/多表查询实现方式:

方式一:多次使用单表查询,然后封装数据

方式二:自定义查询方法和 SQL

情景:基于以上的用户表,新添加一个订单表 orders,订单表中有订单信息,但是也有用户 id;

要求:在查询用户表的同时还要查询出用户的订单信息,这就涉及到了两张表的查询。

具体业务要求:根据用户名查询用户的所有信息,包括订单信息。

数据准备

新建订单表 orders:

DROP TABLE IF EXISTS `orders`;
CREATE TABLE `orders` (
`order_id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`receiver_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`receiver_mobile` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`receiver_address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
PRIMARY KEY (`order_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact; INSERT INTO `orders` VALUES (1, 1, 'luis', '13344445555', '湖北武汉');

新建实体类 Order:

@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "orders")
public class Order { @Id
private Integer orderId;
private Integer userId;
private String receiverName;
private String receiverMobile;
private String receiverAddress; }

新建 dao 接口:

注意,此处 dao 接口继承的是自定义的通用接口模板,相关说明参见之前创建示例 UserDao 的步骤。

也可以直接继承 tkMapper 的两个接口。(注意灵活运用!)

public interface OrderDao extends GeneralDao<Order> {
}

说明:进行关联/多表查询前,需要修改下之前的 User 实体类,在实体类中需要添加一个订单的字段,以便查询出用户所关联的订单信息。

@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "users") //数据库表名和实体类类名不一致需要指定映射关系!
public class User { @Id //指定主键
private Integer userId;
private String userName;
private String userPwd;
private String userRealname;
private String userImg; //订单
private List<Order> orderList; }
方式一:多次单表查询
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
public class UserDaoTest { @Autowired
private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
@Autowired
private OrderDao orderDao; @Test
public void test() { //根据用户名查询用户信息
Example example = new Example(User.class);
Example.Criteria criteria = example.createCriteria();
criteria.andEqualTo("userName", "luis");
//条件查询
List<User> users = userDao.selectByExample(example);
User user = users.get(0); //根据用户id查询订单信息
Example example1 = new Example(Order.class);
Example.Criteria criteria1 = example.createCriteria();
criteria.andEqualTo("userId", user.getUserId());
//条件查询
List<Order> orders = orderDao.selectByExample(example1); //将查询到的订单信息设置到user中
user.setOrderList(orders); System.out.println("========> " + user);
}
}
方式二:自定义连接查询
  1. UserDao 接口中新建查询方法

    public interface UserDao extends GeneralDao<User> {
    
        public User selectByUserName(String userName);
    }
  2. mappers 目录下创建对应的 UserMapper.xml 文件,自定义查询 SQL

    <?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.luis.dao.UserDao"> <resultMap id="userMap" type="com.luis.beans.User">
    <id column="user_id" property="userId"/>
    <result column="user_name" property="userName"/>
    <result column="user_pwd" property="userPwd"/>
    <result column="user_realname" property="userRealname"/>
    <result column="user_img" property="userImg"/>
    <collection property="orderList" ofType="com.luis.beans.Order">
    <id column="order_id" property="orderId"/>
    <result column="user_id" property="userId"/>
    <result column="receiver_name" property="receiverName"/>
    <result column="receiver_mobile" property="receiverMobile"/>
    <result column="receiver_address" property="receiverAddress"/>
    </collection>
    </resultMap> <select id="selectByUserName" resultMap="userMap">
    select u.user_id,u.user_name,u.user_pwd,u.user_realname,u.user_img,
    o.order_id,o.user_id,o.receiver_name,o.receiver_mobile,o.receiver_address
    from users u inner join orders o
    on u.user_id = o.user_id;
    </select>
    </mapper>
  3. 测试

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = SpringbootTkMapperDemoApplication.class) //启动类.class
    public class UserDaoTest { @Autowired
    private UserDao userDao; //如果爆红线不用管(或Dao接口上添加@Repository注解)
    @Autowired
    private OrderDao orderDao; @Test
    public void test02() { //使用自定义的查询方法
    User user = userDao.selectByUserName("luis");
    System.out.println("========> " + user);
    }
    }

逆向工程

所谓逆向工程,就是通过数据库表,来自动生成实体类、dao 接口和 mapper 文件。

需要注意的是,本逆向工程是最好配合 tkMapper 环境使用,因为,有一些配置和 tkMapper 相关,如生成的 dao 接口会继承自定义的通用接口模板,而该通用的接口模板就是继承了 tkMapper 中的两个接口,从而才能使用 tkMapper 提供的通用数据操作方法;还有,生成的实体类上的注解需要依赖 tkMapper 环境。

重要说明:本逆向工程使用的 mysql 版本是低版本 5.1.36!经测试,如果使用高版本如 8.xxx,很大概率会生成有问题!所以建议项目中统一使用低版本的 MySQL。

  1. 在 pom.xml 中 build 的 plugins 下添加下列生成器插件

    <!-- mybatis-generator-maven-plugin -->
    <plugin>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-maven-plugin</artifactId>
    <version>1.3.6</version>
    <!-- 生成器配置文件位置;如果还没有添加,可以先注释,添加后再放开 -->
    <configuration>
    <configurationFile>
    ${basedir}/src/main/resources/generator/GeneratorConfig.xml
    </configurationFile>
    </configuration>
    <!-- 插件所需的两个依赖 -->
    <dependencies>
    <!-- mysql -->
    <dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.36</version>
    </dependency>
    <!-- mapper -->
    <dependency>
    <groupId>tk.mybatis</groupId>
    <artifactId>mapper</artifactId>
    <version>4.1.5</version>
    </dependency>
    </dependencies>
    </plugin>

    注意:推荐直接复制,但如果想自己在 maven 仓库中搜索,注意关键词:mybatis-generator-maven-plugin,并且,千万注意,你搜索到的肯定是依赖,而并非插件!此时,你只需要复制依赖的 gav 坐标,自己在 pom 中创建空 plugin 标签,将 gav 坐标复制进去即可!(如果相关依赖刷新添加失败,可以复制到 dependences 下,重新刷新添加试试,添加成功后复制回来即可)

  2. 注意查看项目中是否自定义有通用接口模板 GeneralDao,使其继承 tkMapper 的两个接口;如果没有,则在 dao 同级目录,创建 general 目录,在 general 目录下创建自定义通用接口模板 GeneralDao,继承 tkMapper 的两个接口;

    public interface GeneralDao<T> extends Mapper<T>, MySqlMapper<T> {
    }
  3. resources/generator 下添加 GeneratorConfig.xml 生成器配置(创建并复制后改主要配置即可)

    主要需要配置:配置数据库连接、配置实体类存放路径、配置 XML 存放路径、配置 DAO 存放路径、配置 GeneralDao

    注意:默认配置是生成指定数据库中所有表,也可以自定义的指定只生成哪些表

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE generatorConfiguration
    PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
    "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration>
    <!-- 引入数据库连接配置 -->
    <!-- <properties resource="jdbc.properties"/>--> <context id="Mysql" targetRuntime="MyBatis3Simple" defaultModelType="flat">
    <property name="beginningDelimiter" value="`"/>
    <property name="endingDelimiter" value="`"/> <!-- 配置 GeneralDao -->
    <plugin type="tk.mybatis.mapper.generator.MapperPlugin">
    <property name="mappers" value="com.luis.general.GeneralDao"/>
    </plugin> <!-- 配置数据库连接(注意数据库版本问题,需要使用低版本的,高版本可能出现问题!) -->
    <jdbcConnection driverClass="com.mysql.jdbc.Driver"
    connectionURL="jdbc:mysql://localhost:3306/springdb?serverTimezone=UTC"
    userId="root" password="luis">
    </jdbcConnection> <!-- 配置实体类存放路径 -->
    <javaModelGenerator targetPackage="com.luis.beans" targetProject="src/main/java"/> <!-- 配置 XML 存放路径 -->
    <sqlMapGenerator targetPackage="/" targetProject="src/main/resources/mappers"/> <!-- 配置 Dao 存放路径 -->
    <javaClientGenerator targetPackage="com.luis.dao" targetProject="src/main/java" type="XMLMAPPER"/> <!-- 配置需要指定生成的数据库和表,% 代表所有表 -->
    <table tableName="%">
    <!-- mysql 配置 -->
    <!-- <generatedKey column="id" sqlStatement="Mysql" identity="true"/>-->
    </table>
    <!-- <table tableName="tb_roles">-->
    <!-- &lt;!&ndash; mysql 配置 &ndash;&gt;-->
    <!-- <generatedKey column="roleid" sqlStatement="Mysql" identity="true"/>-->
    <!-- </table>-->
    <!-- <table tableName="tb_permissions">-->
    <!-- &lt;!&ndash; mysql 配置 &ndash;&gt;-->
    <!-- <generatedKey column="perid" sqlStatement="Mysql" identity="true"/>-->
    <!-- </table>-->
    </context>
    </generatorConfiguration>
  4. 打开 IDEA 右侧 Maven 窗口,找到项目--》Plugins--》mybatis-generator--》mybatis-generator:generate,双击执行逆向生成即可!

    示例图:

  5. 查看 beans、dao、mappers 目录下的生成情况,看生成的相关接口是否符合开发要求,根据情况可做相关修改,然后进行相关测试。

Spring Boot 中使用 tkMapper的更多相关文章

  1. spring boot(三):Spring Boot中Redis的使用

    spring boot对常用的数据库支持外,对nosql 数据库也进行了封装自动化. redis介绍 Redis是目前业界使用最广泛的内存数据存储.相比memcached,Redis支持更丰富的数据结 ...

  2. Spring Boot中的事务管理

    原文  http://blog.didispace.com/springboottransactional/ 什么是事务? 我们在开发企业应用时,对于业务人员的一个操作实际是对数据读写的多步操作的结合 ...

  3. Spring Boot中的注解

    文章来源:http://www.tuicool.com/articles/bQnMra 在Spring Boot中几乎可以完全弃用xml配置文件,本文的主题是分析常用的注解. Spring最开始是为了 ...

  4. 在Spring Boot中使用Https

    本文介绍如何在Spring Boot中,使用Https提供服务,并将Http请求自动重定向到Https. Https证书 巧妇难为无米之炊,开始的开始,要先取得Https证书.你可以向证书机构申请证书 ...

  5. Spring Boot中使用Swagger2构建强大的RESTful API文档

    由于Spring Boot能够快速开发.便捷部署等特性,相信有很大一部分Spring Boot的用户会用来构建RESTful API.而我们构建RESTful API的目的通常都是由于多终端的原因,这 ...

  6. Dubbo在Spring和Spring Boot中的使用

    一.在Spring中使用Dubbo 1.Maven依赖 <dependency> <groupId>com.alibaba</groupId> <artifa ...

  7. springboot(十一):Spring boot中mongodb的使用

    mongodb是最早热门非关系数据库的之一,使用也比较普遍,一般会用做离线数据分析来使用,放到内网的居多.由于很多公司使用了云服务,服务器默认都开放了外网地址,导致前一阵子大批 MongoDB 因配置 ...

  8. springboot(三):Spring boot中Redis的使用

    spring boot对常用的数据库支持外,对nosql 数据库也进行了封装自动化. redis介绍 Redis是目前业界使用最广泛的内存数据存储.相比memcached,Redis支持更丰富的数据结 ...

  9. Spring Boot中使用Swagger2构建API文档

    程序员都很希望别人能写技术文档,自己却很不愿意写文档.因为接口数量繁多,并且充满业务细节,写文档需要花大量的时间去处理格式排版,代码修改后还需要同步修改文档,经常因为项目时间紧等原因导致文档滞后于代码 ...

随机推荐

  1. 究竟什么是Shadow DOM?

    shadow dom 是什么? 顾名思义,shadow dom直译的话就是影子dom,但我更愿把它理解为DOM中的DOM.因为他能够为Web组件中的 DOM和 CSS提供了封装,实际上是在浏览器渲染文 ...

  2. 华为云计算灾备产品BCManager 及eBackup的组网方式

    BCManager的作用 OceanStor BCManager是面向企业数据中心存储容灾业务的管理软件,实现容灾.双活.两地三中心等容灾环境的管理,具备多种数据库应用与虚拟化环境的容灾管理功能,简单 ...

  3. HC32L110(五) Ubuntu20.04 VSCode的Debug环境配置

    目录 HC32L110(一) HC32L110芯片介绍和Win10下的烧录 HC32L110(二) HC32L110在Ubuntu下的烧录 HC32L110(三) HC32L110的GCC工具链和VS ...

  4. luogu [ZJOI2007] 矩阵游戏

    [ZJOI2007] 矩阵游戏 题目描述 小 Q 是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏――矩阵游戏.矩阵游戏在一个 \(n \times n\) 黑白方阵进行(如同国际象棋 ...

  5. 开发个RTMP播放器居然这么难?RTMP播放器对标和考察指标

    好多开发者提到,RTMP播放器,不知道有哪些对标和考察指标,以下大概聊聊我们的一点经验,感兴趣的,可以关注 github: 1. 低延迟:大多数RTMP的播放都面向直播场景,如果延迟过大,严重影响体验 ...

  6. KingbaseESV8R6 垃圾回收原理以及如何预防膨胀

    背景 KingbaseESV8R6支持snapshot too old 那么实际工作中,经常看到表又膨胀了,那么我们讨论一下导致对象膨胀的常见原因有哪些呢? 未开启autovacuum 对于未开启au ...

  7. 面试突击83:什么情况会导致@Transactional事务失效?

    一个程序中不可能没有事务,而 Spring 中,事务的实现方式分为两种:编程式事务和声明式事务,又因为编程式事务实现相对麻烦,而声明式事务实现极其简单,所以在日常项目中,我们都会使用声明式事务 @Tr ...

  8. 文件内再分类到各txt文件

    当老师叫我们帮他做事,比如文件内内容再分类,我们就可以建个面板,里面有各要导入文件按钮,先把分类内容copy下,再点按钮导入进txt文件就行啦. 以下为java代码,使用了tableLayout布局 ...

  9. 邻接矩阵bfs

    #include<bits/stdc++.h> using namespace std; int a[11][11]; bool visited[11]; void store_graph ...

  10. P1600 [NOIP2016 提高组] 天天爱跑步 (树上差分)

    对于一条路径,s-t,位于该路径上的观察员能观察到运动员当且仅当以下两种情况成立:(d[ ]表示节点深度) 1.观察员x在s-lca(s,t)上时,满足d[s]=d[x]+w[x]就能观察到,所以我们 ...