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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容