专栏首页大话swiftKotlin之data与mybatis映射的坑

Kotlin之data与mybatis映射的坑

Kotlin作为走在替代Java的路上可谓是越走越快,简洁的语法,现代化的人性化语法,总之作为Google大力推荐的Android第一开发语言越来越受到大家关注,而Spring出了针对Kotlin的快速入门的Springboot版本的入门,今天我们就来看看怎么在mybatis上使用Kotlin吧

1 依赖配置

自不必说都是基于pom的我们需要添加Kotlin依赖 mybatis依赖,MySQL依赖这些基本的依赖

 <dependencies>
       
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.35</version>
        </dependency>
      
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-test</artifactId>
            <version>${kotlin.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.1.0</version>
        </dependency>

    </dependencies>

    <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <version>${kotlin.version}</version>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>compile</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                    <execution>
                        <id>test-compile</id>
                        <phase>test-compile</phase>
                        <goals>
                            <goal>test-compile</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <jvmTarget>1.8</jvmTarget>
                </configuration>
            </plugin>
        </plugins>
    </build>

这里说一点对于springboot打包是resource文件有缺失的可以参考上文方式中的include方式将文件打包进去,具体的根据个人需求来做,下面的是例子

 <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
        </resources>
  </build>

我们配置了依赖需要配置环境属性变量---resources文件夹下新建application.yml将mybatis MySQL的基本配置进行配置

server:
  port: 8080
spring:
  freemarker:
    suffix: .ftl                                 # 设置模板后缀名
    content-type: text/html                      # 设置文档类型
    charset: UTF-8                               # 设置页面编码格式
    cache: false                                 # 设置页面缓存
    template-loader-path: classpath:/templates   # 设置ftl文件路径
    check-template-location: true
  mvc:
      static-path-pattern: /static
  datasource:
    url: jdbc:mysql://localhost:3306/app?useUnicode=true&characterEncoding=utf-8
    username: root
    password: 12345678
mybatis:
  mapper-locations: classpath:mybatis/mapper/*.xml
logging:
  level:
    app:
      mapper: debug

mapper与model映射

单一model与mapper映射

什么叫做单一的映射也就是说model中只有基本的数据类型没有那些自定的model如:Person这个data class吧,内部属性只有 id age name

我们以一个电影的表示模型为例来实现

data class Movie(val id: Int = 0,
 val title: String, 
 var brief: String?,
  var directors: String? = null, 
  var actors: String? = null,
   var categoryId: Int = 0,
   val pic:String,
   val parentCategoryId:Int = 0) 

看似属性成员一大堆,但是由于都是基本数据类型因此它就是单一的模型,对应的mapper就十分单一,查询的sql就更加单一

<resultMap id="movie" type="app.entity.Movie">
        <result property="id" column="ic"/>
        <result column="title" property="title"/>
        <result column="brief" property="brief"/>
        <result column="directors" property="directors"/>
        <result column="actors" property="actors"/>
        <result column="category_id" property="categoryId"/>
        <result column="pic" property="pic"/>
        <result column="parent_category_id" property="parentCategoryId"/>
    </resultMap>
    
    
 <select id="indexMovie" resultMap="movie">
        <bind name="off_set" value="(page-1)*pageSize"></bind>
        select * from movie
        <choose>
            <when test="category==1"></when>
            <otherwise>
                <where>
                    <choose>
                        <when test="parentId ==0">
                            parent_category_id = #{category}
                        </when>
                        <otherwise>
                            category_id = #{category}
                        </otherwise>
                    </choose>
                </where>
            </otherwise>
        </choose>
        <if test="page>0">
            limit #{off_set},#{pageSize}
        </if>

    </select>

上文中看似十分复杂的动态查询,其实逻辑十分简单:

①定义model对应的class类映射

② 动态sql查询数据然后与数据映射通过反射集合

复杂数据结构

我们以一个带有二级菜单的作为实例

 data class Menu(val id: Int) {
    val name: String? = null
    val status: Int = 0
    val parent: Int = 0
    val link: String? = null
}

data class MainMenu(val id: Int) {
    val name: String? = null
    val status: Int = 0
    val parent: Int = 0
    val link: String? = null
    open var subs: List<Menu> = mutableListOf()
}

上面是一个稍微复杂的数据结构,对应的mapper映射会要想表达出MainMenu的方式需要用到collection这个方式,代码如下

 <resultMap id="menu" type="app.entity.MainMenu">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="status" property="status"/>
        <result column="parent" property="parent"/>
        <result column="link" property="link"/>
        <collection property="subs" ofType="app.entity.Menu">
            <id column="child_id" property="id"/>
            <result column="child_name" property="name"/>
            <result column="child_status" property="status"/>
            <result column="child_parent" property="parent"/>
            <result column="child_link" property="link"/>
        </collection>
    </resultMap>

无论是单一还是负责的映射模型定义,我们发现我们给的都是有构造函数的模型名义而在Java中使用话我们的模型定义往往是不需要指定构造函数的。然鹅我们能否在Kotlin也这么定义呢?加入你采用data class的方式那么你就必须要有构造函数针对数据库有id的方式最好的建议就是基于id的唯一构造参数定义模型(如我们文中的)

使用了collection方式踩坑,我们在举个associate的方式将主要的坑踩完,内ring我们不细说,自己慢慢体会,遇到了可以做个参考

关注阅读更多
data class Resource(var  id: Int) {
    constructor():this(id=0)
    var  status: Int = 0
    var link: String?=null
    var movieId: Int = 0
    var type:ResourceType? = null
}

data class ResourceType(val id:Int = 0) {
    var type: String  =""
}


 <resultMap id="resource" type="app.entity.Resource">
            <id column="id" javaType="java.lang.Integer"/>
        <result column="status" property="status"/>
        <result column="link" property="link"/>
        <result column="movie_id" property="movieId"/>
        <association property="type" javaType="app.entity.ResourceType">
            <id column="type_id" property="id"/>
            <result property="type" column="type_type"/>
        </association>
    </resultMap>

    <select id="resourceByMovieId" resultMap="resource">
        select  app_resource.*, app_resource_type.id type_id, app_resource_type.type type_type from app_resource , app_resource_type where movie_id = #{movieId} and app_resource_type.id = app_resource.type
    </select>

本文分享自微信公众号 - 大话swift(gh_ca2266b7cab0),作者:YuLongLi

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 科普一下程序运行时内存分配

    代码段(code segment/text segment )通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通...

    大话swift
  • Opaque Types 之 some

    在看some之前我们肯定要提一个沸沸扬扬的主角SwitUI--这个OS实时预览的大神。里面可谓是打出透露这some这个人民币玩家……说的有点偏题啦。先来看个小例...

    大话swift
  • macOS QuickLook 之 flutter dart查看

    macOS的QuickLook可谓是便利,这次借助flutter之际开发一款QuickLook小插件

    大话swift
  • Navigation——Fragment创建新的实例问题详解

    上一篇文章Navigation——Fragment创建新的实例问题,我们简述了我们在使用Navigation遇到的Fragment创建新的实例的问题。接下来,我...

    Demo_Yang
  • 文本数据的机器学习自动分类方法(上)

    【编者按】:随着互联网技术的迅速发展与普及,如何对浩如烟海的数据进行分类、组织和管理,已经成为一个具有重要用途的研究课题。而在这些数据中,文本数据又是数量最大的...

    小莹莹
  • MyBatis 多表操作

      关系数据库中第一个表中的单个行只可以与第二个表中的一个行相关,且第二个表中的一个行也只可以与第一个表中的一个行相关。

    Demo_Null
  • Mybatis创建dao接口、Mybatis主配置文件、创建映射配置文件

    即上述创建的IUserDao.xml文件进行约束和配置 其实就是Mapper的约束啦

    韦恩少爷的背
  • 小程序支付详解+源码(客户端+服务端)

    小程序的支付调通,和大家分享下(坑) 包括小程序端、java服务器端 和其他方式的微信支付方式区别不大,也都需要经过统一下单、支付结果通知(回调),具体流程如...

    极乐君
  • Linux系统利用cp命令实现强制覆盖功能的方法

    cp命令用来将一个或多个源文件或者目录复制到指定的目的文件或目录。它可以将单个源文件复制成一个指定文件名的具体的文件或一个已经存在的目录下。cp命令还支持同时复...

    砸漏
  • thinkPHP5框架接口写法简单示例

    更多关于thinkPHP相关内容感兴趣的读者可查看本站专题:《ThinkPHP入门教程》、《thinkPHP模板操作技巧总结》、《ThinkPHP常用方法总结》...

    砸漏

扫码关注云+社区

领取腾讯云代金券