Spring for MongoDB
常见数据库分类
Classification | Name |
---|---|
Key-Value | Redis、Memcached |
Document | MongoDB、CouchDB |
Columnar | HBase、Cassandra |
Graph | Neo4J |
Docker 部署 MongoDB
1# 拉取image
2[root@master ~]# docker pull mongo
3[root@master ~]# docker images | grep mongo
4mongo latest a0e2e64ac939 3 weeks ago 64MB
5
6# 创建本地挂载目录
7[root@master ~]# mkdir /data/mongodb -pv
8
9# 创建容器
10[root@master ~]# docker run --name mongo -v /data/mongod:/data/db -p 27017:27017 -e MONGO_INITDB_ROOT_USERNAME=admin -e MONGO_INITDB_ROOT_PASSWORD=123456 -d mongo
110503c6157ef3b7e7cea96be9d193567543cfb52698ca294f10bb45ac886ddb28
12
13# 登录到MongoDB容器中
14[root@master ~]# docker exec -it mongo bash
15
16# 通过 Shell 连接 MongoDB
17root@752473287d58:/# mongo -u admin -p 123456
18---
19>
Spring 对 MongoDB 的支持
Spring Data 的目标就是在不失各个数据库特性的基础上增加一层相对统一的封装和抽象。
通过 Spring Data MongoDB 项目。也提供了和 JdbcTemplate 类似的 MongoTemplate,通过 MongoTemplate 对数据进行 CRUD。同时 Spring Data MongoDB 也提供了像 JPA Repository 这样的 Repository 的支持。
注解
- @Document:作用类似于 @Entity
- @Id:文档的 Id
MongoTemplate
- save / remove
- Update / Query / Criteria
MongoTemplate
初始化 MongoDB 的库及权限
1# 创建库
2use springbucks;
3
4# 创建用户
5db.createUser(
6 {
7 user: "springbucks",
8 pwd: "springbucks",
9 roles: [
10 { role: "readWrite", db: "springbucks" }
11 ]
12 }
13)
引入依赖
1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.1.2.RELEASE</version>
9 <relativePath/> <!-- lookup parent from repository -->
10 </parent>
11 <groupId>geektime.spring.data</groupId>
12 <artifactId>mongo-demo</artifactId>
13 <version>0.0.1-SNAPSHOT</version>
14 <name>mongo-demo</name>
15 <description>Demo project for Spring Boot</description>
16
17 <properties>
18 <java.version>1.8</java.version>
19 </properties>
20
21 <dependencies>
22 <dependency>
23 <groupId>org.springframework.boot</groupId>
24 <artifactId>spring-boot-starter-data-mongodb</artifactId>
25 </dependency>
26
27 <dependency>
28 <groupId>org.joda</groupId>
29 <artifactId>joda-money</artifactId>
30 <version>RELEASE</version>
31 </dependency>
32
33 <dependency>
34 <groupId>org.projectlombok</groupId>
35 <artifactId>lombok</artifactId>
36 <optional>true</optional>
37 </dependency>
38 <dependency>
39 <groupId>org.springframework.boot</groupId>
40 <artifactId>spring-boot-starter-test</artifactId>
41 <scope>test</scope>
42 </dependency>
43 </dependencies>
44
45 <build>
46 <plugins>
47 <plugin>
48 <groupId>org.springframework.boot</groupId>
49 <artifactId>spring-boot-maven-plugin</artifactId>
50 </plugin>
51 </plugins>
52 </build>
53</project>
application.properties
1spring.data.mongodb.uri=mongodb://springbucks:springbucks@192.168.31.201:27017/springbucks
2spring.data.mongodb.username=admin
3spring.data.mongodb.password=123456
Coffee 实体类
1package geektime.spring.data.mongodemo.model;
2
3import lombok.AllArgsConstructor;
4import lombok.Builder;
5import lombok.Data;
6import lombok.NoArgsConstructor;
7import org.joda.money.Money;
8import org.springframework.data.annotation.Id;
9import org.springframework.data.mongodb.core.mapping.Document;
10
11import java.util.Date;
12
13@Document //表明和 Coffee collection是对应的
14@Data
15@NoArgsConstructor
16@AllArgsConstructor
17@Builder
18public class Coffee {
19 @Id //会自动转换成MongoDB中的object id org.springframework.data.annotation.Id;
20 private String id;
21 private String name;
22 private Money price;
23 private Date createTime;
24 private Date updateTime;
25}
26
MoneyReadConverter 类型转换处理类
1package geektime.spring.data.mongodemo.converter;
2
3import org.bson.Document;
4import org.joda.money.CurrencyUnit;
5import org.joda.money.Money;
6import org.springframework.core.convert.converter.Converter;
7
8public class MoneyReadConverter implements Converter<Document, Money> {
9 /**
10 * 类型转换:用于处理 Document => Money
11 * @param source
12 * @return
13 */
14 @Override
15 public Money convert(Document source) {
16 Document money = (Document) source.get("money");
17 double amount = Double.parseDouble(money.getString("amount"));
18 String currency = ((Document) money.get("currency")).getString("code");
19 return Money.of(CurrencyUnit.of(currency), amount);
20 }
21}
启动类
1package geektime.spring.data.mongodemo;
2
3import com.mongodb.client.result.UpdateResult;
4import geektime.spring.data.mongodemo.converter.MoneyReadConverter;
5import geektime.spring.data.mongodemo.model.Coffee;
6import lombok.extern.slf4j.Slf4j;
7import org.joda.money.CurrencyUnit;
8import org.joda.money.Money;
9import org.springframework.beans.factory.annotation.Autowired;
10import org.springframework.boot.ApplicationArguments;
11import org.springframework.boot.ApplicationRunner;
12import org.springframework.boot.SpringApplication;
13import org.springframework.boot.autoconfigure.SpringBootApplication;
14import org.springframework.context.annotation.Bean;
15import org.springframework.data.mongodb.core.MongoTemplate;
16import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
17import org.springframework.data.mongodb.core.query.Criteria;
18import org.springframework.data.mongodb.core.query.Query;
19import org.springframework.data.mongodb.core.query.Update;
20
21import java.util.Arrays;
22import java.util.Date;
23import java.util.List;
24
25import static org.springframework.data.mongodb.core.query.Criteria.where;
26import static org.springframework.data.mongodb.core.query.Query.query;
27
28@SpringBootApplication
29@Slf4j
30public class MongoDemoApplication implements ApplicationRunner {
31 @Autowired
32 private MongoTemplate mongoTemplate;
33
34 public static void main(String[] args) {
35 SpringApplication.run(MongoDemoApplication.class, args);
36 }
37
38 /**
39 * 注入 MongoCustomConversions 用于类型转换
40 * @return
41 */
42 @Bean
43 public MongoCustomConversions mongoCustomConversions() {
44 return new MongoCustomConversions(Arrays.asList(new MoneyReadConverter()));
45 }
46
47 @Override
48 public void run(ApplicationArguments args) throws Exception {
49 //save : espresso
50 Coffee espresso = Coffee.builder()
51 .name("espresso")
52 .price(Money.of(CurrencyUnit.of("CNY"), 20.0))
53 .createTime(new Date())
54 .updateTime(new Date()).build();
55 Coffee saved = mongoTemplate.save(espresso);
56 log.info("Coffee {}", saved);
57 //Coffee Coffee(id=5e1c1985a99c044c4825a017, name=espresso, price=CNY 20.00, createTime=Mon Jan 13 15:17:25 CST 2020, updateTime=Mon Jan 13 15:17:25 CST 2020)
58
59 //Query
60 List<Coffee> list = mongoTemplate.find(
61 Query.query(Criteria.where("name").is("espresso")), Coffee.class);
62 log.info("Find {} Coffee", list.size());
63 //Find 1 Coffee
64 list.forEach(c -> log.info("Coffee {}", c));
65 //Coffee Coffee(id=5e1c1985a99c044c4825a017, name=espresso, price=CNY 20.00, createTime=Mon Jan 13 15:17:25 CST 2020, updateTime=Mon Jan 13 15:17:25 CST 2020)
66
67
68 //update
69 Thread.sleep(1000); // 为了看更新时间
70 UpdateResult result = mongoTemplate.updateFirst(query(where("name").is("espresso")),
71 new Update().set("price", Money.ofMajor(CurrencyUnit.of("CNY"), 30))
72 .currentDate("updateTime"),
73 Coffee.class);
74 log.info("Update Result: {}", result.getModifiedCount());
75 //Update Result: 1
76
77 //findById
78 Coffee updateOne = mongoTemplate.findById(saved.getId(), Coffee.class);
79 log.info("Update Result: {}", updateOne);
80 //Update Result: Coffee(id=5e1c214ba99c04325c0ae2b4, name=espresso, price=CNY 30.00, createTime=Mon Jan 13 15:50:35 CST 2020, updateTime=Mon Jan 13 15:50:37 CST 2020)
81
82 //remove
83 mongoTemplate.remove(updateOne);
84 }
85}
登录容器中查看保存的文档信息
1> use springbucks
2switched to db springbucks
3> show collections;
4coffee
5> db.coffee.find();
6{ "_id" : ObjectId("5e1c1985a99c044c4825a017"), "name" : "espresso", "price" : { "money" : { "currency" : { "code" : "CNY", "numericCode" : 156, "decimalPlaces" : 2 }, "amount" : "20.00" } }, "createTime" : ISODate("2020-01-13T07:17:25.919Z"), "updateTime" : ISODate("2020-01-13T07:17:25.919Z"), "_class" : "geektime.spring.data.mongodemo.model.Coffee" }
7
8//删除espresso
9> db.coffee.remove({"name":"espresso"});
10WriteResult({ "nRemoved" : 1 })
11> db.coffee.find();
MongoRepository
@EnableMongoRepositories
对应接⼝
- MongoRepository<T, ID>
- PagingAndSortingRepository<T, ID>
- CrudRepository<T, ID>
引入依赖
1<?xml version="1.0" encoding="UTF-8"?>
2<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4 <modelVersion>4.0.0</modelVersion>
5 <parent>
6 <groupId>org.springframework.boot</groupId>
7 <artifactId>spring-boot-starter-parent</artifactId>
8 <version>2.1.2.RELEASE</version>
9 <relativePath/> <!-- lookup parent from repository -->
10 </parent>
11 <groupId>geektime.spring.data</groupId>
12 <artifactId>mongo-repository-demo</artifactId>
13 <version>0.0.1-SNAPSHOT</version>
14 <name>mongo-repository-demo</name>
15 <description>Demo project for Spring Boot</description>
16
17 <properties>
18 <java.version>1.8</java.version>
19 </properties>
20
21 <dependencies>
22 <dependency>
23 <groupId>org.springframework.boot</groupId>
24 <artifactId>spring-boot-starter-data-mongodb</artifactId>
25 </dependency>
26
27 <dependency>
28 <groupId>org.joda</groupId>
29 <artifactId>joda-money</artifactId>
30 <version>RELEASE</version>
31 </dependency>
32 <dependency>
33 <groupId>org.projectlombok</groupId>
34 <artifactId>lombok</artifactId>
35 <optional>true</optional>
36 </dependency>
37 <dependency>
38 <groupId>org.springframework.boot</groupId>
39 <artifactId>spring-boot-starter-test</artifactId>
40 <scope>test</scope>
41 </dependency>
42 </dependencies>
43
44 <build>
45 <plugins>
46 <plugin>
47 <groupId>org.springframework.boot</groupId>
48 <artifactId>spring-boot-maven-plugin</artifactId>
49 </plugin>
50 </plugins>
51 </build>
52</project>
application.properties
1spring.data.mongodb.uri=mongodb://springbucks:springbucks@192.168.31.201:27017/springbucks
2spring.data.mongodb.username=admin
3spring.data.mongodb.password=123456
Coffee
1package geektime.spring.data.mongodemo.model;
2
3import lombok.AllArgsConstructor;
4import lombok.Builder;
5import lombok.Data;
6import lombok.NoArgsConstructor;
7import org.joda.money.Money;
8import org.springframework.data.annotation.Id;
9import org.springframework.data.mongodb.core.mapping.Document;
10
11import java.util.Date;
12
13@Document
14@Data
15@NoArgsConstructor
16@AllArgsConstructor
17@Builder
18public class Coffee {
19 @Id
20 private String id;
21 private String name;
22 private Money price;
23 private Date createTime;
24 private Date updateTime;
25}
MoneyReadConverter 类型转换处理类
1package geektime.spring.data.mongodemo.converter;
2
3import org.bson.Document;
4import org.joda.money.CurrencyUnit;
5import org.joda.money.Money;
6import org.springframework.core.convert.converter.Converter;
7import org.springframework.stereotype.Component;
8
9@Component
10public class MoneyReadConverter implements Converter<Document, Money> {
11 @Override
12 public Money convert(Document source) {
13 Document money = (Document) source.get("money");
14 double amount = Double.parseDouble(money.getString("amount"));
15 String currency = ((Document) money.get("currency")).getString("code");
16 return Money.of(CurrencyUnit.of(currency), amount);
17 }
18}
CoffeeRepository
1package geektime.spring.data.mongodemo.repository;
2
3import geektime.spring.data.mongodemo.model.Coffee;
4import org.springframework.data.mongodb.repository.MongoRepository;
5
6import java.util.List;
7
8public interface CoffeeRepository extends MongoRepository<Coffee, String> {
9 List<Coffee> findByName(String name);
10}
启动类
1package geektime.spring.data.mongodemo;
2
3import geektime.spring.data.mongodemo.converter.MoneyReadConverter;
4import geektime.spring.data.mongodemo.model.Coffee;
5import geektime.spring.data.mongodemo.repository.CoffeeRepository;
6import lombok.extern.slf4j.Slf4j;
7import org.joda.money.CurrencyUnit;
8import org.joda.money.Money;
9import org.springframework.beans.factory.annotation.Autowired;
10import org.springframework.boot.CommandLineRunner;
11import org.springframework.boot.SpringApplication;
12import org.springframework.boot.autoconfigure.SpringBootApplication;
13import org.springframework.context.annotation.Bean;
14import org.springframework.data.domain.Sort;
15import org.springframework.data.mongodb.core.convert.MongoCustomConversions;
16import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
17
18import java.util.Arrays;
19import java.util.Date;
20
21@Slf4j
22@SpringBootApplication
23@EnableMongoRepositories
24public class MongoRepositoryDemoApplication implements CommandLineRunner {
25 @Autowired
26 private CoffeeRepository coffeeRepository;
27
28 public static void main(String[] args) {
29 SpringApplication.run(MongoRepositoryDemoApplication.class, args);
30 }
31
32 @Bean
33 public MongoCustomConversions mongoCustomConversions() {
34 return new MongoCustomConversions(Arrays.asList(new MoneyReadConverter()));
35 }
36
37 @Override
38 public void run(String... args) throws Exception {
39 //init: espresso 、 latte
40 Coffee espresso = Coffee.builder()
41 .name("espresso")
42 .price(Money.of(CurrencyUnit.of("CNY"), 20.0))
43 .createTime(new Date())
44 .updateTime(new Date()).build();
45 Coffee latte = Coffee.builder()
46 .name("latte")
47 .price(Money.of(CurrencyUnit.of("CNY"), 30.0))
48 .createTime(new Date())
49 .updateTime(new Date()).build();
50 //insert
51 coffeeRepository.insert(Arrays.asList(espresso, latte));
52
53 //find
54 coffeeRepository.findAll(Sort.by("name"))
55 .forEach(c -> log.info("Saved Coffee {}", c));
56 //Saved Coffee Coffee(id=5e1c28b1a99c0451e446ac1d, name=espresso, price=CNY 20.00, createTime=Mon Jan 13 16:22:09 CST 2020, updateTime=Mon Jan 13 16:22:09 CST 2020)
57 //Saved Coffee Coffee(id=5e1c28b1a99c0451e446ac1e, name=latte, price=CNY 30.00, createTime=Mon Jan 13 16:22:09 CST 2020, updateTime=Mon Jan 13 16:22:09 CST 2020)
58
59 //update
60 Thread.sleep(1000);
61 latte.setPrice(Money.of(CurrencyUnit.of("CNY"), 35.0));
62 latte.setUpdateTime(new Date());
63 coffeeRepository.save(latte);
64 coffeeRepository.findByName("latte")
65 .forEach(c -> log.info("Coffee {}", c));
66 //Coffee Coffee(id=5e1c28b1a99c0451e446ac1e, name=latte, price=CNY 35.00, createTime=Mon Jan 13 16:22:09 CST 2020, updateTime=Mon Jan 13 16:22:10 CST 2020)
67
68 //delete
69 coffeeRepository.deleteAll();
70 }
71}