Spring数据模型-具有Lombok的抽象基类?

时间:2019-01-24 02:22:09

标签: spring-data spring-data-mongodb

我对Spring Data(在我的具体情况下为Spring Data Mongo)中的模型有一个设计问题。

我的要求:

  • 我要强制所有聚合根都使用String作为ID的数据类型。
  • 我想强制将空字符串或空格的ID编组为null(因此mongo会为它们生成密钥)
  • 我最终希望为每个聚合根添加标准审核属性。
  • 我想将Lombok用于模型以减少样板。

我已经看到了几个使用抽象基类的示例:

@SuperBuilder
public abstract class PersistentDocument implements Serializable {

    private static final long serialVersionUID = 1L;

    private String id;
    public void setId(String id) {
        if (!StringUtils.hasText(getId())) {
            this.id = null;
        } else {
            this.id = id;
        }
    }
    public String getId() {
        this.id;
    }
    .
    .
    auditing fields...etc.
}

后代:

@Data
@SuperBuilder
public class UnitOfMeasure extends PersistentDocument {

    private static final long serialVersionUID = 1L;
    private String name;
    private String description;
}

有两个问题:

  • 这取决于实验“ SuperBuilder”
  • 需要手动添加一个构造函数以包含super的字段,这抵消了Lombok的某些好处。

作为替代方案,我开始使用接口来强制执行数据类型标准:

public interface PersistentDocument extends Serializable {

    void setId(String id);
    public String getId();

    .
    . Setters/Getters for audit fields
}

这好一点,但是每个后代文档都可以正确实现将空格转换为null并注释审核字段的逻辑。

我真的很想知道别人在做什么吗?

1 个答案:

答案 0 :(得分:0)

我想继续回答自己的问题:

为了利用Lombok来处理样板代码,并强制所有聚合根都遵循相同的ID和审计属性约定:

我决定使用该界面:

@Document
public interface PersistentDocument extends Serializable {

    void setId(String id);
    String getId();

    @CreatedDate
    @ReadOnlyProperty
    void setCreatedTimestamp(LocalDateTime timestamp);
    LocalDateTime getCreatedTimestamp();

    @LastModifiedDate
    void setLastModifiedTimestamp(LocalDateTime timestamp);
    LocalDateTime getLastModifiedTimestamp();

    @Version
    void setVersion(Long version);
    Long getVersion();
}

关于界面的一个非常好的但微妙的事情是,spring数据注释可以应用在界面上而不是模型上。这不会完全从模型中删除注释(例如,您仍然需要使用索引注释模型字段)。

模型对象仅定义属性并利用Lombok:

@Data
@Builder
public class UnitOfMeasure implements PersistentDocument {

    private static final long serialVersionUID = 1L;

    private String id;

    @Indexed(unique=true)
    private String code;
    private String name;
    private String description;

    //Audit Columns
    private LocalDateTime createdTimestamp;
    private LocalDateTime lastModifiedTimestamp;
    private Long version;
}

要解决空字符串/空白持久性ID的卫生问题,

我能够通过自己的实现扩展SimpleMongoRepository:

public class PersistentDocumentMongoRepository<T extends PersistentDocument> extends SimpleMongoRepository <T, String> {

    public PersistentDocumentMongoRepository(MongoEntityInformation<T, String> metadata, MongoOperations mongoOperations) {
        super(metadata, mongoOperations);
    }

    @Override
    public <S extends T> S save(S entity) {
        sanitizeId(entity);
        return super.save(entity);
    }


    @Override
    public <S extends T> List<S> saveAll(Iterable<S> entities) {

        Assert.notNull(entities, "The given Iterable of entities not be null!");
        Streamable.of(entities).stream().forEach(this::sanitizeId);
        return super.saveAll(entities);
    }


    @Override
    public <S extends T> S insert(S entity) {
        sanitizeId(entity);
        return super.insert(entity);
    }

    @Override
    public <S extends T> List<S> insert(Iterable<S> entities) {
        Assert.notNull(entities, "The given Iterable of entities not be null!");
        Streamable.of(entities).stream().forEach(this::sanitizeId);
        return super.insert(entities);
    }

    private void sanitizeId(T entity) {
        if (!StringUtils.hasText(entity.getId())) {
            entity.setId(null);
        }
    }
}

最后告诉Spring Data使用自定义存储库实现:

@EnableMongoAuditing
@EnableMongoRepositories(repositoryBaseClass=PersistentDocumentMongoRepository.class)

我希望这对其他人有帮助,我真的很想看看其他人如何解决类似的问题。