1. SQL解决方案
- 现有数据层解决方案技术选型
Druid + MyBatis-Plus + MySQL
♦数据源:DruidDataSource
♦持久化技术:MyBatis-Plus / MyBatis
♦数据库: MySQL
1.1 数据源配置格式
- 格式一
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
username: root
password: root
type: com.alibaba.druid.pool.DruidDataSource
- 格式二
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
username: root
password: root
- SpringBoot提供了3种内嵌的数据源对象供开发者选择
♦ HikariCP:默认内置数据源对象
♦ Tomcat提供DataSource:HikariCP不可用的情况下,且在web环境中,将使用Tomcat服务器配置的数据源对象
♦ Commons DBCP:HikarI不可用,tomcat数据源也不用,将使用dbcp数据源
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
username: root
password: root
- 通用配置无法设置具体的数据源配置信息,仅提供基本的连接相关配置,如需配置,在下一级配置中设置具体设定
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/ssm_db?serverTimezone=UTC
username: root
password: root
hikari:
maximum-pool-size: 50
1.2 内置持久化解决方案——JdbcTemplate**
使用JdbcTemplate需要导入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
代码
@Test
void test() {
String sql = "select * from tbl_book where id = 1";
List<Book> qurey = jdbcTemplate.query(sql, new RowMapper<Book>() {
@Override
public Book mapRow(ResultSet rs, int rowNum) throws SQLException {
Book temp = new Book();
temp.setId(rs.getInt("id"));
temp.setName(rs.getString("name"));
temp.setType(rs.getString("type"));
temp.setDescription(rs.getString("description"));
return temp;
}
});
System.out.println(qurey);
}
配置
spring:
jdbc:
template:
query-timeout: -1 #查询超时时间
max-rows: 500 #最大行数
fetch-size: -1 #批处理数量
1.3 内嵌数据库
- SpringBoot提供了3种内嵌数据库供开发者选择,提高开发测试效率
♦ H2
♦ HSQL
♦ Derby - 设置当前项目为web工程,并配置H2管理控制台参数
server:
port: 80
spring:
h2:
console:
enabled: true
path: /h2
♦ 访问用户名sa,默认密码123456
- 操作数据库(创建表)
create table tbl_book (id int,name varchar,type varchar,description varchar)
- 设置访问数据源
server:
port: 80
spring:
h2:
console:
enabled: true
path: /h2
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:~/test
username: sa
password: 123456
- H2数据库控制台仅用于开发阶段,线上项目请务必关闭控制台功能
server:
port: 80
spring:
h2:
console:
enabled: flase
path: /h2
- SpringBoot可以根据url地址自动识别数据库种类,在保障驱动类存在的情况下,可以省略配置
server:
port: 80
spring:
h2:
console:
enabled: true
path: /h2
datasource:
# driver-class-name: org.h2.Driver
url: jdbc:h2:~/test
username: sa
password: 123456
2. NoSQL解决方案
- 市面上常见的NoSQL解决方案
♦ Redis
♦ Mongo
♦ ES
2.1 Redis
- Redis是一款key-value存储结构的
内存级
NoSQL数据库
♦ 支持多种数据存储格式
♦ 支持持久化
♦ 支持集群
SpringBoot整合Redis
- 导入Redis对应的starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
- 配置Redis(采用默认配置)
spring:
redis:
host: localhost
port: 6379
♦ 主机:localhost(默认)
♦ 端口:6379(默认)
- RedisTemplate提供操作各种数据存储类型的接口API
♦ ops*:获取各种数据类型操作接口
客户端:RedisTemplate以对象作为key和value,内部对数据进行序列化
@SpringBootTest
class Springboot16RedisApplicationTests {
@Test
void set(@Autowired RedisTemplate redisTemplate) {
ValueOperations ops = redisTemplate.opsForValue();
ops.set("age", 41);
}
@Test
void get(@Autowired RedisTemplate redisTemplate) {
ValueOperations ops = redisTemplate.opsForValue();
Object age = ops.get("age");
System.out.println(age);
}
@Test
void hset(@Autowired RedisTemplate redisTemplate) {
HashOperations hashOperations = redisTemplate.opsForHash();
hashOperations.put("info", "b", "bb");
}
@Test
void hget(@Autowired RedisTemplate redisTemplate) {
HashOperations hashOperations = redisTemplate.opsForHash();
Object val = hashOperations.get("info", "b");
System.out.println(val);
}
}
客户端:StringRedisTemplate以字符串作为key和value,与Redis客户端操作等效(常用)
@SpringBootTest
public class StringRedisTemplateTest {
@Test
void set(@Autowired StringRedisTemplate stringRedisTemplate) {
ValueOperations ops = stringRedisTemplate.opsForValue();
ops.set("testKey","testKey");
}
@Test
void get(@Autowired StringRedisTemplate stringRedisTemplate) {
ValueOperations<String, String> ops = stringRedisTemplate.opsForValue();
String name = ops.get("testKey");
System.out.println(name);
}
}
SpringBoot整合Redis客户端选择
客户端选择:jedis
导入依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
配置客户端:
spring:
redis:
host: localhost # 127.0.0.1
port: 6379
client-type: jedis
lettcus与jedis区别
- jedis连接Redis服务器是直连模式,当多线程模式下使用jedis
会存在线程安全问题,解决方案 可以通过配置连接池使每个连接专用,这样整体性能就大受影响。 - lettcus基于Netty框架进行与Redis服务器连接,底层设计中采用StatefulRedisConnection。StatefulRedisConnection自身是线程安全的,可以保障并发访问安全问题,所以一个连接可以被多线程复用。当然lettcus也支持多连接实例一起工作。(默认)
2.2 Mongodb
Mongodb基础CRUD
- Mongodb是一个开源、高性能、无模式的文档型数据库。NoSQL数据库产品中的一种,是最像关系型数据库的非关系型数据库
- 淘宝用户数据
♦ 存储位置:数据库
♦ 特征:永久性存储,修改频度极低
- 游戏装备数据、游戏道具数据
♦ 存储位置:数据库、Mongdb
♦ 特征:永久性存储与临时存储相结合、修改频度较高
- 直播数据、打赏数据、粉丝数据
♦ 存储位置:数据库、Mongdb
♦ 特征:永久性存储与临时存储相结合、修改频度较高
- 物联网数据
♦ 存储位置:Mongdb
♦ 特征:临时存储,修改频度飞速
新增
db.集合名称.insert/save/insertOne(文档)
修改
db.集合名称.remove(条件)
删除
db.集合名称.update(条件,{操作种类:{文档}})
查询
1.基础查询
♦ 查询全部:db.集合.find();
♦ 查第一条:db.集合.findOne();
♦ 查询指定数量文档:db.集合.find().limit(10) //查10条文档
♦ 跳过指定数量文档:db.集合.find().skip(20) //跳过20条文档
♦ 统计:db.集合.count()
♦ 排序:db.集合.sort({age:1}) //按age升序排序
♦ 投影:db.集合名称.find(条件,{name:1,age:1}) //仅保留name与age域
2.条件查询
♦ 基本格式:db.集合.find({条件})
♦ 模糊查询:db.集合.find({域名:/正则表达式/}) //等同SQL中的like,比like强大,可以执行正则所有规则
♦ 条件比较运算:db.集合.find({域名:{$gt:值}}) //等同SQL中的数值比较操作,例如:name>18
♦ 包含查询:db.集合.find({域名:{$in:[值1,值2]}}) //等同于SQL中的in
♦ 条件连接查询:db.集合.find({$and:[{条件1},{条件2}]}) //等同SQL中的and、or
SpringBoot整合Mongodb
- 导入Mongodb驱动
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
- 配置客户端
spring:
data:
mongodb:
uri: mongodb://localhost/itheima
- 客户端读写Mongodb
@SpringBootTest
class Springboot17MongodbApplicationTests {
@Autowired
private MongoTemplate mongoTemplate;
@Test
void contextLoads() {
Book book = new Book();
book.setId(2 );
book.setName("spring1");
book.setType("spring1");
book.setDescription("spring1");
mongoTemplate.save(book);
}
@Test
void find() {
List<Book> all = mongoTemplate.findAll(Book.class);
System.out.println(all);
}
}
2.3 Elasticsearch(ES)
- Elasticsearch是一个分布式全文搜索引擎
- Windows版本ES安装与启动
运行 elasticsearch.bat
运行失败修改bin目录下elasticsearch-env.bat的JDK路径
安装ik分词器解压到plugins目录下
Elasticsearch增删改查(文档操作)
- 创建/查询/删除索引
PUT http:/localhost:9200/books
GET http:/localhost:9200/books
DELETE http:/localhost:9200/books
- 使用索引并指定规则
{
"mappings" : {
"properties":{
"id":{
"type":"keyword"
},
"name":{
"type":"text",
"analyzer":"ik_max_word",
"copy_to":"all"
},
"type":{
"type":"keyword"
},
"description":{
"type":"text",
"analyzer":"ik_max_word" ,
"copy_to":"all"
},
"all":{
"type":"text",
"analyzer":"ik_max_word"
}
}
}
}
- 创建文档
POST http:/localhost:9200/books/_doc #使用系统生成的id
POST http:/localhost:9200/books/_create/1 #使用指定id
POST http:/localhost:9200/books/_doc/1 #使用指定id,不存在创建,存在更新(版本递增)
{
"name" : "springboot",
"type" : "springboot",
"description" : "springboot"
}
- 查询文档
GET http:/localhost:9200/books/_doc/1 #查询单个文档
GET http:/localhost:9200/books/_search #查询全部文档
- 条件查询
Get http:/localhost:9200/books/_search?q=name:springboot
- 删除文档
DELETE http:/localhost:9200/books/_doc/1
- 修改文档
PUT http:/localhost:9200/books/_doc/1
{
"name" : "springboot",
"type" : "springboot",
"description" : "springboot";
}
- 修改文档(部分修改)
PUT http:/localhost:9200/books/_update/1
{
"doc" : {
"name" : "springboot"
}
}
Spring整合Elasticsearch客户端(low)
- 导入坐标
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>spring-boot-start-data-elasticsearch</artifactId>
</dependency>
- 配置
spring:
elasticsearch:
=rest:
uris: http://localhost:9200
- 客户端
@SpringBootTest
class Springboot18EsApplicationTests{
@Autowired
private ElasticsearchRestTemplate template;
}
手动操作客户端初始化
- SpringBoot平台没有跟随ES的更新速度进行同步更新,ES提供了Hight Level Client操作ES
- 导入坐标
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
</dependency>
- 配置(无)
- 客户端
@Test
void testCreateClient() throws IOException {
HttpHost host = HttpHost.create("http://localhost:9200");
RestClientBuilder builder = RestClient.builder(host);
RestHighLevelClient = new RestHighLevelClient(builder);
//客户端操作
CreateIndexRequest request = new CreateIndexRequest("books");
//获取操作索引的客户端对象,调用创建索引操作
client.indices().create(request, RequestOptions.DEFAULT);
//关闭客户端
client.close();
}
- 客户端改进
@SpringBootTest
class Springboot18EsApplicationTests {
@Autowired
private BookDao bookDao;
@Autowired
RestHighLevelClient client;
@BeforeEach
void setUp() {
this.client = new RestHighLevelClient(RestClient.builder(HttpHost.create("http://localhost:9200")));
}
@AfterEach
void tearDown() throws IOException {
this.client.close();
}
}
Java代码实现
- 创建索引
@Test
void testCreateByIk() throws IOException {
HttpHost host = HttpHost.create("http://localhost:9200");
RestClientBuilder builder = RestClient.builder(host);
RestClientBuilder client = new RestHighLevelClient(builder);
//客户端操作
CreateIndexRequest request = new CreateIndexRequest("books");
//设置要执行的操作
String json = " ";
//设置请求中的参数,参数类型json数据
request.source(json, XContentType.JSON);
//获取操作索引的客户端对象,调用创建索引操作
client.indices().create(request, RequestOptions.DEFAULT);
//关闭客户端
client.close();
}
- 添加文档
@Test
//添加文档
void testCreateDoc() throws IOException {
Book book = bookDao.selectById(1);
IndexRequest request = new IndexRequest("books").id(book.getId().toString());
String json = JSON.toJSONString(book);
request.source(json, XContentType.JSON);
client.index(request, RequestOptions.DEFAULT);
}
- 批量添加文档
@Test
void testCreateDocAll() throws IOException {
List<Book> bookList = bookDao.selectList(null);
BulkRequest bulkRequest = new BulkRequest();
for (Book book : bookList) {
IndexRequest request = new IndexRequest("books").id(book.getId().toString());
String json = JSON.toJSONString(book);
request.source(json, XContentType.JSON);
bulkRequest.add(request);
}
client.bulk(bulkRequest, RequestOptions.DEFAULT);
}
- 按ID查
//按id查询
@Test
void testGet() throws IOException {
GetRequest request = new GetRequest("books", "1");
GetResponse response = client.get(request, RequestOptions.DEFAULT);
String json = response.getSourceAsString();
System.out.println(json);
}
- 按条件查
//按条件查询
@Test
void testSearch() throws IOException {
SearchRequest request = new SearchRequest("books");
SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.termQuery("name", "java"));
request.source(builder);
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
Book book = JSON.parseObject(sourceAsString, Book.class);
System.out.println(book);
}
}