当前位置: 代码迷 >> 综合 >> Scala 集成Mybatis和SpringBoot改进
  详细解决方案

Scala 集成Mybatis和SpringBoot改进

热度:125   发布时间:2023-09-23 10:03:50.0

Mybatis构造对象缺少默认的无参构造?

通常Scala是这么定义实体类或领域对象的

case class A(a: Int, b: String)

但是这个类在Mybatis中是无效的,因为Mybatis通过反射无参构造来生成对象。

1.一种方法是为样例类定义副构造函数

case class A(a: Int, b: String) {
    def this()= {
    this(0, null)}
}

以上如果还需要get/set方法,还应该增加@BeanProperty注解在字段上

2.第二种是不再使用样例类

// 主构造是需2个参数的,这种定义如果对象有很多字段,但是数据只返回部分,则反射仍然失败
// 如果对象需要Java的get/set方法,还需要未每个字段添加@BeanProperty注解
class A(val a: Int, val b: String) {
    //所以还是需要提供一个无参构造用于反射构造一个对象def this()= {
    this(0, null)}
}class A {
    //生成Java的get/set方法@BeanProperty var a: Int@BeanProperty var b: String//定义副构造,因为此时主构造就是无参的def this(a: Int, b: String)= {
    this.a=athis.b=b}
}

Spring获取字段失败?

因为case class没有Java的get/set方法,字段需要加@BeanProperty注解

改进的兼容方式

scala2.13 导入库

    implementation 'io.github.jxnu-liguobin:scala-macro-tools_2.13:0.3.2'

增加gradle编译参数

tasks.withType(ScalaCompile) {scalaCompileOptions.additionalParameters = ["-Ymacro-annotations"]
}

使用宏注解@JavaCompatible在case class定义上

  @JavaCompatible case class AddInfo(id: Int,uid: Int,content: String,from: Int,from_group: Int,`type`: Int,remark: String,href: String,read: Int,time: String,user: User //使用@JavaCompatible注解时,嵌套对象User不能定义在同一个object中。(很多Scala喜欢将领域对象都放在一个文件中,但是宏处理不了这种情况,会出现找不到或编译器的循环依赖错误))

@JavaCompatible说明:

  1. 为case class生成默认的无参构造函数
  2. 为case class生成所有字段的get/set方法(这是通过在编译期间为所有字段增加@BeanProperty来实现的)
  3. 该注解强制在case class上才能使用,编译期类型安全,如果有不支持的类型,编译不会通过
  4. 该注解还会校验case class的字段是否已经有@BeanProperty,不会重复放置
  5. 如果case class已经存在无参构造,则编译不通过
  6. 该注解支持case class的柯里化,但是柯里化参数块中的b参数需要指定为valvar(如:case class A(a: Int)(val b: String)),否则由于编译器将其视为private[this],注解会忽略这种字段。(应该改成编译期报错,这种一般是service用于隐式参数,不应该这样用)

我们的文档在 https://bitlap.org/lab/smt/java-compatible
我们源码实现 https://github.com/jxnu-liguobin/scala-macro-tools

  相关解决方案