2017-08-16 28 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