2

我使用 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

}

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

1 回答 1

1

不同之处在于将注释应用于类主体中定义的属性与在主构造函数中声明的注释属性有何不同。

请参阅:语言参考中的注释使用站点目标:

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

如果不指定使用站点目标,则根据@Target正在使用的注解的注解选择目标。如果有多个适用目标,则使用以下列表中的第一个适用目标:

  • param
  • property
  • field

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

abstract class AbstractEntity(
    @get:JsonProperty("_id")
    val id: String? = null,
    @get:JsonProperty("_rev")
    val revision: String? = null
)
于 2017-08-16T14:37:58.683 回答