SpringBoot 整合 MongoDB实战

SpringBoot 整合 MongoDB 实战开发

一、介绍
在前面的文章中,我们详细的介绍了 MongoDB 的配置和使用,如果你对 MongoDB 还不是很了解,也没关系,在 MongoDB 中有三个比较重要的名词:数据库、集合、文档!

数据库(Database):和关系型数据库一样,每个数据库中有自己的用户权限,不同的项目组可以使用不同的数据库
集合(Collection): 集合指的是文档组(类似于 Mysql 中的表的概念),里面可以存储许多文档
文档(Document): 文档是 MongoDB 中最基本的数据单元,由键值对组成,类似于 JSON 格式,可以存储不同字段,字段的值可以包括其他文档、数组和文档数组
二、常用註解
2.1 Collection
@Id
@Document
@Field
@Transient
釋義:
@Id
主键,不可重复,自带索引,可以在定义的列名上标注,需要自己生成并维护不重复的约束。如果自己不设置@Id主键,mongo会自动生成一个唯一主键,并且插入时效率远高于自己设置主键。原因可参考上一篇mongo和mysql的性能对比。
在实际业务中不建议自己设置主键,应交给mongo自己生成,自己可以设置一个业务id,如int型字段,用自己设置的业务id来维护相关联的表
@Document
标注在实体类上,类似于hibernate的entity注解,标明由mongo来维护该表。
org.springframework.data.mongodb.core.mapping.Document.class
把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档。
@Document(collection=“mongodb 对应 collection 名”)
// 若未加 @Document ,该 bean save 到 mongo 的 user collection
// 若添加 @Document ,则 save 到 thisUser collection

org.springframework.data.mongodb.core.mapping.Document.class
把一个java类声明为mongodb的文档,可以通过collection参数指定这个类对应的文档。
@Document(collection="mongodb 对应 collection 名")      
 
// 若未加 @Document ,该 bean save 到 mongo 的 user collection
// 若添加 @Document ,则 save 到 thUser collection
@Document(collection="thUser ") 
public class User{
}

@Field

代表一个字段,可以不加,不加的话默认以参数名为列名。

给映射存储到 mongodb 的字段取别名
在 java bean 中字段名为 firstName,存储到 mongo 中 key 为 fName

给映射存储到 mongodb 的字段取别名
在 java bean 中字段名为userName,存储到 mongo 中 key 为 uName
    @Field("uName")
private String userName;

@Transient
被该注解标注的,将不会被录入到数据库中。只作为普通的javaBean属性

三 、SpringBoot 整合 MongoDB
3.1、创建 SpringBoot 工程,添加 MongoDB 依赖包

org.springframework.boot spring-boot-starter-parent 2.1.0.RELEASE org.springframework.boot spring-boot-starter-data-mongodb 3.2、添加配置文件 在application.properties文件中添加mongodb配置

#配置数据库连接地址
spring.data.mongodb.uri=mongodb://test123:test123@127.0.0.1:27017/test_db
3.3、创建实体类
创建用于示例中测试的实体类Person。

其中注解@Document(collection=“persons”)用于指定当前文档属于集合persons。

注解@Id表示当前id字段属于主键类型。

/**

  • 使用@Document注解指定集合名称
    */
    @Document(collection=“persons”)
    public class Person implements Serializable {
    private static final long serialVersionUID = -3258839839160856613L;

    /**

    • 使用@Id注解指定MongoDB中的 _id 主键
      */
      @Id
      private Long id;

    private String userName;

    private String passWord;

    private Integer age;

    private Date createTime;

    //…get/set

    @Override
    public String toString() {
    return “Person{” +
    “id=” + id +
    “, userName='” + userName + ‘’’ +
    “, passWord='” + passWord + ‘’’ +
    “, age=” + age +
    “, createTime=” + createTime +
    ‘}’;
    }
    }
    3.4、操作 MongoDB
    Springboot 操作 MongoDB 有两种方式。

第一种方式是采用 Springboot 官方推荐的 JPA 方式,这种操作方式,使用简单但是灵活性比较差。
第二种方式是采用 Spring Data MongoDB 封装的 MongoDB 官方 Java 驱动 MongoTemplate 对 MongoDB 进行操作,这种方式非常灵活,能满足绝大部分需求。
本文将采用第二种方式进行介绍!

3.5、插入文档
MongoTemplate提供了insert()方法,用于插入文档,示例代码如下:

用于插入文档
没指定集合名称时,会取@Document注解中的集合名称
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 插入文档
 * @throws Exception
 */
@Test
public void insert() throws Exception {
    Person person =new Person();
    person.setId(1l);
    person.setUserName("张三");
    person.setPassWord("123456");
    person.setCreateTime(new Date());
    mongoTemplate.insert(person);
}

}
自定义集合名称,插入文档
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 自定义集合,插入文档
 * @throws Exception
 */
@Test
public void insertCustomCollection() throws Exception {
    Person person =new Person();
    person.setId(1l);
    person.setUserName("张三");
    person.setPassWord("123456");
    person.setCreateTime(new Date());
    mongoTemplate.insert(person, "custom_person");
}

}
自定义集合,批量插入文档
如果采用批量插入文档,必须指定集合名称
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 自定义集合,批量插入文档
 * @throws Exception
 */
@Test
public void insertBatch() throws Exception {
    List<Person> personList = new ArrayList<>();
    Person person1 =new Person();
    person1.setId(10l);
    person1.setUserName("张三");
    person1.setPassWord("123456");
    person1.setCreateTime(new Date());
    personList.add(person1);

    Person person2 =new Person();
    person2.setId(11l);
    person2.setUserName("李四");
    person2.setPassWord("123456");
    person2.setCreateTime(new Date());
    personList.add(person2);
    mongoTemplate.insert(personList, "custom_person");
}

}
3.6、存储文档
MongoTemplate提供了save()方法,用于存储文档。

在存储文档的时候会通过主键ID进行判断,如果存在就更新,否则就插入,示例代码如下:

存储文档,如果没有插入,否则通过主键ID更新
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 存储文档,如果没有插入,否则更新
 * @throws Exception
 */
@Test
public void save() throws Exception {
    Person person =new Person();
    person.setId(13l);
    person.setUserName("八八");
    person.setPassWord("123456");
    person.setAge(40);
    person.setCreateTime(new Date());
    mongoTemplate.save(person);
}

}
自定义集合,存储文档
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 自定义集合,存储文档
 * @throws Exception
 */
@Test
public void saveCustomCollection() throws Exception {
    Person person =new Person();
    person.setId(1l);
    person.setUserName("张三");
    person.setPassWord("123456");
    person.setCreateTime(new Date());
    //必须指定集合名称,否则无法保存成功
    mongoTemplate.save(person, "custom_person");
}

}
注:save和insert都是插入,但还是有区别的
(一、使用save函数里,如果原来的对象不存在,那他们都可以向collection里插入数据,如果已经存在,save会调用update更新里面的记录,而insert则会忽略操作
二、insert可以一次性插入一个列表,而不用遍历,效率高, save则需要遍历列表,一个个插入。)

3.7、更新文档
MongoTemplate提供了updateFirst()和updateMulti()方法,用于更新文档,示例代码如下:

更新文档,匹配查询到的文档数据中的第一条数据
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 更新文档,匹配查询到的文档数据中的第一条数据
 * @throws Exception
 */
@Test
public void updateFirst() throws Exception {
    //更新对象
    Person person =new Person();
    person.setId(1l);
    person.setUserName("张三123");
    person.setPassWord("123456");
    person.setCreateTime(new Date());

    //更新条件
    Query query= new Query(Criteria.where("id").is(person.getId()));

    //更新值
    Update update= new Update().set("userName", person.getUserName()).set("passWord", person.getPassWord());
    //更新查询满足条件的文档数据(第一条)
    UpdateResult result =mongoTemplate.updateFirst(query,update, Person.class);
    if(result!=null){
        System.out.println("更新条数:" + result.getMatchedCount());
    }
}

}
更新文档,匹配查询到的文档数据中的所有数据
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 更新文档,匹配查询到的文档数据中的所有数据
 * @throws Exception
 */
@Test
public void updateMany() throws Exception {
    //更新对象
    Person person =new Person();
    person.setId(1l);
    person.setUserName("张三");
    person.setPassWord("123456");
    person.setCreateTime(new Date());

    //更新条件
    Query query= new Query(Criteria.where("id").is(person.getId()));

    //更新值
    Update update= new Update().set("userName", person.getUserName()).set("passWord", person.getPassWord());
    //更新查询满足条件的文档数据(全部)
    UpdateResult result = mongoTemplate.updateMulti(query, update, Person.class);
    if(result!=null){
        System.out.println("更新条数:" + result.getMatchedCount());
    }
}

}
3.8、删除文档
MongoTemplate提供了remove()、findAndRemove()和findAllAndRemove()方法,用于删除文档,示例代码如下:

删除符合条件的所有文档
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 删除符合条件的所有文档
 * @throws Exception
 */
@Test
public void remove() throws Exception {
    Person person =new Person();
    person.setId(1l);
    person.setUserName("张三");
    person.setPassWord("123456");
    person.setCreateTime(new Date());

    Query query = new Query(Criteria.where("userName").is(person.getUserName()));
    DeleteResult result = mongoTemplate.remove(query, Person.class);
    System.out.println("删除条数:" + result.getDeletedCount());
}

}
删除符合条件的单个文档,并返回删除的文档
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 删除符合条件的单个文档,并返回删除的文档
 * @throws Exception
 */
@Test
public void findAndRemove() throws Exception {
    Person person =new Person();
    person.setId(1l);
    person.setUserName("张三");
    person.setPassWord("123456");
    person.setCreateTime(new Date());

    Query query = new Query(Criteria.where("id").is(person.getId()));
    Person result = mongoTemplate.findAndRemove(query, Person.class);
    System.out.println("删除的文档数据:" + result.toString());
}

}
删除符合条件的所有文档,并返回删除的文档
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 删除符合条件的所有文档,并返回删除的文档
 * @throws Exception
 */
@Test
public void findAllAndRemove() throws Exception {
    Person person =new Person();
    person.setId(1l);
    person.setUserName("张三");
    person.setPassWord("123456");
    person.setCreateTime(new Date());

    Query query = new Query(Criteria.where("id").is(person.getId()));
    List<Person> result = mongoTemplate.findAllAndRemove(query, Person.class);
    System.out.println("删除的文档数据:" + result.toString());
}

}
3.9、查询文档
Query对象常用的条件
1 创建一个query对象(用来封装所有条件对象),再创建一个criteria对象(用来构建条件)
2 精准条件:criteria.and(“key”).is(“条件”)
3 模糊条件:criteria.and(“key”).regex(“条件”)
4 封装条件:query.addCriteria(criteria)
5 大于(创建新的criteria):Criteria gt = Criteria.where(“key”).gt(“条件”)
6 小于(创建新的criteria):Criteria lt = Criteria.where(“key”).lt(“条件”)
7 Query.addCriteria(new Criteria().andOperator(gt,lt));
8 一个query中只能有一个andOperator()。其参数也可以是Criteria数组。
9 排序 :query.with(new Sort(Sort.Direction.ASC, “age”). and(newSort(Sort.Direction.DESC, “date”)))

MongoTemplate提供了非常多的文档查询方法,日常开发中用的最多的就是find()方法,示例代码如下:
查询集合中的全部文档数据
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 查询集合中的全部文档数据
 * @throws Exception
 */
@Test
public void findAll() throws Exception {
    List<Person> result = mongoTemplate.findAll(Person.class);
    System.out.println("查询结果:" + result.toString());
}

}
查询集合中指定的ID文档数据
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 查询集合中指定的ID文档数据
 * @throws Exception
 */
@Test
public void findById() {
    long id = 1l;
    Person result = mongoTemplate.findById(id, Person.class);
    System.out.println("查询结果:" + result.toString());
}

}
根据条件查询集合中符合条件的文档,返回第一条数据
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 根据条件查询集合中符合条件的文档,返回第一条数据
 */
@Test
public void findOne() {
    String userName = "张三";
    Query query = new Query(Criteria.where("userName").is(userName));
    Person result = mongoTemplate.findOne(query, Person.class);
    System.out.println("查询结果:" + result.toString());
}

}
根据条件查询集合中符合条件的文档
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 根据条件查询集合中符合条件的文档
 */
@Test
public void findByCondition() {
    String userName = "张三";
    Query query = new Query(Criteria.where("userName").is(userName));
    List<Person> result = mongoTemplate.find(query, Person.class);
    System.out.println("查询结果:" + result.toString());
}

}
根据【AND】关联多个查询条件,查询集合中的文档数据
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 根据【AND】关联多个查询条件,查询集合中的文档数据
 */
@Test
public void findByAndCondition() {
    // 创建条件
    Criteria criteriaUserName = Criteria.where("userName").is("张三");
    Criteria criteriaPassWord = Criteria.where("passWord").is("123456");
    // 创建条件对象,将上面条件进行 AND 关联
    Criteria criteria = new Criteria().andOperator(criteriaUserName, criteriaPassWord);
    // 创建查询对象,然后将条件对象添加到其中
    Query query = new Query(criteria);
    List<Person> result = mongoTemplate.find(query, Person.class);
    System.out.println("查询结果:" + result.toString());
}

}
根据【OR】关联多个查询条件,查询集合中的文档数据
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 根据【OR】关联多个查询条件,查询集合中的文档数据
 */
@Test
public void findByOrCondition() {
    // 创建条件
    Criteria criteriaUserName = Criteria.where("userName").is("张三");
    Criteria criteriaPassWord = Criteria.where("passWord").is("123456");
    // 创建条件对象,将上面条件进行 OR 关联
    Criteria criteria = new Criteria().orOperator(criteriaUserName, criteriaPassWord);
    // 创建查询对象,然后将条件对象添加到其中
    Query query = new Query(criteria);
    List<Person> result = mongoTemplate.find(query, Person.class);
    System.out.println("查询结果:" + result.toString());
}

}
根据【IN】关联多个查询条件,查询集合中的文档数据
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 根据【IN】关联多个查询条件,查询集合中的文档数据
 */
@Test
public void findByInCondition() {
    // 设置查询条件参数
    List<Long> ids = Arrays.asList(1l, 10l, 11l);
    // 创建条件
    Criteria criteria = Criteria.where("id").in(ids);
    // 创建查询对象,然后将条件对象添加到其中
    Query query = new Query(criteria);
    List<Person> result = mongoTemplate.find(query, Person.class);
    System.out.println("查询结果:" + result.toString());
}

}
根据【逻辑运算符】查询集合中的文档数据
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 根据【逻辑运算符】查询集合中的文档数据
 */
@Test
public void findByOperator() {
    // 设置查询条件参数
    int min = 20;
    int max = 35;
    Criteria criteria = Criteria.where("age").gt(min).lte(max);
    // 创建查询对象,然后将条件对象添加到其中
    Query query = new Query(criteria);
    List<Person> result = mongoTemplate.find(query, Person.class);
    System.out.println("查询结果:" + result.toString());
}

}
根据【正则表达式】查询集合中的文档数据
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 根据【正则表达式】查询集合中的文档数据
 */
@Test
public void findByRegex() {
    // 设置查询条件参数
    String regex = "^张*";
    Criteria criteria = Criteria.where("userName").regex(regex);
    // 创建查询对象,然后将条件对象添加到其中
    Query query = new Query(criteria);
    List<Person> result = mongoTemplate.find(query, Person.class);
    System.out.println("查询结果:" + result.toString());
}

}
根据条件查询集合中符合条件的文档,获取其文档列表并排序
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 根据条件查询集合中符合条件的文档,获取其文档列表并排序
 */
@Test
public void findByConditionAndSort() {
    String userName = "张三";
    Query query = new Query(Criteria.where("userName").is(userName)).with(Sort.by("age"));
    List<Person> result = mongoTemplate.find(query, Person.class);
    System.out.println("查询结果:" + result.toString());
}

}
根据单个条件查询集合中的文档数据,并按指定字段进行排序与限制指定数目
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
* 根据单个条件查询集合中的文档数据,并按指定字段进行排序与限制指定数目
*/
@Test
public void findByConditionAndSortLimit() {
String userName = “张三”;
//从第一行开始,查询2条数据返回
Query query = new Query(Criteria.where(“userName”).is(userName)).with(Sort.by(“createTime”)).limit(2).skip(1);
List result = mongoTemplate.find(query, Person.class);
System.out.println(“查询结果:” + result.toString());
}
}
统计集合中符合【查询条件】的文档【数量】
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
* 统计集合中符合【查询条件】的文档【数量】
/
@Test
public void countNumber() {
// 设置查询条件参数
String regex = "^张
";
Criteria criteria = Criteria.where(“userName”).regex(regex);
// 创建查询对象,然后将条件对象添加到其中
Query query = new Query(criteria);
long count = mongoTemplate.count(query, Person.class);
System.out.println(“统计结果:” + count);
}
}
4.0、创建索引
索引在所有的数据库中,暂居的位置非常重要,例如当你检索一张上百万的数据表的时候,如果没走索引,查询效率会极其缓慢,对于 MongoDB 来说,同样如此。

示例如下:

创建升序索引
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
 * 创建升序索引
 */
@Test
public void createAscendingIndex() {
    // 设置字段名称
    String field = "userName";
    // 创建索引
    mongoTemplate.getCollection("persons").createIndex(Indexes.ascending(field));
}

}
移除索引
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
* 根据索引名称移除索引
*/
@Test
public void removeIndex() {
// 设置字段名称
String field = “userName”;
// 删除索引
mongoTemplate.getCollection(“persons”).dropIndex(field);
}
}
查询集合中所有的索引
@RunWith(SpringRunner.class)
@SpringBootTest
public class PersonServiceTest {

@Autowired
private MongoTemplate mongoTemplate;

/**
* 查询集合中所有的索引
/
@Test
public void getIndexAll() {
// 获取集合中所有列表
ListIndexesIterable indexList = mongoTemplate.getCollection(“persons”).listIndexes();
// 获取集合中全部索引信息
for (Document document : indexList) {
System.out.println(“索引列表:” + document);
}
}
}
我们还可以通过在实体类上加注解方式来创建索引
/
*

  • 使用@Document注解指定集合名称
    */
    @Document(collection=“persons”)
    public class Person implements Serializable {
    private static final long serialVersionUID = -3258839839160856613L;

    /**

    • 使用@Id注解指定MongoDB中的 _id 主键
      */
      @Id
      private Long id;

    private String userName;

    private String passWord;

    private Integer age;

    /**

    • 创建一个5秒之后文档自动删除的索引
      */
      @Indexed(expireAfterSeconds=5)
      private Date createTime;

    //…get/set

    @Override
    public String toString() {
    return “Person{” +
    “id=” + id +
    “, userName='” + userName + ‘’’ +
    “, passWord='” + passWord + ‘’’ +
    “, age=” + age +
    “, createTime=” + createTime +
    ‘}’;
    }
    }
    4.1、引入 MongoDB 中的事务
    单节点 mongodb 不支持事务,需要搭建 MongoDB 复制集。
    /**

  • 配置事务管理器

*/
@Configuration
public class TransactionConfig {

@Bean
MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) {
    return new MongoTransactionManager(dbFactory);
}

}
事务服务测试!

@Service
public class TransactionExample {

@Autowired
private MongoTemplate mongoTemplate;

@Transactional(rollbackFor = Exception.class)
public Object transactionTest(){
    Person person =new Person();
    person.setId(1l);
    person.setUserName("张三");
    person.setPassWord("123456");
    person.setCreateTime(new Date());
    Person newPerson = mongoTemplate.insert(person);
    // 抛出异常,观察数据是否进行回滚
    if(1 == 1){
        throw new RuntimeException("异常");
    }
    return newPerson;
}

}

參考文檔:MongoDB查詢文檔api介紹

隨手記錄,若有誤請提醒更正。

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值