All Downloads are FREE. Search and download functionalities are using the official Maven repository.

helper.database.cassandra.CassandraRepository Maven / Gradle / Ivy

The newest version!
package helper.database.cassandra;

import com.datastax.driver.core.PagingState;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.querybuilder.Clause;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;
import com.datastax.driver.mapping.Mapper;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import helper.database.Paging;
import helper.database.Repository;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 基于 Cassandra 的抽象仓库。
 * 

* 简化 CQL 语句的相关操作。 * * @author qiang.zhang */ public abstract class CassandraRepository implements Repository { private static final Logger LOGGER = LoggerFactory.getLogger("cassandra"); protected final Class entityClass; /** * 由实体类型构造的 Cassandra 仓库。 * * @param entityClass 实体类型。 */ protected CassandraRepository(Class entityClass) { Preconditions.checkNotNull(entityClass); this.entityClass = entityClass; } /** * Cassandra 驱动。 *

* 通常是由实现类提供的单例对象。 * * @return Cassandra 驱动。 */ abstract protected Cassandra cassandra(); /** * 根据实体映射器以及查询子句,获得资源总数量。 * * @param mapper 实体映射器。 * @param clauses 查询子句。 * @return 0 表示没有任何资源,大于 0 表示查询到的资源总数量。 */ protected Long countAll(Mapper mapper, List clauses) { Session session = mapper.getManager().getSession(); String keyspace = mapper.getTableMetadata().getKeyspace().getName(); String table = mapper.getTableMetadata().getName(); Select.Where countWhere = QueryBuilder.select().countAll().from(keyspace, table).where(); for (Clause c : clauses) { countWhere.and(c); } LOGGER.debug("Execute count cql: {}", countWhere); ResultSet countSet = session.execute(countWhere); long total = 0L; if (countSet.getAvailableWithoutFetching() > 0) { total = countSet.one().getLong("count"); } LOGGER.debug("keyspace {} table {} count all {}", keyspace, table, total); return total; } /** * 将 Map 对象转换为查询子句列表。 * * @param map 包含查询子句键值的 Map 对象。 * @return 查询子句列表。不为 Null,但有可能是 Empty。 */ protected List ofMap(@Nullable Map map) { List clauses = map == null ? Collections.emptyList() : Lists.newArrayListWithCapacity(map.size()); if (map != null) { for (Map.Entry entry : map.entrySet()) { String key = entry.getKey(); if (Strings.isNullOrEmpty(key)) { continue; } Object value = entry.getValue(); if (value != null) { clauses.add(QueryBuilder.eq(key, value)); } } } return clauses; } /** * 通过实体映射器、第一行序号、最大行数以及查询子句,获得资源列表。 * * @param mapper 实体映射器。 * @param firstRow 第一行序号。 * @param maxRows 最大行数。 * @param clauses 查询子句。 * @return 资源列表。如果没有查询到,则返回 Null。 */ @Nullable protected List resource(Mapper mapper, int firstRow, int maxRows, List clauses) { Session session = mapper.getManager().getSession(); String keyspace = mapper.getTableMetadata().getKeyspace().getName(); String table = mapper.getTableMetadata().getName(); Select.Where where = QueryBuilder.select().from(keyspace, table).where(); for (Clause c : clauses) { where.and(c); } LOGGER.debug("Execute list cql: {}", where); if (firstRow <= 1) { // 第一页的第一行,只需要限制最大行数 ResultSet resultSet = session.execute(where.limit(maxRows)); return mapper.map(resultSet).all(); } // 获取当前页面第一行之前的分页状态 PagingState pagingState = session.execute(where.setFetchSize(firstRow - 1)) .getExecutionInfo() .getPagingState(); // 根据分页状态获取当前页面的结果 ResultSet resultSet = session.execute(where.setFetchSize(maxRows) .setPagingState(pagingState)); // 如果有可用的结果 if (resultSet.getAvailableWithoutFetching() > 0) { int fetchSize = resultSet.getAvailableWithoutFetching(); List resource = Lists.newArrayListWithCapacity(fetchSize); // for 循环添加到列表,防止 all 语句获取全部结果 for (int i = 0; i < fetchSize; i++) { // 全部获取完毕,或当前页面无结果 if (resultSet.isExhausted() || resultSet.getAvailableWithoutFetching() == 0) { break; } resource.add(mapper.map(resultSet).one()); } return resource; } return null; } @Override public void save(E entity) { Preconditions.checkNotNull(entity); LOGGER.debug("Save entity: {}", entity); cassandra().mapper(entityClass).ifPresent(mapper -> mapper.save(entity)); } @Override public void delete(Object... primaryKey) { Preconditions.checkNotNull(primaryKey); Preconditions.checkArgument(primaryKey.length > 0); LOGGER.debug("Delete primary key: {}", Arrays.toString(primaryKey)); cassandra().mapper(entityClass).ifPresent(mapper -> mapper.delete(primaryKey)); } @Override public Optional get(Object... primaryKey) { Preconditions.checkNotNull(primaryKey); Preconditions.checkArgument(primaryKey.length > 0); LOGGER.debug("Get primary key: {}", Arrays.toString(primaryKey)); return cassandra().mapper(entityClass).map(mapper -> mapper.get(primaryKey)); } @Override public Paging list(int index, int size, @Nullable Map clause) { LOGGER.debug("paging index: {} size: {} clause: {}", index, size, clause); int firstRow = Paging.computeFirstRow(index, size); int maxRows = Paging.computeMaxRows(size); return cassandra().mapper(entityClass) .map(mapper -> countAll(mapper, ofMap(clause))) .filter(total -> total > 0 && firstRow <= total) .map(total -> { int count = Paging.computePageCount(total, maxRows); List resources = cassandra().mapper(entityClass) .map(mapper -> resource(mapper, firstRow, maxRows, ofMap(clause))) .orElse(Collections.emptyList()); return Paging.of(total, index, count, resources); }).orElse(Paging.ofEmpty(index)); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy