Primavera mongo único campo de escritura

Kirill Simonov:

Tengo una clase abstracta que describe un documento mongo. Podría haber diferentes implementaciones de esta clase que necesitan para sustituir un método abstracto. Aquí es un ejemplo simplificado:

@Document
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public abstract class Entity {

    @Id
    private ObjectId id;

    abstract String getSomething();
}

Quiero getSomething()que se escriben en el documento como un campo de cadena. Pero no quiero volver a leerlo .

He intentado utilizar la @AccessTypeanotación:

@AccessType(AccessType.Type.PROPERTY)
abstract String getSomething();

Pero cuando estoy leyendo este documento de la db, primavera lanza UnsupportedOperationException: No accessor to set property. Se está tratando de encontrar un regulador para este campo, pero no quiero definir un colocador para que - el método puede devolver un valor calculado y no debe haber ninguna posibilidad de cambiarlo. Aunque una incubadora vacía podría ayudar, se parece más a una solución, y yo trataría de evitarlo.

Así que estoy preguntando si hay una manera de saltarse esta propiedad en particular cuando se lee de la base de datos? Algo opuesto a la @Transientanotación. O similares a los @JsonIgnorede la biblioteca de Jackson.

Kirill Simonov:

Sorprendentemente, no existe una solución fácil de hacer solamente una escritura campo.

A pesar de que la creación de una incubadora vacía resolvería el problema, siento que rompe el principio de mínima sorpresa : si tiene un setter, se esperaría que establece un valor.

Así que decidí crear mi propia @WriteOnlyanotación y utilizarlo para ignorar los campos no quiero leer desde el PP:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface WriteOnly {
}

Para utilizarlo tendrá que extender una AbstractMongoEventListener :

@Service
public class WriteOnlyListener extends AbstractMongoEventListener<Entity> {

    @Override
    public void onAfterLoad(AfterLoadEvent<Entity> event) {
        Document doc = event.getDocument();
        if (doc == null) return;
        for (Field field: getWriteOnly(event.getType(), Class::getDeclaredFields)) {
            doc.remove(field.getName());
        }
        for (Method method: getWriteOnly(event.getType(), Class::getDeclaredMethods)) {
            doc.remove(getFieldName(method.getName()));
        }
    }

    private <T extends AccessibleObject> List<T> getWriteOnly(Class<?> type, 
                                                              Function<Class<?>, T[]> extractor) {
        List<T> list = new ArrayList<>();
        for (Class<?> c = type; c != null; c = c.getSuperclass()) {
            list.addAll(Arrays.stream(extractor.apply(c))
                    .filter(o -> o.isAnnotationPresent(WriteOnly.class))
                    .collect(Collectors.toList()));
        }
        return list;
    }

    private static String getFieldName(String methodName) {
        return Introspector.decapitalize(methodName.substring(methodName.startsWith("is") ? 2 : 
                    methodName.startsWith("get") ? 3 : 0));
    }

}

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=331231&siteId=1
Recomendado
Clasificación