MongoDB —— 使用Spring Data MongoDB操做数据库

本文代码示例参见:https://gitee.com/imlichao/MongoDB-examplehtml

 

咱们使用Spring Data MongoDB能够方便的在Spring boot项目中操做MongoDBjava

文档地址:https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/htmlsingle/#boot-features-mongodbgit

加载包

在pom文件中加入spring-boot-starter-data-mongodb配置正则表达式

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

 

配置参数

# user - 用户名、secret - 密码、mongo1.example.com - 数据库地址、27017- 端口号、teat - 库名 
spring.data.mongodb.uri=mongodb://user:secret@mongo1.example.com:27017/test

 

实体映射

咱们能够经过实体类来进行关系映射,从而可以方便的使用对象进行数据操做。spring

Spring Data MongoDB提供了一些方便的映射注释供咱们使用,下面列出官方说明地址以供参考mongodb

官方说明文档:https://docs.spring.io/spring-data/mongodb/docs/2.1.3.RELEASE/reference/html/#mapping-usage数据库

  • @Id:用于标记id字段,没有标记此字段的实体也会自动生成id字段,可是咱们没法经过实体来获取id。id建议使用ObjectId类型来建立。api

  • @Document:用于标记此实体类是mongodb集合映射类。可使用collection参数指定集合名称。特别须要注意的是若是实体类没有为任何字段建立索引将不会自动建立集合。数组

  • @Indexed:用于标记为某一字段建立索引。direction参数能够指定排序方向,升或降序。oracle

  • @CompoundIndex:用于建立复合索引。def参数能够定义复合索引的字段及排序方向。

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

  • @PersistenceConstructor:用于声明构造函数,做用是把从数据库取出的数据实例化为对象。

  • @Field:用于指定某一个字段映射到数据库中的名称。

  • @DBRef:用于指定与其余集合的级联关系,可是须要注意的是并不会自动建立级联集合。

 

一个简单的例子:

//注释此类将被映射到数据库的一个集合(collection为集合名称)
@Document(collection = "ex_entity_test")

//建立联合索引
@CompoundIndexes({
        //联合索引 name 索引名称 、def 索引字段、parameter1升序、parameter3降序
        @CompoundIndex(name = "compound_index", def = "{'parameter1': 1, 'parameter3': -1}")
})

public class EntityTest implements Serializable {
    //标记id字段
    @Id
    private ObjectId id;
    //建立单字段索引(默认ASCENDING 升序、DESCENDING 降序)
    @Indexed(direction = DESCENDING)
    private Long parameter1;
    //修改映射到数据库中的名称
    @Field("parameter2_")
    private String parameter2;

    private Date parameter3;

    private Integer parameter4;

    //关联其余集合(不添加此注释时List将会保存具体的实体值,而添加了此注释List保存的是关联集合的id)
    @DBRef
    private List<EntityTest1> parameter5;
    //此字段不映射到数据库
    @Transient
    private Integer parameter6;

    public EntityTest(){

    }
    //声明构造函数,用于实例化查询结果数据
    @PersistenceConstructor
    public EntityTest(Long parameter1, String parameter2, Date parameter3, Integer parameter4, List<EntityTest1> parameter5) {
        this.parameter1 = parameter1;
        this.parameter2 = parameter2;
        this.parameter3 = parameter3;
        this.parameter4 = parameter4;
        this.parameter5 = parameter5;
    }

    public ObjectId getId() {
        return id;
    }

    public void setId(ObjectId id) {
        this.id = id;
    }

    ......

    public Integer getParameter6() {
        return parameter6;
    }

    public void setParameter6(Integer parameter6) {
        this.parameter6 = parameter6;
    }
}

上例关联的集合

//注释此类将被映射到数据库的一个集合(collection为集合名称)
@Document(collection = "ex_entity_test1")

public class EntityTest1 implements Serializable {
    //标记id字段
    @Id
    private ObjectId id;

    //若是实体类没有为任何字段建立索引将不会自动建立集合
    @Indexed
    private Long parameter1;

    public EntityTest1(){

    }

    public EntityTest1(Long parameter1) {
        this.parameter1 = parameter1;
    }

    public ObjectId getId() {
        return id;
    }

    public void setId(ObjectId id) {
        this.id = id;
    }

    public Long getParameter1() {
        return parameter1;
    }

    public void setParameter1(Long parameter1) {
        this.parameter1 = parameter1;
    }
}

 

数据操做

当完成一系列的配置与准备工做后,咱们就可使用MongoTemplate来操做数据库了。

MongoTemplate为咱们提供了全面的增删改查等操做数据库的方法,详情可查看官方说明文档和API文档

官方说明文档:https://docs.spring.io/spring-data/mongodb/docs/2.1.3.RELEASE/reference/html/#mongo-template

API文档:https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/MongoTemplate.html

一个简单的例子:

@Controller
public class MongoController {

    @Autowired
    private MongoTemplate mongoTemplate;

    @GetMapping(value = "/")
    public String index(){
        return "redirect:/find";
    }

    //新增文档
    @GetMapping(value = "/insert")
    public String insert(){
        //insert方法并不提供级联类的保存,因此级联类须要先本身先保存
        EntityTest1 entityTest1_1 = new EntityTest1(1000L);
        //执行完insert后对象entityTest1将会得到保存后的id
        mongoTemplate.insert(entityTest1_1);
        //再添加一条
        EntityTest1 entityTest1_2 = new EntityTest1(1001L);
        mongoTemplate.insert(entityTest1_2);
        //建立列表并将保存后的关联对象添加进去
        ArrayList<EntityTest1> entityTest1List = new ArrayList<EntityTest1>();
        entityTest1List.add(entityTest1_1);
        entityTest1List.add(entityTest1_2);

        //新增主体对象
        EntityTest entityTest = new EntityTest(100L,"test",new Date(),10,entityTest1List);
        //新增数据的主键已经存在,则会抛DuplicateKeyException异常
        mongoTemplate.insert(entityTest);
        return "redirect:/find";
    }

    //保存文档
    //保存与新增的主要区别在于,若是主键已经存在,新增抛出异常,保存修改数据
    @GetMapping(value = "/save")
    public String save(){
        //查询最后一条数据并更新
        Sort sort = new Sort(Sort.Direction.DESC,"parameter3");
        EntityTest entityTest = mongoTemplate.findOne(Query.query(Criteria.where("")).with(sort),EntityTest.class);
        entityTest.setParameter4(3000);
        //保存数据的主键已经存在,则会对已经存在的数据修改
        mongoTemplate.save(entityTest);
        return "redirect:/find";
    }

    //删除文档
    @GetMapping(value = "/delete")
    public String delete(){
        //查询第一条数据并删除
        EntityTest entityTest = mongoTemplate.findOne(Query.query(Criteria.where("")),EntityTest.class);
        //remove方法不支持级联删除因此要单独删除子数据
        List<EntityTest1> entityTest1List = entityTest.getParameter5();
        for(EntityTest1 entityTest1:entityTest1List){
            mongoTemplate.remove(entityTest1);
        }
        //删除主数据
        mongoTemplate.remove(entityTest);

        return "redirect:/find";
    }

    //更新文档
    @GetMapping(value = "/update")
    public String update(){
        //将查询条件符合的所有文档更新
        Query query = new Query();
        Update update = Update.update("parameter2_","update");
        mongoTemplate.updateMulti(query,update,EntityTest.class);
        return "redirect:/find";
    }

    //查询文档
    @GetMapping(value = "/find")
    public String find(Model model){
        //查询小于当前时间的数据,并按时间倒序排列
        Sort sort = new Sort(Sort.Direction.DESC,"parameter3");
        List<EntityTest> findTestList = mongoTemplate.find(Query.query(Criteria.where("parameter3").lt(new Date())).with(sort) ,EntityTest.class);
        model.addAttribute("findTestList",findTestList);

        //使用findOne查询若是结果极为多条,则返回排序在最上面的一条
        EntityTest findOneTest = mongoTemplate.findOne(Query.query(Criteria.where("parameter3").lt(new Date())).with(sort) ,EntityTest.class);
        model.addAttribute("findOneTest",findOneTest);

        //模糊查询
        List<EntityTest> findTestList1 = mongoTemplate.find(Query.query(Criteria.where("parameter3").lt(new Date()).and("parameter2").regex("es")) ,EntityTest.class);
        model.addAttribute("findTestList1",findTestList1);

        //分页查询(每页3行第2页)
        Pageable pageable = new PageRequest(1,3,sort);
        List<EntityTest> findTestList2 = mongoTemplate.find(Query.query(Criteria.where("parameter3").lt(new Date())).with(pageable) ,EntityTest.class);
        //共多少条
        Long count = mongoTemplate.count(Query.query(Criteria.where("parameter3").lt(new Date())),EntityTest.class);
        //返回分页对象
        Page<EntityTest> page = new PageImpl<EntityTest>(findTestList2,pageable,count);
        model.addAttribute("page",page);

        //分页查询(经过起始行和数量也能够本身实现分页逻辑)
        List<EntityTest> findTestList3 = mongoTemplate.find(Query.query(Criteria.where("parameter3").lt(new Date())).with(sort).skip(3).limit(3) ,EntityTest.class);
        model.addAttribute("findTestList3",findTestList3);

        return "/index";
    }
}

 

查询

因为查询相对于其余增删改的操做要复杂一些,因此在这里单独说一下查询。还看上面的例子就能够。

首先咱们先介绍一下几个和查询有关的类Query、Criteria、Sort、PageRequest、PageImpl

Query

查询对象定义一个查询的全部要素,其中包括筛选条件、排序、起始行、返回条数等内容

API文档:https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/query/Query.html

经常使用方法介绍:

query(CriteriaDefinition criteriaDefinition)

静态方法经过注入一个CriteriaDefinition条件对象得到Query查询对象。在简单查询时使用此方法将很是的方便。
例如:mongoTemplate.find(Query.query(Criteria.where("parameter3").lt(new Date())

addCriteria(CriteriaDefinition criteriaDefinition)

添加一个CriteriaDefinition查询条件类到本次查询

skip(long skip)

跳过文档的数量,能够与limit配合使用实现分页效果。

limit(int limit)

查询返回的文档数量。

with(Sort sort)

添加一个Sort排序对象

with(Pageable pageable)

添加一个Pageable分页对象。Pageable能够注入一个Sort,因此分页和排序能够一块儿添加。
例如:Pageable pageable = new PageRequest(1,3,sort);

 

Criteria

查询条件类,使用此类定义查询时的查询条件至关于SQL的where。

API文档:https://docs.spring.io/spring-data/mongodb/docs/current/api/org/springframework/data/mongodb/core/query/Criteria.html

经常使用方法介绍:

where(String key)

静态方法,用它能够很方便的定义查询条件

例如:mongoTemplate.find(Query.query(Criteria.where("parameter3").lt(new Date()).and("parameter2").regex("es"))

and(String key) 与操做
gt(Object o) 大于
gte(Object o) 大于等于
in(Object... o) 包含
is(Object o) 等于
lt(Object o) 小于
lte(Object o)    小于等于
not()
regex(String re) 正则表达式
andOperator(Criteria... criteria) 建立与操做
orOperator(Criteria... criteria) 建立或操做

 

Sort

查询排序类,使用此类能够建立查询排序。

API文档:https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/Sort.html?is-external=true

经常使用方法介绍:

Sort(Sort.Direction direction, String... properties) 构造方法建立一个排序。direction为排序方向的枚举类型,properties为排序字段数组
and(Sort sort) 多个排序条件连接
ascending() 返回升序排列对象
descending() 返回降序排列对象

 

PageRequest和PageImpl

这两个类都是分页相关的封装类,与其余数据库的使用方法同样。PageRequest分页请求类,PageImpl为页面封装类。

API文档:https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/PageRequest.html

               https://docs.spring.io/spring-data/commons/docs/current/api/org/springframework/data/domain/PageImpl.html

相关文章
相关标签/搜索