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
说明:
- 为case class生成默认的无参构造函数
- 为case class生成所有字段的get/set方法(这是通过在编译期间为所有字段增加
@BeanProperty
来实现的) - 该注解强制在case class上才能使用,编译期类型安全,如果有不支持的类型,编译不会通过
- 该注解还会校验case class的字段是否已经有
@BeanProperty
,不会重复放置 - 如果case class已经存在无参构造,则编译不通过
- 该注解支持case class的柯里化,但是柯里化参数块中的
b
参数需要指定为val
或var
(如: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