Spring框架:一文读懂SpringData中的各类组件的实现
SpringData封装了很多三方软件的调用组件,给程序员很多便利,例如:Redis,Mongodb,ElasticSearch。大部分都是使用模板模式实现,读完之后可以根据业务需要自定需要的调用接口,屏蔽底层实现。
一、简介
1.1 引入
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-elasticsearch</artifactId>
<version>5.2.1</version>
</dependency>
1.2 使用方式(官方用例)
// Object Mapping : 注解方式关联Es的字段
@Data
@Builder
@Document(indexName = "conference-index")
public class Conference {
private @Id String id;
private String name;
private @Field(type = Date) String date;
private GeoPoint location;
private List<String> keywords;
}
// 自定义repository,用于指定泛型
interface ConferenceRepository extends ElasticsearchRepository<Conference, String> {}
// 调用
class ApplicationConfiguration {
@Autowired ElasticsearchOperations operations;
@Autowired ConferenceRepository repository;
@PreDestroy
public void deleteIndex() {
// 删除信息
operations.indexOps(Conference.class).delete();
}
@PostConstruct
public void insertDataSample() {
operations.indexOps(Conference.class).refresh();
// Save data sample
var documents = Arrays.asList(
Conference.builder().date("2014-11-06").name("Spring eXchange 2014 - London")
.keywords(Arrays.asList("java", "spring")).location(new GeoPoint(51.500152D, -0.126236D)).build(), //
Conference.builder().date("2014-12-07").name("Scala eXchange 2014 - London")
.keywords(Arrays.asList("scala", "play", "java")).location(new GeoPoint(51.500152D, -0.126236D)).build(), //
Conference.builder().date("2014-11-20").name("Elasticsearch 2014 - Berlin")
.keywords(Arrays.asList("java", "elasticsearch", "kibana")).location(new GeoPoint(52.5234051D, 13.4113999))
.build(), //
Conference.builder().date("2014-11-12").name("AWS London 2014").keywords(Arrays.asList("cloud", "aws"))
.location(new GeoPoint(51.500152D, -0.126236D)).build(), //
Conference.builder().date("2014-10-04").name("JDD14 - Cracow").keywords(Arrays.asList("java", "spring"))
.location(new GeoPoint(50.0646501D, 19.9449799)).build());
// 新增条数
repository.saveAll(documents);
}
}
二、详细实现
2.1 总结
- 多次使用模板方法来对抽象
- SimpleElasticsearchRepository:Es调用接口及实现类,实现自动刷新
- **DocumentOperations **:封装 ObjectMapping 和ducument 的转换,
2.2 ElasticsearchRepository 模板:定义会使用的接口
public interface ElasticsearchRepository<T, ID> extends PagingAndSortingRepository<T, ID>, CrudRepository<T, ID> {
Page<T> searchSimilar(T entity, @Nullable String[] fields, Pageable pageable);
<S extends T> S save(S entity, @Nullable RefreshPolicy refreshPolicy);
<S extends T> Iterable<S> saveAll(Iterable<S> entities, @Nullable RefreshPolicy refreshPolicy);
void deleteById(ID id, @Nullable RefreshPolicy refreshPolicy);
void delete(T entity, @Nullable RefreshPolicy refreshPolicy);
void deleteAllById(Iterable<? extends ID> ids, @Nullable RefreshPolicy refreshPolicy);
void deleteAll(Iterable<? extends T> entities, @Nullable RefreshPolicy refreshPolicy);
void deleteAll(@Nullable RefreshPolicy refreshPolicy);
}
2.3 SimpleElasticsearchRepository 实现类:自动刷新
public class SimpleElasticsearchRepository<T, ID> implements ElasticsearchRepository<T, ID> {
protected ElasticsearchOperations operations;
protected IndexOperations indexOperations;
protected Class<T> entityClass;
protected ElasticsearchEntityInformation<T, ID> entityInformation;
public <S extends T> Iterable<S> saveAll(Iterable<S> entities) {
Assert.notNull(entities, "Cannot insert 'null' as a List.");
IndexCoordinates indexCoordinates = this.getIndexCoordinates();
// 自动刷新
this.executeAndRefresh((operations) -> {
// 传入 DocumentOperation 操作
return operations.save(entities, indexCoordinates);
});
return entities;
}
}
2.4 DocumentOperations 接口:Es的具体实现接口
public interface DocumentOperations {
<T> T save(T entity);
<T> T save(T entity, IndexCoordinates index);
...
}
2.5 DocumentOperations Es的具体链接:Es的ObjectMappingDocument,Sql组装。及底层查询
public abstract class AbstractElasticsearchTemplate implements ElasticsearchOperations, ApplicationContextAware {
protected ElasticsearchConverter elasticsearchConverter;
protected EntityOperations entityOperations;
@Nullable
protected EntityCallbacks entityCallbacks;
@Nullable
protected RefreshPolicy refreshPolicy;
protected RoutingResolver routingResolver;
public <T> T save(T entity, IndexCoordinates index) {
Assert.notNull(entity, "entity must not be null");
Assert.notNull(index, "index must not be null");
// Object Document 映射
T entityAfterBeforeConvert = this.maybeCallbackBeforeConvert(entity, index);
IndexQuery query = this.getIndexQuery(entityAfterBeforeConvert);
this.doIndex(query, index);
// 将命令传入底层的链接中
return this.maybeCallbackAfterSave(Objects.requireNonNull(query.getObject()), index);
}
}
浙公网安备 33010602011771号