我对Spring Data(在我的具体情况下为Spring Data Mongo)中的模型有一个设计问题。
我的要求:
我已经看到了几个使用抽象基类的示例:
@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;
}
有两个问题:
作为替代方案,我开始使用接口来强制执行数据类型标准:
public interface PersistentDocument extends Serializable {
void setId(String id);
public String getId();
.
. Setters/Getters for audit fields
}
这好一点,但是每个后代文档都可以正确实现将空格转换为null并注释审核字段的逻辑。
我真的很想知道别人在做什么吗?
答案 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)
我希望这对其他人有帮助,我真的很想看看其他人如何解决类似的问题。