Kotlin之data与mybatis映射的坑

2019-10-09 15:08:37 浏览数 (1)

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

1 依赖配置

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

代码语言:javascript复制
 <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方式将文件打包进去,具体的根据个人需求来做,下面的是例子

代码语言:javascript复制
 <build>
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*</include>
                </includes>
            </resource>
        </resources>
  </build>

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

代码语言:javascript复制
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

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

代码语言:javascript复制
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就更加单一

代码语言:javascript复制
<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查询数据然后与数据映射通过反射集合

复杂数据结构

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

代码语言:javascript复制
 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这个方式,代码如下

代码语言:javascript复制
 <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我们不细说,自己慢慢体会,遇到了可以做个参考

关注阅读更多关注阅读更多
代码语言:javascript复制
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>

0 人点赞