2017-08-16 40 views
2

我使用Ektorp作为CouchDB“ORM”,但这个问题似乎比这更一般。有人能解释什么是Kotlin mutators

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

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

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

} 

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

之间的区别?

对于第一种情况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) 

此外,如果我做

@JsonInclude(NON_NULL) 
abstract class AbstractEntity(
     @JsonProperty("_id") 
     var id: String? = null, 
     @JsonProperty("_rev") 
     var revision: String? = null 
) 

我得到:

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)时似乎使用的代码片段。

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; 
     } 

回答

1

的差别是如何注释到在类体内定义的属性的应用程序从注释在主构造声明的属性不同。

参见:Annotation Use-site Targets语言参考:

当你标注的属性或主构造参数,存在从相应科特林元件产生的多个Java元素,并且因此多个可能的位置用于生成的Java字节码中的注释。

如果不指定使用站点内的目标,目标是根据@Target注解注释的选择使用。如果有多个适用对象,从下面的列表中的第一个适用的目标时:

  • param
  • property
  • field

所以,当你注释中声明的属性一个主构造函数,它是构造函数参数,默认情况下获取Java字节码中的注释。要改变的是,明确指定注释目标,例如:

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

虽然这解决了与VAR的问题这并没有解释为什么使用* VAL *场不会产生“无法解析修订增变”的异常,同时使用它在构造函数中(即使有你的修复)......有什么想法?逻辑会建议val不应该工作,因为它不会创建setter ...但它确实(当作为一个字段使用,而不是在构造函数声明中,这使得事情变得更奇怪) – kboom

+0

我没有使用这个工具,所以我只能假设它检测到一个构造函数,它可以用来创建一个新的对象与更新的属性值而不是设置可变属性,这就足够了。 – hotkey

+0

除了它反过来 - 它只适用于如果我使用字段声明(外部构造函数) - 但仍然“val”。无论如何,对,这必须是更多的ektorp lib实现细节... – kboom