使用Spring Data Cassandra缓存的预备语句

桑博远
2023-12-01

今天,我有一篇简短的文章,内容涉及在Spring Data Cassandra中使用Prepared Statements。 Spring为您提供了一些实用程序,使您可以更轻松地使用“预备语句”,而不必依靠自己使用Datastax Java驱动程序手动注册查询。 Spring代码提供了一个缓存来存储经常使用的准备好的语句。 允许您通过缓存执行查询,缓存可以从缓存中检索准备好的查询,也可以在执行之前添加一个新查询。

为了简短起见,我们可能应该开始看一些代码。

依存关系

<parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.0.5.RELEASE</version>
</parent>

<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-cassandra</artifactId>
  </dependency>
</dependencies>

使用Spring Boot 2.0.5.RELEASE将拉入Spring Data Cassandra的2.0.10.RELEASE

使用准备好的语句

让我们直接进入:

@Repository
public class PersonRepository extends SimpleCassandraRepository<Person, PersonKey> {

  private final Session session;
  private final CassandraOperations cassandraTemplate;
  private final PreparedStatementCache cache = PreparedStatementCache.create();

  public PersonRepository(
      Session session,
      CassandraEntityInformation entityInformation,
      CassandraOperations cassandraTemplate) {
    super(entityInformation, cassandraTemplate);
    this.session = session;
    this.cassandraTemplate = cassandraTemplate;
  }

  // using ORM
  public List<Person> findByFirstNameAndDateOfBirth(String firstName, LocalDate dateOfBirth) {
    return cassandraTemplate
        .getCqlOperations()
        .query(
            findByFirstNameAndDateOfBirthQuery(firstName, dateOfBirth),
            (row, rowNum) -> cassandraTemplate.getConverter().read(Person.class, row));
  }

  private BoundStatement findByFirstNameAndDateOfBirthQuery(
      String firstName, LocalDate dateOfBirth) {
    return CachedPreparedStatementCreator.of(
            cache,
            select()
                .all()
                .from("people_by_first_name")
                .where(eq("first_name", bindMarker("first_name")))
                .and(eq("date_of_birth", bindMarker("date_of_birth"))))
        .createPreparedStatement(session)
        .bind()
        .setString("first_name", firstName)
        .setDate("date_of_birth", toCqlDate(dateOfBirth));
  }

  private com.datastax.driver.core.LocalDate toCqlDate(LocalDate date) {
    return com.datastax.driver.core.LocalDate.fromYearMonthDay(
        date.getYear(), date.getMonth().getValue(), date.getDayOfMonth());
  }

  // without ORM
  public List<Person> findByFirstNameAndDateOfBirthWithoutORM(
      String firstName, LocalDate dateOfBirth) {
    return cassandraTemplate
        .getCqlOperations()
        .query(
            findByFirstNameAndDateOfBirthQuery(firstName, dateOfBirth),
            (row, rowNum) -> convert(row));
  }

  private Person convert(Row row) {
    return new Person(
        new PersonKey(
            row.getString("first_name"),
            toLocalDate(row.getDate("date_of_birth")),
            row.getUUID("person_id")),
        row.getString("last_name"),
        row.getDouble("salary"));
  }

  private LocalDate toLocalDate(com.datastax.driver.core.LocalDate date) {
    return LocalDate.of(date.getYear(), date.getMonth(), date.getDay());
  }
}

这里有相当数量的样板代码,因此我们可以访问Spring Data的ORM。 我还提供了代码来演示如何在不使用ORM的情况下实现相同的目标(无论如何,直接将查询直接映射到对象)。

让我们更仔细地研究一种方法:

public List<Person> findByFirstNameAndDateOfBirth(String firstName, LocalDate dateOfBirth) {
  return cassandraTemplate
      .getCqlOperations()
      .query(
          findByFirstNameAndDateOfBirthQuery(firstName, dateOfBirth),
          (row, rowNum) -> cassandraTemplate.getConverter().read(Person.class, row));
}

private BoundStatement findByFirstNameAndDateOfBirthQuery(
    String firstName, LocalDate dateOfBirth) {
  return CachedPreparedStatementCreator.of(
          cache,
          select()
              .all()
              .from("people_by_first_name")
              .where(eq("first_name", bindMarker("first_name")))
              .and(eq("date_of_birth", bindMarker("date_of_birth"))))
      .createPreparedStatement(session)
      .bind()
      .setString("first_name", firstName)
      .setDate("date_of_birth", toCqlDate(dateOfBirth));
}

CachedPreparedStatementCreator完全按照其说的进行操作...它创建缓存的Prepared Statements。 of方法采用实例化Bean时定义的cache ,并创建第二个参数定义的新查询。 如果查询是最近已经注册的查询,即它已经在缓存中。 然后,从那里开始查询,而不是完成注册新语句的整个过程。

传入的查询是一个RegularStatement ,可以通过调用createPreparedStatement将它转换为PreparedStatement (我猜是吧)。 现在,我们可以将值绑定到查询,因此它实际上可以做一些有用的事情。

就缓存Prepared Statements而言,这就是您要做的全部。 还有其他方法可以执行此操作,例如,您可以手动使用PreparedStatementCache或定义自己的缓存实现。 无论您的船浮在水上。

您现在已经到了这篇简短文章的结尾,希望它实际上包含了足够有用的信息……

在本文中,我们介绍了如何使用CachedPreparedStatementCreator创建和将Prepared Statements放入高速缓存中,以便在以后更快地执行。 使用Spring Data提供的类,我们可以减少需要编写的代码量。

这篇文章中使用的代码可以在我的GitHub上找到

如果您认为这篇文章有帮助,可以在Twitter上@LankyDanDev关注我,以跟上我的新文章。

翻译自: https://www.javacodegeeks.com/2018/10/cached-prepared-statements-cassandra.html

 类似资料: