MybatisPuls学习

  • 前言
  • 一、MybatisPuls有什么特点
    • 支持数据库
  • 二、使用步骤
    • 1.快速入门(官网案例)
    • 2. 配置日志输出
    • 3. MybatisPlus中的雪花算法
    • 4. 自定义ID生成策略
    • 5. 自动填充
    • 6. 乐观锁
    • 7. 查询
      • 基本查询
      • 分页查询
    • 8. 删除
      • 普通删除
      • 逻辑删除
    • ~~9. 性能分析插件(好像新版被移除了)~~
    • 9. 条件构造器
      • 判断条件
      • 使用 like + notLike + likeRight
      • 子查询
      • 降序查询
    • 10. 代码生成器
  • 总结

前言

学习之前,需要有SSM基础比较好,Mybatis可以节省我们大量的sql代码编写的时间,尤其在简单的sql语句中只需要调用一个方法即可完成增删改查


![在这里插入图片描述](https://img-blog.csdnimg.cn/e06f79d0c29b497dbde8c3575c3f56fb.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LiN5aSq5oeC57yW56iL,size_20,color_FFFFFF,t_70,g_se,x_16)

正如官方所介绍为简化开发而生

一、MybatisPuls有什么特点

特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
    内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
    内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
    内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

支持数据库

任何能使用 mybatis 进行 CRUD, 并且支持标准 SQL 的数据库,具体支持情况如下,如果不在下列表查看分页部分教程 PR 您的支持。

mysql,oracle,db2,h2,hsql,sqlite,postgresql,sqlserver,Phoenix,Gauss ,clickhouse,Sybase,OceanBase,Firebird,cubrid,goldilocks,csiidb

二、使用步骤

1.快速入门(官网案例)

参考地址

  1. 创建数据库和user表
DROP TABLE IF EXISTS user;CREATE TABLE user
(id BIGINT(20) NOT NULL COMMENT '主键ID',name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名',age INT(11) NULL DEFAULT NULL COMMENT '年龄',email VARCHAR(50) NULL DEFAULT NULL COMMENT '邮箱',PRIMARY KEY (id)
);DELETE FROM user;INSERT INTO user (id, name, age, email) VALUES
(1, 'Jone', 18, 'test1@baomidou.com'),
(2, 'Jack', 20, 'test2@baomidou.com'),
(3, 'Tom', 28, 'test3@baomidou.com'),
(4, 'Sandy', 21, 'test4@baomidou.com'),
(5, 'Billie', 24, 'test5@baomidou.com');
  1. 使用IDEA创建工程 官网默认用h2数据库我们不需要进行导入
<!--数据库驱动-->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId>
</dependency>
<!--mybatis-plus不用在导入mybatis了-->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.0.5</version>
</dependency>
  1. 配置数据源
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatisplus?useSSL=false&useUnicode=true&characterEncoding=utf-8
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
  1. 开始编码
  • 传统mybatis写法依然支持不做介绍,可参考mybatis原生案例
  • 使用mybatis-plus (pojo->mapper接口->使用)我们可以看到都不需要配置xml文件
    创建User实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {private Long id;private String name;private Integer age;private String email;
}

创建Mapper接口

//在对应的Mapper上面是实现基本的接口BaseMapper
@Repository
public interface UserMapper extends BaseMapper<User> {//所有的crud的擦欧总已经编写完毕了
}

简单看看baseMapper里面已经定义好啦非常多的接口

入口文件增加注解扫描Mapper
@MapperScan("cn.qileyun.mybatisplus.mapper")
测试一下看看

//继承baseMapper所有可以使用它的所有方法,里面已经封装好了基本crud代码
@Autowired
private UserMapper userMapper;@Test
void contextLoads() {List<User> users = userMapper.selectList(null);users.forEach(System.out::println);
}

2. 配置日志输出

#配置日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

3. MybatisPlus中的雪花算法

User user = new User();
user.setName("我爱学编程");
user.setAge(3);
user.setEmail("1541177517@qq.com");
int result = userMapper.insert(user);//帮我们自动生成id
System.out.println(result);
System.out.println(user);

我们并没有插入id,当是给我们生成一个全局唯一id,我们来探究一下

4. 自定义ID生成策略

在pojo类中定义id

  • AUTO 自增 数据库id必须是自增的
  • UUID uuid全球唯一id
  • INPUT 手动输入需要自己配置id
  • ID_WORKER_STR 数字->字符串
  • INONE 不使用id生成
  • ID_WORKER 默认全局唯一id 雪花算法
    @TableId(type = IdType.AUTO)//自增 数据库id必须是自增的private Long id;

5. 自动填充

  1. 修改数据库
  2. 修改实体类
// 字段填充内容
@TableField(fill = FieldFill.INSERT)private Date createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime;
  1. 编写处理器
@Slf4j
@Component//加入到ico容器中
public class MyMetaObjectHandler implements MetaObjectHandler {//插入时的填充策略@Overridepublic void insertFill(MetaObject metaObject) {this.setFieldValByName("createTime",new Date(),metaObject);this.setFieldValByName("updateTime",new Date(),metaObject);}//更新时的填充策略@Overridepublic void updateFill(MetaObject metaObject) {this.setFieldValByName("updateTime",new Date(),metaObject);}
}
  1. 执行插入和修改

6. 乐观锁

  • 乐观锁:顾名思义十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题,在次更新值测试

  • 悲观锁:顾名思义十分悲观,无论干什么都会上锁!再去操作!

  • 取出记录时,获取当前version

  • 更新时,带上version

  • 执行更新时,set version = newVersion where = version = oldVersion

  • 如果version不对,就更新失败

--A
update user set name = "lala",version = version+1 where id=2 and version = 1
--B 如果现在B先抢占了线程,就会导致A修改失败,因为version字段已经+1操作变成了2了
update user set name = "lala",version = version+1 where id=2 and version = 1

使用乐观锁插件

  1. 增加字段
  2. 实体类添加字段
@Version
private  Integer version;
  1. 注册组件
//扫描我们的mapper文件夹
@MapperScan("cn.qileyun.mybatisplus.mapper")
@EnableTransactionManagement
@Configuration//配置类
public class MybatisPlusConfig {//注册乐观锁插件 这个按照你的mybatis二选一/*** 旧版*/@Beanpublic OptimisticLockerInterceptor optimisticLockerInterceptor() {return new OptimisticLockerInterceptor();}/*** 新版*/@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return mybatisPlusInterceptor;}
}
  1. 测试看看
    //    测试成功的案例@Testpublic void testOptimisticLocker() {//1. 查询用户信息User user = userMapper.selectById(1L);//2.修改用户信息user.setName("zengfeiixang");user.setEmail("1541177517@qq.com");//3. 执行更新操作userMapper.updateById(user);}//   测试失败的案例@Testpublic void testOptimisticLocker2() {//1. 查询用户信息User user = userMapper.selectById(1L);//2.修改用户信息user.setName("bbbbb");user.setEmail("1541177517@qq.com");//模拟另外一个线程执行插队操作User user2 = userMapper.selectById(1L);user2.setName("aaaaaa");user2.setEmail("1541177517@qq.com");//3. 执行更新操作userMapper.updateById(user2);//执行成功userMapper.updateById(user);//更改失败如果没有乐观锁就会覆盖插队线程的值}

7. 查询

基本查询

//测试查询@Testpublic void testSelectById(){//查询单个User user = userMapper.selectById(1L);System.out.println(user);}//测试批量查询@Testpublic void testSelectByBatchId(){List<User> users = userMapper.selectBatchIds(Arrays.asList(1,2,3));users.forEach(System.out::println);}//条件查询 map@Testpublic void testSelectByBatchIds(){HashMap<String, Object> map = new HashMap<>();//自定义查询map.put("name","Tom");map.put("age",28);List<User> users = userMapper.selectByMap(map);users.forEach(System.out::println);}

分页查询

分页在网站使用的十分之多
1、原始的limit进行分页
2、pageHelper 第三方插件
3、MP其实内置了分页插件
使用教程

  1. 注册插件
//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {PaginationInterceptor paginationInterceptor = new PaginationInterceptor();return paginationInterceptor;
}/**
* 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 新版本好像用这个了没有测试 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除)
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2));return interceptor;
}
  1. 测试一下
//测试分页查询
public void testPage(){//参数1 第一页//参数2 一页条目数量IPage<User> page = new Page<>(1,5);IPage<User> userIPage = userMapper.selectPage(page, null);userIPage.getRecords().forEach(System.out::println);System.out.println(page.getTotal());//总计
}

8. 删除

普通删除

//测试删除
@Test
public void testDeleteById(){userMapper.deleteById(1468132628929495041L);
}//批量删除
@Test
public void testDeleteBatchId(){userMapper.deleteBatchIds(Arrays.asList(1468132628929495041L,1468132628929495042L));
}//通过Map删除
public void testDeleteMap(){HashMap<String, Object> map = new HashMap<>();map.put("name","lala");userMapper.deleteByMap(map);
}

逻辑删除

物理删除:从数据库中直接移除
逻辑删除:在数据库中没有移除,而是通过一个变量来让他失效!delete =0 => delete=1
可以把他看成一个回收站一样,只是给他标识一个已经不存在了

  1. 数据库增加字段
    增加int类型的delete字段并且默认值为0

  2. 实体类增加字段

@TableLogic
private Integer deleted;
  1. 编写配置
mybatis-plus:global-config:db-config:logic-delete-field: flag  # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)logic-delete-value: 1 # 逻辑已删除值(默认为 1)logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
  1. 注册插件
//逻辑删除
@Bean
public ISqlInjector sqlInjector(){return new LogicSqlInjector();
}
  1. 测试删除代码
    其实执行的不在是delete操作了而是更新了字段吧deleted = 1

    查询看看可以看出已经自动加上了deleted = 0的条件,判断是否被删除过

9. 性能分析插件(好像新版被移除了)

MP提供了性能分析插件,如果超过这个时间就停止运行!

  1. 导入插件
 //sql执行效率插件@Bean@Profile({"dev","test"})//设置dev test环境开启,保证我们的效率public PerformanceInterceptor performanceInterceptor(){PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();performanceInterceptor.setMaxTime(100);//设置sql执行的最大时间,如果超超过了就不执行performanceInterceptor.setFormat(true);//sql格式化return new PerformanceInterceptor();}
  1. 配置spring为开发环境
spring:profiles:active: dev
  1. 测试使用
    如果这个时间超过100ms就会报错

9. 条件构造器

可以看出官方有非常多的条件

判断条件

@Testvoid contextLoads() {//查询name不为空的用户,年龄大于等于12,并且邮箱不为空QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.isNotNull("name").isNotNull("email").ge("age",12);userMapper.selectList(wrapper).forEach(System.out::println);}@Testvoid test2(){//查询名字lalaQueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("name","lala");//selectOne 查询一个数据System.out.println(userMapper.selectOne(wrapper));}//查询 10 到 20 岁的用户数
@Test
void test3(){QueryWrapper<User> wrapper=new QueryWrapper<>();wrapper.between("age",10,20);
​Integer count = userMapper.selectCount(wrapper);//查询 10 到 20 岁的用户的结果数
​System.out.println(count);
}

使用 like + notLike + likeRight

@Test
void selectLike01(){QueryWrapper<User> wrapper=new QueryWrapper<>();wrapper.notLike("name","To") //名字不包含 To.like("name","o") //名字包含 o 的//左和右 左:%e   右:e%  两边:%e%//右查询.likeRight("email","test");
​List<Map<String, Object>> users = userMapper.selectMaps(wrapper);users.forEach(System.out::println);
}

子查询

@Test
void selectLike02(){QueryWrapper<User> wrapper=new QueryWrapper<>();wrapper//一个SQL语句写的子查询.inSql("id","select id from user where age<20");
​List<Object> users = userMapper.selectObjs(wrapper);users.forEach(System.out::println);
}

降序查询

@Test
void selectLike03(){QueryWrapper<User> wrapper=new QueryWrapper<>();//降序排序wrapper.orderByDesc("id");//升序排序//wrapper.orderByAsc("id");
​List<User> users = userMapper.selectList(wrapper);users.forEach(System.out::println);
}

更多的可以参考官方文档

10. 代码生成器

  1. 添加依赖
<!--代码生成器-->
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-generator</artifactId><version>3.0.7</version>
</dependency>
<!--模版 -->
<dependency><groupId>org.apache.velocity</groupId><artifactId>velocity</artifactId><version>1.7</version>
</dependency>
  1. 测试类编写生成代码类
//需要构建一个代码生成器对象AutoGenerator mpg = new AutoGenerator();//全局配置GlobalConfig gc = new GlobalConfig();String property = System.getProperty("user.dir");gc.setOutputDir(property+"/src/main/java");gc.setAuthor("奇乐云");gc.setOpen(false);gc.setFileOverride(false);//是否覆盖gc.setServiceImplName("%sService");//去除Service的I前缀gc.setIdType(IdType.ID_WORKER);gc.setDateType(DateType.ONLY_DATE);gc.setSwagger2(true);mpg.setGlobalConfig(gc);//设置数据源DataSourceConfig dsc= new DataSourceConfig();dsc.setUrl("jdbc:mysql://localhost:3306/mybatisplus?useSSL=false&useUnicode=true&characterEncoding=utf-8");dsc.setDriverName("com.mysql.cj.jdbc.Driver");dsc.setUsername("root");dsc.setPassword("123456");dsc.setDbType(DbType.MYSQL);mpg.setDataSource(dsc);//包的配置PackageConfig pc = new PackageConfig();//pc.setModuleName("blog");//模块pc.setParent("cn.qileyun.mybatisplus");//包根路径pc.setEntity("entity");pc.setMapper("mapper");pc.setService("service");pc.setController("controller");mpg.setPackageInfo(pc);//策略配置StrategyConfig strategy = new StrategyConfig();strategy.setInclude("user");//设置要映射的表 可以传入多个表strategy.setNaming(NamingStrategy.underline_to_camel);strategy.setEntityLombokModel(true);//自动lombokstrategy.setRestControllerStyle(true);strategy.setLogicDeleteFieldName("deleted");//逻辑删除字段//自动填充配置TableFill gmtCreate = new TableFill("gmt_create", FieldFill.INSERT);TableFill gmtModified = new TableFill("gmt_modified", FieldFill.INSERT_UPDATE);ArrayList<TableFill> tableFills = new ArrayList<>();tableFills.add(gmtCreate);tableFills.add(gmtModified);strategy.setTableFillList(tableFills);//乐观锁strategy.setVersionFieldName("version");strategy.setRestControllerStyle(true);strategy.setControllerMappingHyphenStyle(true);//mpg.setStrategy(strategy);mpg.execute();//执行策略

看到一个写的不错的代码生成器

package com.yixin;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.PackageConfig;
import com.baomidou.mybatisplus.generator.config.StrategyConfig;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import org.junit.platform.commons.util.StringUtils;import java.util.ArrayList;
import java.util.Scanner;public class CodeGenerator {public static String scanner(String tip) {Scanner scanner = new Scanner(System.in);StringBuilder help = new StringBuilder();help.append("请输入" + tip + ":");System.out.println(help.toString());if (scanner.hasNext()) {String ipt = scanner.next();if (StringUtils.isNotBlank(ipt)) {return ipt;}}throw new MybatisPlusException("请输入正确的" + tip + "!");}public static void main(String[] args) {// 代码生成器AutoGenerator mpg = new AutoGenerator();// 全局配置GlobalConfig gc = new GlobalConfig();String projectPath = System.getProperty("user.dir");gc.setOutputDir(projectPath + "/src/main/java");//设置代码生成路径gc.setFileOverride(true);//是否覆盖以前文件gc.setOpen(false);//是否打开生成目录gc.setAuthor("yixin");//设置项目作者名称gc.setIdType(IdType.AUTO);//设置主键策略gc.setBaseResultMap(true);//生成基本ResultMapgc.setBaseColumnList(true);//生成基本ColumnListgc.setServiceName("%sService");//去掉服务默认前缀gc.setDateType(DateType.ONLY_DATE);//设置时间类型mpg.setGlobalConfig(gc);// 数据源配置DataSourceConfig dsc = new DataSourceConfig();dsc.setUrl("jdbc:mysql://localhost:3306/mybatis_plus_db?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8");dsc.setDriverName("com.mysql.cj.jdbc.Driver");dsc.setUsername("root");dsc.setPassword("123456");mpg.setDataSource(dsc);// 包配置PackageConfig pc = new PackageConfig();pc.setParent("com.yixin");pc.setMapper("mapper");pc.setXml("mapper.xml");pc.setEntity("pojo");pc.setService("service");pc.setServiceImpl("service.impl");pc.setController("controller");mpg.setPackageInfo(pc);// 策略配置StrategyConfig sc = new StrategyConfig();sc.setNaming(NamingStrategy.underline_to_camel);sc.setColumnNaming(NamingStrategy.underline_to_camel);sc.setEntityLombokModel(true);//自动lomboksc.setRestControllerStyle(true);sc.setControllerMappingHyphenStyle(true);sc.setLogicDeleteFieldName("deleted");//设置逻辑删除//设置自动填充配置TableFill gmt_create = new TableFill("create_time", FieldFill.INSERT);TableFill gmt_modified = new TableFill("update_time", FieldFill.INSERT_UPDATE);ArrayList<TableFill> tableFills=new ArrayList<>();tableFills.add(gmt_create);tableFills.add(gmt_modified);sc.setTableFillList(tableFills);//乐观锁sc.setVersionFieldName("version");sc.setRestControllerStyle(true);//驼峰命名//  sc.setTablePrefix("tbl_"); 设置表名前缀sc.setInclude(scanner("表名,多个英文逗号分割").split(","));mpg.setStrategy(sc);// 生成代码mpg.execute();}}
  1. 测试看看

    其他参数可以参考官网进行配置,新版本做了很多更新。

总结

这里是看了狂神说的mybatis plus的入门教程,但是看了官网最新的mybatis plus貌似改了蛮多东西的,有机会多看看官网教程。

Mybatis 特别篇 Mybatis-plus入门教程相关推荐

  1. Mybatis generator 1.4.x 入门教程--转载

    Mybatis generator 1.4.x 入门教程 一.前言 ​ 最近因为公司开了新的项目,所以在构建骨架的时候发现mybatis最新的版本已经更新到了1.4.0了,尝试了一下,比起之前的myb ...

  2. 很特别的一个动态规划入门教程

    很特别的一个动态规划入门教程 今天在网上看到一个讲动态规划的文章,是以01背包为例的,这文章和书上的讲解非常不一样,令我眼前一亮,于是转载一下下--- (说明一下,本人非常痛恨教材公式定理漫天飞,实际 ...

  3. style 字体加粗_第9篇 Qt Quick入门教程之基础(九)文本显示和字体

    导语 文本显示是界面开发必不可少的内容,在Qt Quick模块中提供了 Text 项目来进行文本的显示,其中可以使用 font 属性组对文本字体进行设置.这一篇我们来看看它们的具体使用. 使用字体 就 ...

  4. php入门公开课,【PHP公开课|送你一篇有关laravel入门教程的php菜鸟笔记】- 环球网校...

    [摘要]PHP作为一种超文本预处理器,已经成为了我们常用的网站编程语言,并且结合了C语言,Java等我们常见的编程语言,所以,有很多web开发领域的新人都看中了他的使用广泛性,有很多人都想了解php的 ...

  5. python入门教程收藏_特别详细的Python入门教程,建议收藏

    Python是一种简单易学,功能强大的编程语言,它有高效率的高层数据结构,简单而有效地实现面向对象编程.Python简洁的语法和对动态输入的支持,再加上解释性语言的本质,使得它在大多数编程语言的使用场 ...

  6. Linux Capabilities 入门教程--进阶实战篇

    该系列文章总共分为三篇: Linux Capabilities 入门教程:概念篇 Linux Capabilities 入门教程:基础实战篇 Linux Capabilities 入门教程:进阶实战篇 ...

  7. Linux Capabilities 入门教程--基础实战篇

    该系列文章总共分为三篇: Linux Capabilities 入门教程:概念篇 Linux Capabilities 入门教程:基础实战篇 Linux Capabilities 入门教程:进阶实战篇 ...

  8. Linux Capabilities 入门教程--概念篇

    该系列文章总共分为三篇: Linux Capabilities 入门教程:概念篇 Linux Capabilities 入门教程:基础实战篇 Linux Capabilities 入门教程:进阶实战篇 ...

  9. 专为设计师而写的GitHub快速入门教程

    在互联网行业工作的想必都多多少少听说过GitHub的大名,除了是最大的开源项目托管平台,许多企业也都是用GitHub来协同开发工作,当然我们彩程也是其中之一.笔者最初决定学习Git也是因为在团队内部设 ...

最新文章

  1. python电脑软件下载-Python for windows
  2. 【计算机网络】网络安全 : 实体鉴别 ( 实体鉴别过程 | 不重数机制 | 公钥体质加密不重数 | 中间人攻击 )
  3. G - 变形课 HDU - 1181(搜索之dfs)
  4. 对Linux命令od -tc -tx1的C语言程序实现myod-优化版
  5. VS2012下载和安装
  6. 4个老司机常用的黑科技资源网站
  7. openstack私有云搭建
  8. 爬虫项目七:Python对唯品会商品数据、评论数据的爬取
  9. 电脑突然复制粘贴不了
  10. 求整型和浮点型绝对值的方法
  11. 用wireshark抓包分析TCP协议的三次握手连接、四次握手断开
  12. 垃圾回收只知道标记清除?一文帮你打通V8垃圾回收
  13. 关于导数非常的好文章
  14. (转载)你好,C++(6)2.3 C++兵器谱
  15. Android自定义View之数字密码锁
  16. win系统快捷键大全
  17. “空中交巡警”+智能信号灯 渝中智慧城市建设焕发新活力
  18. qt制作c语言万年历,基于QT实现的日历程序
  19. Non-Salient Region Object Mining for Weakly Supervised Semantic Segmentation
  20. iPhone开发者必读:苹果iOS 6固件重点

热门文章

  1. Java模拟操作系统实验一:四种进程调度算法实现(FCFS,SJF,RR,HRN)
  2. PS精选模块之移动工具的6种分布详解(默认针对于选区)
  3. Anaconda:The environment is inconsistent, please check the package plan carefully问题的解决办法
  4. linux下JAVA IDE安装汇总
  5. 转载:电线电缆的横截面积与载流量的关系
  6. 对接某个免签支付接口的过程 (跨域问题的解决)
  7. 我在Salira的800天(2009.5.20~2011.7.29)-三.研究与学习篇
  8. 微信小程序 radio-group(排列) 及事件绑定、点击切换样式
  9. 蓝牙模块--OTA升级
  10. Forever at your feet---Oh Susanna[静静地聆听雨声!]