一文学会Spring JDBC 使用
Spring JDBC
1、JDBC
JDBC 就是 数据库开发 操作的 代名词,因为只要是现代商业项目的开发那么一定是离不开 数据库 的,不管你搞的是什么,只要是想使用动态的开发结构,那么一定就是 JDBC ,那么下面首先来回顾一下传统JDBC的使用。
JDBC有四种连接: 像JDBC-ODBC的连接已经确定不再使用了、主要采用的是 JDBC网络连接模式。
- 在JDBC的开发之中,一定要 配置相应数据库的驱动程序 后才可以使用,所以这就属于标准的做法,同时还有一点必须明确,不管未来出现了什么样的 Java数据库开发框架,那么核心的本质只有一点: JDBC,可是JDBC 标准里面所定义的 操作结构 是属于 较为底层 的操作形式,所以使用起来 非常的
繁琐
,因为几乎所有的数据库的项目都需要加载驱动、创建数据库连接、数据库的操作对象、关闭数据库
,只有中间的数据库的CRUD操作是有区别的,那么就需要考虑对JDBC进行封装了,那么这个时候就有了ORM组件(全称ORMapping
、对象关联映射,采用对象的形式实现JDBC的开发操作)。
从历史的发展上来讲,ORMapping组件出现较多:JDO、Entity Bean、Hibernate、IBatis、SpringJDBC、MyBatis、JPA标准,当然随着技术的发展与淘汰,基本上现在阶段剩下的ORM组件,常用的就是MyBatis(国内互联网公司)、JPA(国外机构),而SpringJDBC是属于JDBC的轻度包装组件(其他的组件都属于重度包装),所以使用
SpringJDBC
可以简化JDBC
传统开发里面繁琐的操作步骤。
添加依赖
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spring.version>5.3.21</spring.version>
<mysql.version>8.0.30</mysql.version>
</properties>
<dependencies>
<!--核心依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</dependency>
<!--spring-jdbc-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
</dependency>
<!--数据库依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--测试-->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.8.2</version>
</dependency>
<!--日志依赖-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!--日志依赖-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.25</version>
</dependency>
</dependencies>
log4j.properties 日志配置文件 (当启动程序,没有任何报错,但是没有信息打印时,需要配置日志)
#将等级为DEBUG的日志信息输出到console和file这两个目的地,console和file的定义在下面的代码
log4j.rootLogger=DEBUG,console,file
#控制台输出的相关设置
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.Threshold=DEBUG
log4j.appender.console.ImmediateFlush=true
log4j.appender.console.Target=System.err
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=[%-5p] %d(%r) --> [%t] %l: %m %x %n
#文件输出的相关设置
log4j.appender.file = org.apache.log4j.RollingFileAppender
log4j.appender.file.File=./log/logFile.log
log4j.appender.file.MaxFileSize=10mb
log4j.appender.file.Threshold=DEBUG
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=[%p][%d{yy-MM-dd}][%c]%m%n
#日志输出级别
log4j.logger.org.mybatis=DEBUG
log4j.logger.java.sql=DEBUG
log4j.logger.java.sql.Statement=DEBUG
log4j.logger.java.sql.ResultSet=DEBUG
log4j.logger.java.sql.PreparedStatement=DEBUG
2、使用
要想使用JDBC,配置数据源,是关键性的一步。
2.1、配置数据源:
2.1.1、注册数据源对像
创建数据源的配置类:(基于配置类的方式)
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import javax.sql.DataSource;
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
// 驱动数据源
DriverManagerDataSource dataSource = new DriverManagerDataSource();
// 加载驱动程序
dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/yootk");
dataSource.setUsername("root");
dataSource.setPassword("317311");
return dataSource;
}
}
创建数据源的配置类:(基于xml的方式)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<!--数据源的配置-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/yootk"/>
<property name="username" value="root"/>
<property name="password" value="317311"/>
</bean>
</beans>
2.1.2、测试:
import look.word.jdbc.config.DataSourceConfig;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import javax.sql.DataSource;
@ContextConfiguration(classes = DataSourceConfig.class) // 两者二选一即可
//@ContextConfiguration(locations ={"classpath:data-source.xml"})
@ExtendWith(SpringExtension.class)
public class TestDataSource {
// 日志工厂对象
private static final Logger LOGGER = LoggerFactory.getLogger(TestDataSource.class);
@Autowired
private DataSource dataSource;
@Test
public void testConnection() throws Exception{
LOGGER.info("【数据库连接对象】:{}",dataSource);
}
}
// 执行结果 输入数据源对象,说明连接成功
// [INFO ] 2022-09-14 12:18:59,307(386) --> [main] look.word.test.TestDataSource.testConnection(TestDataSource.java:29): 【数据库连接对象】:org.springframework.jdbc.datasource.DriverManagerDataSource@535779e4
但是基于这种连接操作的性能是非常一般的,请追随源代码,一探究竟。
然后找到我们的AbstractDriverBasedDataSource.getConnection()方法,进入getConnectionFromDriver()方法。
找到getConnectionFromDriver(),他是一个抽象方法,然后找到其子类,DriverManagerDataSource
然后又会发现,我们回到了DriverManagerDataSource,然后我们在进入getConnectionFromDriverManager方法。
最终获取连接的方式,
2.1.3、默认连接方式的缺点
这种连接的管理方式,是在每一次 获取连接 的时候 才进行 数据库连接的操作了,那么现在的问题就来了,这样的管理方式好吗 ?首先在数据库连接的处理之中,一定会建立若干个Socket 连接,那么会有耗时,而在数据库关闭的时候也会存在有同样的耗时处理,这样在“次次次高并发”的处理下很难得到有效的控制。所以在实际项目中最佳数据库连接的管理,一定是基于数据库连接池方式实现的。所以此时可以考虑在 Spring 内部去实现一个连接池的维护。早期的数据库连接池组件提供有一个 C3P0组件,但是现在已经停止维护了。
2.2、HikariCP
在实际的项目应用开发过程之中,为了解决JDBC连接与关闭的延时以及性能问题,提供了数据库连接池的解决方案,并且针对于该方案提供了成型的HikariCP服务组件。HikariCP (Hikari来自日文,是“光”的含义)是由日本程序员开源的一个数据库连接池组件,该组件拥有如下特点:
- 宇节码更加的精简,这样可以在缓存中添加更多的程序代码;
- 实现了一个无锁集合,减少了并发访问造成的资源竞争问题;
- 使用了自定义数组类型(FastList)代替了ArrayList,提高了get()与remove()的操作性能;
- 针对CPU的时间片算法进行了优化,尽可能在一个时间片内完成所有处理操作。
在Spring之中默认推荐的数据库连接池组件就是HikariCP,不建议再使用其他的数据库连接池组件,当然国内也有优秀的CP组件,那么就是阿里推出的Druid(在性能上可能低于HikariCP,但是提供有完整的管理界面),如果要想使用这个组件,可以采用如下的步骤进行配置。
2.2.1、使用
添加依赖:
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version>
</dependency>
编写配置类:
这次我们再用配置文件的方式,方便扩展
- 创建配置文件:src/main/profiles/dev/config/database.properties
yootk.database.driverClassName=com.mysql.cj.jdbc.Driver
yootk.database.jdbcUrl=jdbc:mysql://localhost:3306/yootk
yootk.database.username=root
yootk.database.password=317311
# 【Hikaricp】配置数据库连接超时时间 单位【毫秒】
yootk.database.connectionTimeOut=3000
# 【Hikaricp】一个连接最小维持的时间 单位【毫秒】
yootk.database.idleTimeOut=3000
# 【Hikaricp】一个连接最长存活的时间 单位【毫秒】
yootk.database.maxLifetime=6000
# 【Hikaricp】最大保存的数据库连接实例
yootk.database.maximumPoolSize=60
# 【Hikaricp】最小保存的数据库连接实例 (在没有任何用户访问时,最少维持的连接数量)
yootk.database.minimumIdle=20
# 【Hikaricp】是否为只读
yootk.database.readOnly=false
创建配置对象
@Configuration
//读取指定位置的资源文件
@PropertySource("classpath:config/database.properties")
public class HikariCpDataSourceConfig {
/**
* 绑定资源文件中的配置数据项
*/
@Value("${yootk.database.driverClassName}")
private String driverClassName;
@Value("${yootk.database.jdbcUrl}")
private String jdbcUrl;
@Value("${yootk.database.username}")
private String username;
@Value("${yootk.database.password}")
private String password;
@Value("${yootk.database.connectionTimeOut}")
private Long connectionTimeOut;
@Value("${yootk.database.idleTimeOut}")
private Long idleTimeOut;
@Value("${yootk.database.maxLifetime}")
private Long maxLifetime;
@Value("${yootk.database.maximumPoolSize}")
private Integer maximumPoolSize;
@Value("${yootk.database.minimumIdle}")
private Integer minimumIdle;
@Value("${yootk.database.readOnly}")
private boolean readOnly;
@Bean("dataSource")
public DataSource dataSource() {
// Hikari连接池数据源
HikariDataSource dataSource = new HikariDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setJdbcUrl(jdbcUrl);
dataSource.setUsername(username);
dataSource.setPassword(password);
dataSource.setPassword(password);
// 超时时间
dataSource.setConnectionTimeout(connectionTimeOut);
// 空闲超时
dataSource.setIdleTimeout(idleTimeOut);
// 连接的最长时间
dataSource.setMaxLifetime(maxLifetime);
// 连接池最大数量
dataSource.setMaximumPoolSize(maximumPoolSize);
// 当没有连接时 最小保留的连接数量
dataSource.setMinimumIdle(minimumIdle);
// 是否只读数据库
dataSource.setReadOnly(readOnly);
return dataSource;
}
}
测试类:
import look.word.jdbc.config.HikariCpDataSourceConfig;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import javax.sql.DataSource;
@ContextConfiguration(classes = HikariCpDataSourceConfig.class)
@ExtendWith(SpringExtension.class)
public class TestDataSource {
private static final Logger LOGGER = LoggerFactory.getLogger(TestDataSource.class);
@Autowired
private DataSource dataSource;
@Test
public void testConnection() throws Exception {
LOGGER.info("【数据库连接对象】:{}", dataSource.getConnection());
}
}
如果出错,可以看看日志输入信息。
这样我们就实现了,使用HikariCP获取连接对象了,接下来就会使用HikariCP对具体的数据库进行操作。
2.3、JdbcTempLate
JdbcTempLate的使用很简单,只需要为其指定数据源即可。
我们采用配置类的方式,为其配置数据源
2.3.1、增
添加配置类:
@Configuration
public class JdbcTempLateConfig {
@Bean // 方法形参 会自动从容器中注入对象
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
return jdbcTemplate;
}
}
编写测试类:
@ContextConfiguration(classes = {HikariCpDataSourceConfig.class, JdbcTempLateConfig.class})
@ExtendWith(SpringExtension.class)
public class TestJdbcTempLate {
private static final Logger LOGGER = LoggerFactory.getLogger(TestJdbcTempLate.class);
@Autowired
private JdbcTemplate jdbcTemplate;
@Test
public void testConnection() throws Exception {
String sql = "insert into book(title,author,price) values('java入门','李老师',99.90)";
LOGGER.info("【插入执行结果】:{}", jdbcTemplate.update(sql));
}
}
执行结果:
这个时候就是用JdbcTemplate轻松地实现了数据的插入操作。
但是,可以发现,我们上面的操作,还是存在问题的,比如没有对sql 进行预处理,会出现 Sql 注入的风险。
2.3.2、改
测试类
@Test
public void testUpdate() {
String sql = "update yootk.book set title = ? where bid = ?";
LOGGER.info("【插入执行结果】:{}", jdbcTemplate.update(sql, "Python入门", 2));
}
2.3.3、删
测试类
@Test
public void testDelete() {
String sql = "delete from yootk.book where bid = ?";
LOGGER.info("【插入执行结果】:{}", jdbcTemplate.update(sql, 2));
}
2.3.4、增 (返回id)
在MySQL数据库里面,有一种功能,可以通过一个next()处理函数获取当前所生成的ID号(主要针对于自动增长列),实际上这个功能主要的目的是为了解决增加数据时的ID返回处理问题了,因为很多的时候需要在数据增加成功之后对指定的ID进行控制,所以才提供了专属的处理函数,Oracle之中直接使用序列即可,但是MySQL的实现就需要专属的处理函数了。.在程序的开发之中,如果要想获取到增长后的ID数据,在SpringJDBC里面提供有了一个KeyHolder接口,在这个接口里面定义了获取主键内容的处理方法。
在平常开发中,我们经常会遇到,插入这个数据后,会需要这个数据的id,然后对其进行一系类操作。
如果要想获取到增长后的ID数据,在SpringJDBC里面提供有了一个KeyHolder接口,在这个接口里面定义了获取主键内容的处理方法。
测试类
@Test
public void testInsertReturnId() {
String sql = "insert into yootk.book(title,author,price) values(?,?,?)";
GeneratedKeyHolder keyHolder = new GeneratedKeyHolder(); // 获取KEY的处理信息
int count = jdbcTemplate.update(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); // 对sql进行预处理
ps.setString(1, "Springboot实战");
ps.setString(2, "老李");
ps.setDouble(3, 99.00);
return ps;
}
}, keyHolder);
LOGGER.info("【插入执行影响行数】:{},当前插入数据的ID:{}", count, keyHolder.getKey());
}
// 执行结果
// look.word.test.TestJdbcTempLate.testInsertReturnId(TestJdbcTempLate.java:61): 【插入执行影响行数】:1,当前插入数据的ID:4
如果在
PreparedStatement ps = con.prepareStatement(sql);
中,没有指定需要返回KEY,则会出现异常。
2.3.5、批处理
测试类:
这种方式是基于集合的。
@Test
public void testInsertBatch() {
List<String> titles = List.of("Springboot开发实战", "SSM开发案例", "Netty开发实战", "Redis开发实战");
List<Double> prices = List.of(90.1, 98.9, 78.9, 98.9);
String sql = "insert into yootk.book(title,author,price) values(?,?,?)";
this.jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter() { // 执行批量插入
//@param i 集合索引
@Override
public void setValues(PreparedStatement ps, int i) throws SQLException {
ps.setString(1, titles.get(i));
ps.setString(2, "老李老师");
ps.setDouble(3, prices.get(i));
}
@Override
public int getBatchSize() {
return titles.size(); //总长度
}
});
}
基于对象
@Test
public void testInsertBatch2() {
List<Object[]> params = List.of(
new Object[]{"Spring开发实战", "11", 89.0},
new Object[]{"Spring开发实战1", "11", 89.0},
new Object[]{"Spring开发实战2", "11", 89.0},
new Object[]{"Spring开发实战3", "11", 89.0}
);
String sql = "insert into yootk.book(title,author,price) values(?,?,?)";
int[] result = jdbcTemplate.batchUpdate(sql, params);//批量插入
System.out.println("result = " + result);
}
2.3.4、查
在数据库操作过程中,除了数据更新操作之外,最为繁琐的就是数据库的查询功能了。由于JdbcTemplate设计的定位属于ORMapping组件,所以就需要在查询完成之后,可以自动的将查询结果转为VO类型的实例,而为了解决该问题,在SpringJDBC中提供了一个RowMapper接口,这个接口可以实现ResultSet向指定对象实例的转换。该接口提供有一个mapRow()处理方法,可以接收查询结果每行数据的结果集,用户可以将指定列取出,并保存在自标VO实例之中
查询单个
Book 对象 根据数据库创建
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Book {
private Integer bid;
private String title;
private String author;
private Double price;
}
测试类:
// 查询单个
@Test
public void testQuery() {
String sql = "select bid, title, author, price from yootk.book where bid = ?";
Book book = jdbcTemplate.queryForObject(sql, new RowMapper<Book>() {
@Override
public Book mapRow(ResultSet rs, int rowNum) throws SQLException {
Book book = new Book();
book.setBid(rs.getInt(1));
book.setTitle(rs.getString(2));
book.setAuthor(rs.getString(3));
book.setPrice(rs.getDouble(4));
return book;
}
}, 3); // 这里的3 是对预处理数据的回填 多个需按照顺序编写
System.out.println("【queryForObject 查询结果】book = " + book);
}
查询多个
// 查询所有
@Test
public void testQueryAll() {
String sql = "select bid, title, author, price from yootk.book ";
List<Book> list = jdbcTemplate.query(sql, new RowMapper<Book>() {
@Override
public Book mapRow(ResultSet rs, int rowNum) throws SQLException {
Book book = new Book();
book.setBid(rs.getInt(1));
book.setTitle(rs.getString(2));
book.setAuthor(rs.getString(3));
book.setPrice(rs.getDouble(4));
return book;
}
});
list.stream().forEach(System.out::println);
}
分页查询
// 分页
@Test
public void testQuerySpAll() {
int current = 2; // 页数
int size = 5;// 每页数量
String sql = "select bid, title, author, price from yootk.book limit ? ,? ";
List<Book> list = jdbcTemplate.query(sql, new RowMapper<Book>() {
@Override
public Book mapRow(ResultSet rs, int rowNum) throws SQLException {
Book book = new Book();
book.setBid(rs.getInt(1));
book.setTitle(rs.getString(2));
book.setAuthor(rs.getString(3));
book.setPrice(rs.getDouble(4));
return book;
}
}, (current - 1) * size, size);
list.stream().forEach(System.out::println);
}
统计行数
// 查询行数
@Test
public void testQueryCount() {
String sql = "select count(*) from yootk.book where title like ?";
long count = jdbcTemplate.queryForObject(sql, new RowMapper<Long>() {
@Override
public Long mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getLong(1);
}
}, "%Spring%");
LOGGER.info("【数据库记录总行数】{}", count);
}
一文学会Spring JDBC 使用的更多相关文章
- Spring JDBC概述
1.jdbc 概述 Spring JDBC是Spring框架的持久层子框架.用于对数据库的操作(增删改查). 而JdbcTemplate它是spring jdbc子框架中提供的一个操作类,用于对原始J ...
- Spring JDBC模板类—org.springframework.jdbc.core.JdbcTemplate(转)
今天看了下Spring的源码——关于JDBC的"薄"封装,Spring 用一个Spring JDBC模板类来封装了繁琐的JDBC操作.下面仔细讲解一下Spring JDBC框架. ...
- 4-9 基于Spring JDBC的事务管理(续)
10. 基于Spring JDBC的事务管理(续) 当需要方法是事务性的,可以使用@Transactional注解,此注解可以添加在: 接口 会使得此接口的实现类的所有实现方法都是事务性的 接口中的抽 ...
- spring jdbc 查询结果返回对象、对象列表
首先,需要了解spring jdbc查询时,有三种回调方式来处理查询的结果集.可以参考 使用spring的JdbcTemplate进行查询的三种回调方式的比较,写得还不错. 1.返回对象(queryF ...
- spring jdbc获取插入记录的主键id
在JDBC3.0规范中,当新增记录时,允许将数据库自动产生的主键值绑定到Statement或PreparedStatement中.使用Statement时,可以通过以下方法绑定主键值: int exe ...
- Spring JDBC实现查询
1 db.properties jdbc.user=root jdbc.password=920614 jdbc.driverClass=com.mysql.jdbc.Driver jdbc.jdbc ...
- Spring JDBC
转载:博客主页:http://blog.csdn.NET/chszs 一.概述 在Spring JDBC模块中,所有的类可以被分到四个单独的包:1)core即核心包,它包含了JDBC的核心功能.此包内 ...
- Spring学习进阶(四) Spring JDBC
Spring JDBC是Spring所提供的持久层技术.主要目的是降低使用JDBC API的门槛,以一种更直接,更简洁的方式使用JDBC API.在Spring JDBC里用户仅需要做哪些比不可少的事 ...
- Spring JDBC常用方法详细示例
Spring JDBC使用简单,代码简洁明了,非常适合快速开发的小型项目.下面对开发中常用的增删改查等方法逐一示例说明使用方法 1 环境准备 启动MySQL, 创建一个名为test的数据库 创建Mav ...
随机推荐
- NC23046 华华教月月做数学
NC23046 华华教月月做数学 题目 题目描述 找到了心仪的小姐姐月月后,华华很高兴的和她聊着天.然而月月的作业很多,不能继续陪华华聊天了.华华为了尽快和月月继续聊天,就提出帮她做一部分作业. 月月 ...
- 从零开始实现lmax-Disruptor队列(五)Disruptor DSL风格API原理解析
MyDisruptor V5版本介绍 在v4版本的MyDisruptor实现多线程生产者后.按照计划,v5版本的MyDisruptor需要支持更便于用户使用的DSL风格的API. 由于该文属于系列博客 ...
- GIS技术在医疗行业的应用:利用切片地图发布技术解决dmetrix数字病理切片在线浏览
最近一直在研究切片地图发布技术,解决各种矢量和栅格数据的切片地图制作和发布问题.这块的技术在土地评估和调查类公司中应用较多,因为他们经常需要使用各地地图,传统的文件管理方式很难适应工作现状,如果将各种 ...
- ROS机械臂 Movelt 学习笔记3 | kinect360相机(v1)相关配置
目标是做一个机械臂视觉抓取的demo,在基地里翻箱倒柜,没有找到学长所说的 d435,倒是找到了一个老古董 kinect 360. 前几天就已经在旧电脑上配置好了,现在记录在新电脑上的配置过程. 1. ...
- python 面向对象理解
简介 与java语言一样,python也属于面向对象编程,除此之外,还有面向过程编程.函数式编程. 面向过程编程:依据业务逻辑自上而下一步一步编写, 可能会存在冗余现象 函数式编程:需要编程语言可以将 ...
- mysql玩法
如何字段名查找所在的表名 SELECT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = '字段名字' select sys ...
- CMake教程——Leeds_Garden
本系列适合 乐于学习新知识的人 想要深入学习C++的人 赞美作者的人 系列目录 初步入门 基本操作 (更新中) 创作不易,欢迎分享,把知识分享给更多有需要的人.
- SpringBoot定时任务 - 经典定时任务设计:时间轮(Timing Wheel)案例和原理
Timer和ScheduledExecutorService是JDK内置的定时任务方案,而业内还有一个经典的定时任务的设计叫时间轮(Timing Wheel), Netty内部基于时间轮实现了一个Ha ...
- Luogu4391 [BOI2009]Radio Transmission 无线传输 (KMP)
\(最小循环节\) \(=\) \(lenghth - next[lenghth]\) #include <iostream> #include <cstdio> #inclu ...
- SvelteUI:运用svelte3构建的网页版UI组件库(升级版)
距离上次分享的svelte-ui 1.0已经一月有余,这次带来全新升级完整版svelte-ui 2.0. 这次优化并新增15+个组件.在开发之初借鉴了element-ui组件库,所以在组件结构及语法上 ...