SprongBoot + Koltin + MongoDB

SprongBoot + Koltin + MongoDB

项目搭建

  • 打开IDEA,选择File =>New ==> Project
1645844438(1).jpg
  • 选择Spring Initializr,点击 Next
1645844477(1).jpg
  • 勾选Gradle环境,选择Kotlin语言,输入自己的包名,点击Next
1645844526(1).jpg
  • 点击web,勾选Spring Web, 到门口NoSQL ,勾选SpringDataMongoDB ,点击Next ==> Finish,等待构建完成,一个Springboot项目就搭建好了
1645844822(1).png
  • 在包目录下新建几个文件夹,分别存放实体类,请求接口,数据仓库等


    image-20220226111332148.png
  • 在application.properties中配置数据库连接地址
1645848131(1).jpg

例:获取心灵鸡汤

实体类

  • 在pojo下新建一个实体类,承载数据

    package com.sss.notes.pojo
    import org.springframework.data.annotation.Id
    import org.springframework.data.mongodb.core.mapping.Document
    
    /**
     * Document 表示MongoDB的一个文档
     * collation代表实体类对应数据库中collection的名称
     * @Id则代表了MongoDB中的ObjectId,用String承载改类型
     */
    @Document(collection = "soups")
    data class Soup(
        @Id
        val id: String?,
        val name: String?
    ){
        /**
         *  建议实体类添加默认的空参构造函数 因为MongoDB是非关系型数据库数据字段有多有少
         *  在查询数据中,SpringBoot由于找不到默认的构造函数而报错
         *  如 Failed to instantiate void using constructor NO_CONSTRUCTOR with arguments
         */
        constructor():this("","")
    }
    

该实体类承载的collection:

1645846433(1).jpg

数据仓库

  • 在repository下新建SoupRepository
    package com.sss.notes.repository
    import com.sss.notes.pojo.Soup
    import org.springframework.data.mongodb.core.MongoTemplate
    import org.springframework.data.mongodb.core.query.Query
    import org.springframework.stereotype.Repository
    
    /**
     * @Repository 注解可以标记在任何的类上
     * 用来表明该类是用来执行与数据库相关的操作(即dao对象)
     * 并支持自动处理数据库操作产生的异常
     */
    @Repository
    class SoupRepository(private val mongoTemplate: MongoTemplate) {
     /**
     * 将mongoTemplate写入构造方法, 会自动注入到SoupRepository中
     * 或者可以将mongoTemplate从构造方法中移到成员变量中
     * 并且使用@Autowired 标记
     * mongoTemplate 也会自动被写入
     */
    //    @Autowired
    //    private lateinit var mongoTemplate: MongoTemplate

     /**
     * 使用mongoTemplate 查询以startStr开头的心灵鸡汤
     */
     fun findByNameStartWith(startStr: String): List<Soup> {
    
     //正则表达式左匹配
     val pattern: Pattern = Pattern.compile("^$startStr.*$")
     val query = Query.query(Criteria.where("name").regex(pattern))
     return mongoTemplate.find(query, Soup::class.java)
     }
    }

控制层

  • 在controller包下新建一个SoupController,提供给客户端调用

    package com.sss.notes.controller
    import com.sss.notes.pojo.Soup
    import com.sss.notes.repository.SoupRepository
    import org.springframework.http.HttpStatus
    import org.springframework.web.bind.annotation.*
    
    /**
     * 使用@RestController 标记 SoupController
     * 让Springboot 知道这是一个处理http请求的类
     * @RequestMapping:配置url映射
     */
    @RequestMapping("v1/test/")
    @RestController
    class SoupController(private val soupRepository: SoupRepository) {
        
        @ResponseStatus(HttpStatus.OK)
        @GetMapping("/soup")
        fun getSoup(@RequestParam("start") startStr: String): List<Soup> {
            return soupRepository.findByNameStartWith(startStr)
        }
    }
    
  • 启动服务,进行测试

1645848678(1).jpg

多种查询实现的方式

回头看SoupRepository,还可以借助springboot自带的MongoRepository来完成,在repository新建一个接口SoupMongoRepository

package com.sss.notes.repository

import com.sss.notes.pojo.Soup
import org.springframework.data.mongodb.repository.MongoRepository
interface SoupMongoRepository : MongoRepository<Soup, String> {
    /**
     * 接口不用写实现类
     * 根据自己的需求和MongoRepository下输入方法时的提示
     * SpringBoot在初始化的时候会自动实现该查找
     */
    fun findAllByNameStartingWith(startStr: String)
}
1645849206(1).jpg
  • 将SoupController中的SoupRepository替换为SoupMongoRepository

    package com.sss.notes.controller
    import com.sss.notes.pojo.Soup
    import com.sss.notes.repository.SoupMongoRepository
    import org.springframework.http.HttpStatus
    import org.springframework.web.bind.annotation.*
    
    /**
     * 使用@RestController 标记 SoupController
     * 让Springboot 知道这是一个处理http请求的类
     * @RequestMapping:配置url映射
     */
    @RequestMapping("v1/test/")
    @RestController
    class SoupController(private val soupRepository: SoupMongoRepository) {
    
        @ResponseStatus(HttpStatus.OK)
        @GetMapping("/soup")
        fun getSoup(@RequestParam("start") startStr: String): List<Soup>? {
            return soupRepository.findAllByNameStartingWith(startStr)
        }
    }
    
  • 运行后实现了同样的效果,但是在通常的情况下,数据库中的id我们是不返回给前端的,可以借助Query注解来屏蔽某个字段。

    package com.sss.notes.repository
    
    import com.sss.notes.pojo.Soup
    import org.springframework.data.mongodb.repository.MongoRepository
    import org.springframework.data.mongodb.repository.Query
    
    interface SoupMongoRepository : MongoRepository<Soup, String> {
        /**
         *  如果这样写的话,方法随意命名
         *  @Query注解标记之后,Springboot会根据 @Query中的内容自动生成查询实现方法
         *  value 代表查询条件 ,此处使用了正则表达式,查找以startStr开头的鸡汤,?0表示方法中的第一个参数startStr,依次类推
         *  fields 代表查询返回的字段,0为不返回,反之1为返回
         *
         */
        @Query(value = "{ 'name':{\$regex:/^?0/}}", fields = "{ 'id' : 0 }")
        fun findAllByNameStartStr(startStr: String):List<Soup>?
    
    }
    
  • 重新运行项目,测试后,id字段就没有值了

1645850367(1).jpg
  • 还可以使用MongoRepository中自带的方法来实现该查询,使用ExampleMatcher,修改SoupController,重新运行项目

    package com.sss.notes.controller
    
    import com.sss.notes.pojo.Soup
    import com.sss.notes.repository.SoupMongoRepository
    import org.springframework.data.domain.Example
    import org.springframework.data.domain.ExampleMatcher
    import org.springframework.http.HttpStatus
    import org.springframework.web.bind.annotation.*
    
    /**
     * 使用@RestController 标记 SoupController
     * 让Springboot 知道这是一个处理http请求的类
     * @RequestMapping:配置url映射
     */
    @RequestMapping("v1/test/")
    @RestController
    class SoupController(private val soupRepository: SoupMongoRepository) {
    
    //    @ResponseStatus(HttpStatus.OK)
    //    @GetMapping("/soup")
    //    fun getSoup(@RequestParam("start") startStr: String): List<Soup>? {
    //        return soupRepository.findAllByNameStartingWith(startStr)
    //    }
    
        @ResponseStatus(HttpStatus.OK)
        @GetMapping("/soup")
        fun getSoup(@RequestParam("start") startStr: String): List<Soup>? {
            val soup = Soup(name = startStr)
            //使用ExampleMatcher 必须添加忽略路径_class,否则将会搜索不到结果
            //_class是springboot 保存MongoDB数据时,自动增加的一个字段,其内容为实体类的包路径,
            //其目的主要是为了适配多态的场景下能够准确的找到初始化的类
            //当然在实体类包路径移动后也可以正常工作,最终以查询时实际传入的泛型为实例化参照
            val exampleMatcher =
                ExampleMatcher.matching()
                    .withMatcher("name", ExampleMatcher.GenericPropertyMatchers.startsWith())
                    .withIgnorePaths("_class")
            val example = Example.of(soup,exampleMatcher)
            return soupRepository.findAll(example)
        }
    }
    

实现了相同的效果


1645851263(1).jpg

注意事项

在使用Koltin+SpringBoot时,要保证包中的类全部是.kt的kotlin文件,否则会出现ClassNotFonud,加了注解类缺扫不到等异常,可以借助IDEA在如下所示的方法查看项目中已生成的Bean

1645851472(1).jpg

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容