学游者

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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);
    }
}
posted on 2024-08-15 18:34  学游者  阅读(36)  评论(0)    收藏  举报