【问题标题】:Spring Data Models - Abstract Base Classes With Lombok?Spring Data Models - 带有 Lombok 的抽象基类?
【发布时间】:2019-06-17 16:58:57
【问题描述】:

我有一个关于 Spring Data 模型的设计问题(在我的具体案例中是 Spring Data Mongo)。

我的要求:

  • 我想强制所有聚合根使用字符串作为 ID 的数据类型。
  • 我想强制将空字符串或空格的 ID 编组为 null(因此 mongo 会为这些 ID 生成密钥)
  • 我想最终为每个聚合根添加标准审计属性。
  • 我想为模型使用 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”
  • 需要手动添加一个构造函数来包含超级字段,这否定了 Lombok 的一些好处。

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

public interface PersistentDocument extends Serializable {

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

    .
    . Setters/Getters for audit fields
}

这稍微好一点,但每个后代文档都需要正确实现将空格转换为 null 并注释审计字段的逻辑。

我真的很想看看其他人在做什么?

【问题讨论】:

    标签: spring-data spring-data-mongodb


    【解决方案1】:

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

    为了利用 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();
    }
    
    

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

    模型对象只是定义属性并利用 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)
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-26
      • 1970-01-01
      • 2020-03-12
      • 2018-07-11
      • 1970-01-01
      相关资源
      最近更新 更多