Kotlin突变子

Kotlin突变子,kotlin,ektorp,Kotlin,Ektorp,我使用Ektorp作为CouchDB“ORM”,但这个问题似乎比那个更一般。有人能解释一下两者的区别吗 @JsonInclude(NON_NULL) abstract class AbstractEntity( id: String?, revision: String? ) { @JsonProperty("_id") val id: String? = id @JsonProperty("_rev") val revisio

我使用Ektorp作为CouchDB“ORM”,但这个问题似乎比那个更一般。有人能解释一下两者的区别吗

@JsonInclude(NON_NULL)
abstract class AbstractEntity(
        id: String?,
        revision: String?
) {

    @JsonProperty("_id")
    val id: String? = id

    @JsonProperty("_rev")
    val revision: String? = revision

}

?

对于第一个案例,Ektorp没有投诉,但对于第二个案例,Ektorp说:

org.ektorp.InvalidDocumentException: Cannot resolve revision mutator in class com.scherule.calendaring.domain.Meeting

    at org.ektorp.util.Documents$MethodAccessor.assertMethodFound(Documents.java:165)
    at org.ektorp.util.Documents$MethodAccessor.<init>(Documents.java:144)
    at org.ektorp.util.Documents.getAccessor(Documents.java:113)
    at org.ektorp.util.Documents.getRevision(Documents.java:77)
    at org.ektorp.util.Documents.isNew(Documents.java:85)
我得到:

org.ektorp.DbAccessException: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "_id" (class com.scherule.calendaring.domain.Meeting), not marked as ignorable
问题是第一个代码段与第二个代码段有什么不同?在第一种情况下,Ektorp“认为”有一个变异子,但在第二种情况下没有

以下是Ektorp在定位方法(setId、setRevision)时使用的代码片段

私有方法findMethod(类clazz,字符串名,
类…参数)引发异常{
对于(方法me:clazz.getDeclaredMethods()){
if(me.getName().equals(name)
&&me.getParameterTypes().length==parameters.length){
me.setAccessible(true);
还我;
}
}
return clazz.getSuperclass()!=null?findMethod(
getSuperclass(),名称,参数):null;
}

区别在于对类主体中定义的属性应用注释与对主构造函数中声明的属性进行注释的方式不同

参见:在语言参考中:

在注释属性或主构造函数参数时,有多个Java元素是从相应的Kotlin元素生成的,因此注释在生成的Java字节码中有多个可能的位置

如果未指定使用站点目标,则将根据所用批注的
@target
批注选择目标。如果存在多个适用目标,则使用以下列表中的第一个适用目标:

  • param
  • 属性
  • 字段
因此,当您注释在主构造函数中声明的属性时,默认情况下,是构造函数参数获取Java字节码中的注释。要改变这一点,请显式指定注释目标,例如:

abstract class AbstractEntity(
    @get:JsonProperty("_id")
    val id: String? = null,
    @get:JsonProperty("_rev")
    val revision: String? = null
)

虽然这解决了var的问题,但这还不能解释为什么在构造函数中使用val字段时不会产生“无法解析修订变量”异常(即使使用了您的修复)。。。有什么想法吗?逻辑上,val不应该工作,因为它不会创建setter。。。但它确实(当用作字段时,而不是在构造函数声明中使用时,这会使事情变得更奇怪)我没有使用过这个工具,因此我只能假设它检测到一个构造函数,它可以使用更新的属性值来创建一个新对象,而不是设置可变属性,这就足够了。但它的工作方式正好相反——它只在我使用字段声明(在构造函数之外)时起作用——但仍然是“val”。无论如何,这一定是ektorp lib实现的更多细节。。。
org.ektorp.DbAccessException: com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "_id" (class com.scherule.calendaring.domain.Meeting), not marked as ignorable
private Method findMethod(Class<?> clazz, String name,
                Class<?>... parameters) throws Exception {
            for (Method me : clazz.getDeclaredMethods()) {
                if (me.getName().equals(name)
                        && me.getParameterTypes().length == parameters.length) {
                    me.setAccessible(true);
                    return me;
                }
            }
            return clazz.getSuperclass() != null ? findMethod(
                    clazz.getSuperclass(), name, parameters) : null;
        }
abstract class AbstractEntity(
    @get:JsonProperty("_id")
    val id: String? = null,
    @get:JsonProperty("_rev")
    val revision: String? = null
)