Статьи

Кэшированные подготовленные операторы с помощью Spring Data Cassandra

Сегодня у меня есть небольшой пост об использовании подготовленных заявлений в Spring Data Cassandra. Spring предоставляет вам некоторые утилиты, которые упростят использование подготовленных выражений, вместо того чтобы полагаться на ручную регистрацию запросов вручную с помощью драйвера Java Datastax. Код Spring предоставляет кэш для хранения подготовленных операторов, которые часто используются. Позволяет вам выполнять ваши запросы через кеш, который либо извлекает подготовленный запрос из кеша, либо добавляет новый перед его выполнением.

Для краткости мы, вероятно, должны начать смотреть на некоторый код.

зависимости

01
02
03
04
05
06
07
08
09
10
11
12
<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 будет 2.0.10.RELEASE Spring Data Cassandra.

Использование подготовленных заявлений

Давайте прямо в:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
@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());
  }
}

Здесь имеется достаточное количество стандартного кода, чтобы мы могли получить доступ к ORM Spring Data. Я также предоставил код, чтобы продемонстрировать, как достичь той же цели без использования ORM (в любом случае, хорошо отображая прямо от запроса к объекту вручную).

Давайте посмотрим на один из методов более подробно:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
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 делает именно то, что говорит… Он создает кэшированные подготовленные операторы. Метод принимает в cache определенный при создании экземпляра компонента, и создает новый запрос, определенный вторым параметром. Если запрос уже зарегистрирован, то есть уже находится в кеше. Затем запрос извлекается оттуда, а не проходит весь процесс регистрации нового оператора.

RegularStatement запрос является RegularStatement который преобразуется в PreparedStatement помощью вызова createPreparedStatement (я думаю, это не так). Теперь мы можем связать значения с запросом, чтобы он действительно делал что-то полезное.

С точки зрения кэширования подготовленных заявлений, это все, что вам нужно сделать. Есть и другие способы сделать это, например, вы можете использовать PreparedStatementCache вручную или определить собственную реализацию кэша. Все, что плывет на вашей лодке.

Вы подошли к концу этого короткого поста, надеюсь, он действительно содержал достаточно информации, чтобы быть полезным …

В этой статье мы рассмотрели, как использовать CachedPreparedStatementCreator для создания и помещения подготовленных операторов в кэш для более быстрого выполнения в более позднее время. Используя классы, предоставляемые Spring Data, мы можем сократить объем кода, который нам нужно написать.

Код, используемый в этом посте, можно найти на моем GitHub .

Если вы нашли этот пост полезным, вы можете подписаться на меня в Twitter на @LankyDanDev, чтобы не отставать от моих новых сообщений.

Опубликовано на Java Code Geeks с разрешения Дэна Ньютона, партнера нашей программы JCG . См. Оригинальную статью здесь: кэшированные подготовленные операторы с помощью Spring Data Cassandra

Мнения, высказанные участниками Java Code Geeks, являются их собственными.