Java Pojos - Setter-Call(触及字段)检测

问题描述 投票:0回答:1

Pojo 通常用作模型/DTO,用于将数据插入/更新到数据库中。

它们需要经过验证(使用验证器)以确保它们仅包含用例的预期字段:

  • 插入(必须验证并插入所有字段)
  • 更新(仅必须验证更改/修改的字段并将其更新到数据库中)

为了实现这一点,如果 Java 语言已经包含跟踪 pojo 中“修改”的机制,将会很有帮助。字段的“修改”将是:

  • 已调用字段的 setter。

有人可以帮助我解决这样的 setter-call 检测,并使用尽可能少的样板吗?


这里是我如何使用样板解决这个问题的示例,通过让 Pojo 扩展一个公共类:

public abstract class AbstractDTO {

    private Map<String, Object> modifiedFields = new HashMap<>();

    public AbstractDTO() {
    }

    @JsonIgnore
    @XmlTransient
    protected void setAt(String key, Object value) {
        this.modifiedFields.put(key, value);
    }

    @JsonIgnore
    @XmlTransient
    public void resetModifiedFields() {
        this.modifiedFields.clear();
    }

    @JsonIgnore
    @XmlTransient
    public Map<String, Object> getModifiedFields() {
        return this.modifiedFields;
    }
}

实现:

public class Product extends AbstractDTO {

    private Long productId;

    public Long getProductId() {
        return this.productId;
    }

    public void setProductId(Long productId) {
        this.productId = productId;
        this.setAt("productId", productId);
    }

这样我现在可以检查修改的字段:

boolean isModified = pojo.getModifiedFields().containsKey(field.getName());

我还找到了一种借助反射的额外方法(这有助于我的设置者只需要在父级中调用

touch()
方法:

 public void touch () {
        StackWalker walker = StackWalker.getInstance(RETAIN_CLASS_REFERENCE);
        StackWalker.StackFrame frame = walker.walk(frames -> {
            Iterator<StackWalker.StackFrame> it = frames.iterator();
            StackWalker.StackFrame a = it.next();
            return it.next();
        });
        String methodName = frame.getMethodName();
        try {
            String withoutSet = methodName.substring(3);
            String fieldname = Character.toLowerCase(withoutSet.charAt(0)) + withoutSet.substring(1);
            Class<?> declaringClass = frame.getDeclaringClass();
            Field field = frame.getDeclaringClass().getDeclaredField(fieldname);

            String getterName = "get" + withoutSet;
            Method getter = declaringClass.getMethod(getterName);
            Object value = getter.invoke(this);
            this.modifiedFields.put(field.getName(), value);
        } catch (Exception e) {
            throw new RuntimeException("unable to find field!");
        }
    }

如果有人知道如何在调用 setter 时自动(在幕后)调用此“touch()”函数,这也会有所帮助。

java validation dto pojo
1个回答
1
投票

我认为你心里有类似Javers的想法。请注意,更改跟踪库通常要求您有权访问对象的原始版本,因此请确保保留该版本而不进行更改。

© www.soinside.com 2019 - 2024. All rights reserved.