spring-data-mongoDB

news/2025/2/25 15:57:26

目录

spring-data-mongoDB%E4%BD%BF%E7%94%A8-toc" name="tableOfContents" style="margin-left:0px">spring-data-mongoDB使用

1.导入mongoDB依赖

2.编写配置文件

3.编写实体类,与mongoDB中的文档相对应,使用@Document注解

4.编写service层方法

一.实现保存方法

 二.实现修改方法

三.实现删除方法

四.实现查询方法

项目使用mongoDB实现作业范围 

1.实体类

2.业务实现


这里介绍以下spring-data-mongoDB的用法

spring-data-mongoDB%E4%BD%BF%E7%94%A8" name="spring-data-mongoDB%E4%BD%BF%E7%94%A8" style="background-color:transparent">spring-data-mongoDB使用

1.导入mongoDB依赖

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

2.编写配置文件

spring:
  application:
    name: sl-express-mongodb
  data:
    mongodb:
      host: 192.168.150.101
      port: 27017
      database: sl
      authentication-database: admin #认证数据库
      username: sl
      password: "123321"
      auto-index-creation: true #自动创建索引

3.编写实体类,与mongoDB中的文档相对应,使用@Document注解

java">import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.bson.types.ObjectId;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
import org.springframework.data.mongodb.core.index.Indexed;
import org.springframework.data.mongodb.core.mapping.Document;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document("sl_person") //指定表名,也就是指定集合的名字
public class Person {
    @Id // 标识为主键
    private ObjectId id;
    @Indexed //标识索引字段
    private String name;
    private int age;
    /**
     * 用户位置
     * x: 经度,y:纬度
     */
    @GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
    private GeoJsonPoint location;
    //存储嵌套对象数据
    private Address address;
}
java">import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.mongodb.core.mapping.Document;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Document("sl_address") //指定表名,也就是指定集合的名字
public class Address {
    private String street;
    private String city;
    private String zip;
}

4.编写service层方法

因为mongoDB没有向mysql,neo4j一样提供持久层的接口方法,但是和redis一样有一个MongoTemplate 的bean对象,可以直接对数据库进行CRUD操作

java">public interface PersonService {
    /**
     * 新增数据
     *
     * @param person 数据
     */
    void savePerson(Person person);
    /**
     * 更新数据
     *
     * @param person 数据
     */
    void update(Person person);
    /**
     * 根据名字查询用户列表
     *
     * @param name 用户名字
     * @return 用户列表
     */
    List<Person> queryPersonListByName(String name);
    /**
     * 分页查询用户列表
     *
     * @param page     页数
     * @param pageSize 页面大小
     * @return 用户列表
     */
    List<Person> queryPersonPageList(int page, int pageSize);
    /**
     * 根据id删除用户
     *
     * @param id 主键
     */
    void deleteById(String id);
}
java">import org.springframework.data.mongodb.core.MongoTemplate;

import javax.annotation.Resource;
import java.util.List;

public class PersonServiceImpl implements PersonService {
    @Resource
    private MongoTemplate mongoTemplate;
    @Override
    public void savePerson(Person person) {

    }

    @Override
    public void update(Person person) {

    }

    @Override
    public List<Person> queryPersonListByName(String name) {
        return null;
    }

    @Override
    public List<Person> queryPersonPageList(int page, int pageSize) {
        return null;
    }

    @Override
    public void deleteById(String id) {

    }
}

一.实现保存方法

可以使用insert方法和save方法,但是save方法会直接覆盖原来的值

java">  @Override
    public void savePerson(Person person) {
        mongoTemplate.save(person);
    }

测试

java">import org.bson.types.ObjectId;


 @Resource
    PersonService personService;
    @Test
    void savePerson() {
        Person person = Person.builder()
                .id(ObjectId.get()) //使用mongoDB提供的ObjectId生成id值
                .name("张三")
                .age(20)
                .location(new GeoJsonPoint(116.343847, 40.060539))
                .address(new Address("人民路", "上海市", "666666")).build();
        this.personService.savePerson(person);
    }

不使用ObjectId获取id也可以,mongoDB也会自己生成

java">@Test
    void savePerson() {
        Person person = Person.builder()
                //.id(ObjectId.get())
                .name("张三")
                .age(20)
                .location(new GeoJsonPoint(116.343847, 40.060539))
                .address(new Address("人民路", "上海市", "666666")).build();
        this.personService.savePerson(person);
    }

 二.实现修改方法

java"> @Override
    public void update(Person person) {
        //1.构建查询条件,定义要改哪些数据,这里定义了要改主键_id=person.getId的数据
        /*Query query = new Query();
        query.addCriteria(Criteria.where("_id").is(person.getId()));*/
        //或者:
        Query query = Query.query(Criteria.where("_id").is(person.getId()));

        //2.设置要修改的值
        Update update = new Update();
        update.set("name",person.getName());
        update.set("age",person.getAge());
        update.set("location",person.getLocation());
        update.set("address",person.getAddress());
        //3.只修改一个
        mongoTemplate.updateFirst(query,update, Person.class);//根据Person.class提供的类型才能去操作哪一个集合
    }

测试

java">    @Test
    void update() {
        Person person = Person.builder()
                .id(new ObjectId("67b7fb71ab81697aa2e8688e"))
                .name("张三")
                .age(22) //修改数据
                .location(new GeoJsonPoint(116.343847, 40.060539))
                .address(new Address("人民路", "上海市", "666666")).build();
        this.personService.update(person);
    }

三.实现删除方法

其实_id可以写出id,mongo也会当作主键去查

java">    @Override
    public void deleteById(String id) {
        Query query = Query.query(Criteria.where("_id").is(id));
        mongoTemplate.remove(query, Person.class);
    }

测试

java">@Test
    void deleteById() {
        this.personService.deleteById("67b7fb71ab81697aa2e8688e");
    }

四.实现查询方法

java">    @Override
    public List<Person> queryPersonListByName(String name) {
        Query query = Query.query(Criteria.where("name").regex(name));//根据正则表达式查询,类似模糊查询
        return mongoTemplate.find(query,Person.class);
    }

测试

java">    @Test
    void queryPersonListByName() {
        List<Person> personList = this.personService.queryPersonListByName("三");
        personList.forEach(System.out::println);
    }

五.实现分页查询

java">@Override
    public List<Person> queryPersonPageList(int page, int pageSize) {
        //1.构建查询条件
        Query query = new Query();
        //根据age降序
        query.with(Sort.by(Sort.Direction.DESC,"age"));
        //构建分页条件,mongoDB默认页数从0开始,而一般前端都是从第一页,所以要减一
        query.with(PageRequest.of((page-1),pageSize));
        return mongoTemplate.find(query, Person.class);
    }

 测试

java">    @Test
    void queryPersonPageList() {
        List<Person> personList = this.personService.queryPersonPageList(1, 10);
        personList.forEach(System.out::println);
    }

项目使用mongoDB实现作业范围 

1.实体类

这里对id主键不进行json序列化,使用bid作为我们的业务id,并且对类型进行普通索引,使用type来区分快递机构和快递员,最后使用GeoJsonPolygon类型作为面积范围的闭合的多边形范围,并使用索引

java">@Data
@Document("sl_service_scope")
public class ServiceScopeEntity {

    @Id
    @JsonIgnore
    private ObjectId id;

    /**
     * 业务id,可以是机构或快递员
     */
    @Indexed
    private Long bid;

    /**
     * 类型 {@link com.sl.ms.scope.enums.ServiceTypeEnum}
     */
    @Indexed
    private Integer type;

    /**
     * 多边形范围,是闭合的范围,开始经纬度与结束经纬度必须一样
     * x: 经度,y:纬度
     */
    @GeoSpatialIndexed(type = GeoSpatialIndexType.GEO_2DSPHERE)
    private GeoJsonPolygon polygon;

    private Long created; //创建时间
    private Long updated; //更新时间
}
java">public enum ServiceTypeEnum {

    ORGAN(1, "机构"),
    COURIER(2, "快递员");

    /**
     * 类型编码
     */
    private final Integer code;

    /**
     * 类型值
     */
    private final String value;


    ServiceTypeEnum(Integer code, String value) {
        this.code = code;
        this.value = value;
    }

    public Integer getCode() {
        return code;
    }

    public String getValue() {
        return value;
    }

    public static ServiceTypeEnum codeOf(Integer code) {
        return EnumUtil.getBy(ServiceTypeEnum::getCode, code);
    }
}

2.业务实现

保存数据

java">/**
     * 保存或修改 作业范围
     * @param bid     业务id
     * @param type    类型
     * @param polygon 多边形坐标点
     * @return
     */
    @Override
    public Boolean saveOrUpdate(Long bid, ServiceTypeEnum type, GeoJsonPolygon polygon) {
        // TODO day08 新增作业范围
        // 1. 构建mongo查询条件  bid    type
        Query query = Query.query(Criteria.where("bid").is(bid).and("type").is(type.getCode()));
        // 2. 根据条件查询对应作业范围
        ServiceScopeEntity serviceScopeEntity = mongoTemplate.findOne(query, ServiceScopeEntity.class);
        // 3. 如果作业范围为空 ==> 新建作业范围保存
        if(ObjectUtil.isEmpty(serviceScopeEntity)){
            serviceScopeEntity=new ServiceScopeEntity();
            serviceScopeEntity.setBid(bid);
            serviceScopeEntity.setType(type.getCode());
            serviceScopeEntity.setPolygon(polygon);
            serviceScopeEntity.setCreated(System.currentTimeMillis());
            serviceScopeEntity.setUpdated(System.currentTimeMillis());
        }else{
            // 4. 如果作业范围存在 ==> 修改多边形字段 和 updated时间
            serviceScopeEntity.setPolygon(polygon);
            serviceScopeEntity.setUpdated(System.currentTimeMillis());
        }
        try {
            mongoTemplate.save(serviceScopeEntity);
            return true;
        } catch (Exception e) {
            log.error("新增或者修改数据失败,{}",serviceScopeEntity);
        }
        // 5. 返回结果
        return false;
    }

 GeoJsonPolygon类型的构造参数使用的是List<Point>,注意第一个节点数据需要与最后一个节点数据一样,因为要保持是闭合的多边形

java">   import org.springframework.data.geo.Point;
 @Test
    void saveOrUpdate() {
        List<Point> pointList = Arrays.asList(new Point(116.340064,40.061245),
                new Point(116.347081,40.061836),
                new Point(116.34751,40.05842),
                new Point(116.342446,40.058092),
                new Point(116.340064,40.061245));
        Boolean result = this.scopeService.saveOrUpdate(2L, ServiceTypeEnum.ORGAN, new GeoJsonPolygon(pointList));
        System.out.println(result);
    }

 根据传入的一个点的坐标来判断在哪一个机构或者快递员中的范围中,可能会查出来多个,所以用集合

java"> @Override
    public List<ServiceScopeEntity> queryListByPoint(ServiceTypeEnum type, GeoJsonPoint point) {
        // TODO day08 根据类型 和 坐标点查询有交集的作业范围     tips: intersects 查询传入坐标点和mongo库中多边形相交的数据
        Query query = Query.query(Criteria.where("type").is(type.getCode()).and("polygon").intersects(point));
        return mongoTemplate.find(query, ServiceScopeEntity.class);
    }
    @Override
    public List<ServiceScopeEntity> queryListByPoint(ServiceTypeEnum type, String address) {
        // TODO day08 根据类型 和 详细地址     tips: eagleMapTemplate 查询坐标点
        GeoResult geoResult = eagleMapTemplate.opsForBase().geoCode(address);
        Coordinate location = geoResult.getLocation();
        return queryListByPoint(type,new GeoJsonPoint(location.getLongitude(),location.getLatitude()));
    }
java">    @Test
    void testQueryListByPoint() {
        GeoJsonPoint point = new GeoJsonPoint(116.344828,40.05911);
        List<ServiceScopeEntity> serviceScopeEntities = this.scopeService.queryListByPoint(ServiceTypeEnum.ORGAN, point);
        serviceScopeEntities.forEach(serviceScopeEntity -> System.out.println(serviceScopeEntity));
    }

    @Test
    void testQueryListByPoint2() {
        String address = "北京市昌平区金燕龙办公楼";
        List<ServiceScopeEntity> serviceScopeEntities = this.scopeService.queryListByPoint(ServiceTypeEnum.ORGAN, address);
        serviceScopeEntities.forEach(serviceScopeEntity -> System.out.println(serviceScopeEntity));
    }

可以发现这个坐标点被这个闭合的多边形包围 

 根据bid和类型查询

java">    public ServiceScopeEntity queryByBidAndType(Long bid, ServiceTypeEnum type) {
        // TODO day08 根据bid和类型查询作业范围
        Query query = Query.query(Criteria.where("bid").is(bid).and("type").is(type.getCode()));
        return mongoTemplate.findOne(query,ServiceScopeEntity.class);
    }

 


http://www.niftyadmin.cn/n/5865676.html

相关文章

GB 44495-2024《汽车整车信息安全技术要求》标准解读|内容架构、测试内容、应对措施

一、GB 44495-2024《汽车整车信息安全技术要求》出台背景 从中国智能网联汽车产业开始发力&#xff0c;车辆信息安全开始被重视&#xff0c;近些年国内密集出台了多部相关政策文件。 2022年03月:工信部《车联网网络安全和数据安全标准体系建设指南》 2021年09月:工信部《关于…

从0-1学习Mysql第四章: 查询基础

第四章: 查询基础 在本章中&#xff0c;我们将介绍 MySQL 查询的一些基础知识。SQL 查询是从数据库中提取数据的基本操作&#xff0c;理解和掌握这些基础内容对于开发和调试数据库应用至关重要。 1. SELECT 查询 SELECT 是 SQL 查询中最常用的语句&#xff0c;用于从数据库中…

大白话React第四章战项目阶段

大白话React第四章战项目阶段 1. 选项目 这就像你要开个小店&#xff0c;得先想好卖啥东西。根据自己的兴趣和能力&#xff0c;挑个适合的项目。比如你喜欢写文章&#xff0c;就做个博客系统&#xff1b;要是喜欢整理事情&#xff0c;那就弄个待办事项应用&#xff1b;要是对…

【知识】PyTorch中不同优化器的特点和使用

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 目录 1. SGD&#xff08;随机梯度下降&#xff09; 2. Adam&#xff08;自适应矩估计&#xff09; 3. AdamW 4. Adagrad 5. Adadelta 6. Adafact…

在PyTorch使用UNet进行图像分割【附源码】

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…

DeepSeek 提示词:高效的提示词设计

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…

【基于SprintBoot+Mybatis+Mysql】电脑商城项目之加入购物车和显示购物车列表

&#x1f9f8;安清h&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;【Spring篇】【计算机网络】【Mybatis篇】 &#x1f6a6;作者简介&#xff1a;一个有趣爱睡觉的intp&#xff0c;期待和更多人分享自己所学知识的真诚大学生。 目录 &#x1f680;1.加入购物车-数…

git 克隆及拉取github项目到本地微信开发者工具,微信开发者工具通过git commit、git push上传代码到github仓库

git 克隆及拉取github项目到本地微信开发者工具&#xff0c;微信开发者工具通过git commit、git push上传代码到github仓库 git 克隆及拉取github项目到本地 先在自己的用户文件夹新建一个项目文件夹&#xff0c;取名为项目名 例如这样 C:\Users\HP\yzj-再打开一个终端页面&…