DATACASS-403 - Add improved support for prepared statement caching.
We now provide PreparedStatementCache and CachedPreparedStatementCreator to prepare and cache prepared statements. The original o.s.d.c.c.CachedPreparedStatementCreator is deprecated as it uses an static held Map to cache statements. PreparedStatementCache cache = PreparedStatementCache.create(); CachedPreparedStatementCreator creator = CachedPreparedStatementCreator.of(cache, insert) template.execute(creator, (session, ps) -> session.execute(ps.bind(…))); Related ticket: DATACASS-291.
This commit is contained in:
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cql.core.support;
|
||||
|
||||
import org.springframework.data.cql.core.PreparedStatementCreator;
|
||||
import org.springframework.data.cql.core.QueryOptions;
|
||||
import org.springframework.data.cql.core.QueryOptionsUtil;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.datastax.driver.core.PreparedStatement;
|
||||
import com.datastax.driver.core.RegularStatement;
|
||||
import com.datastax.driver.core.Session;
|
||||
import com.datastax.driver.core.SimpleStatement;
|
||||
import com.datastax.driver.core.exceptions.DriverException;
|
||||
|
||||
/**
|
||||
* {@link PreparedStatementCreator} implementation using caching of prepared statements.
|
||||
* <p />
|
||||
* Regular CQL statements are prepared on first use and executed as prepared statements. Prepared statements are cached
|
||||
* by Cassandra itself (invalidation/eviction possible), in the driver to be able to re-prepare a statement and in this
|
||||
* {@link CachedPreparedStatementCreator} using {@link PreparedStatementCache}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.0
|
||||
* @see PreparedStatementCache
|
||||
*/
|
||||
public class CachedPreparedStatementCreator implements PreparedStatementCreator {
|
||||
|
||||
private final PreparedStatementCache cache;
|
||||
|
||||
private final RegularStatement statement;
|
||||
|
||||
/**
|
||||
* Create a new {@link CachedPreparedStatementCreator}.
|
||||
*
|
||||
* @param cache must not be {@literal null}.
|
||||
* @param statement may be {@literal null} of {@code cql} is provided.
|
||||
*/
|
||||
protected CachedPreparedStatementCreator(PreparedStatementCache cache, RegularStatement statement) {
|
||||
|
||||
Assert.notNull(cache, "Cache must not be null");
|
||||
|
||||
this.cache = cache;
|
||||
this.statement = statement;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link CachedPreparedStatementCreator} given {@link PreparedStatementCache} and
|
||||
* {@link RegularStatement} to prepare. Subsequent calls require the a {@link RegularStatement} object with the same
|
||||
* CQL test for a cache hit. Otherwise, the statement is likely to be re-prepared.
|
||||
*
|
||||
* @param cache must not be {@literal null}.
|
||||
* @param cql must not be {@literal null} or empty.
|
||||
* @return the {@link CachedPreparedStatementCreator} for {@link RegularStatement}.
|
||||
*/
|
||||
public static CachedPreparedStatementCreator of(PreparedStatementCache cache, RegularStatement statement) {
|
||||
|
||||
Assert.notNull(cache, "Cache must not be null");
|
||||
Assert.notNull(statement, "Statement must not be null");
|
||||
|
||||
return new CachedPreparedStatementCreator(cache, statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link CachedPreparedStatementCreator} given {@link PreparedStatementCache} and {@code cql} to
|
||||
* prepare. Subsequent calls require the a CQL statement that {@link String#equals(Object) are equal} to the
|
||||
* previously used CQL string for a cache hit. Otherwise, the statement is likely to be re-prepared.
|
||||
*
|
||||
* @param cache must not be {@literal null}.
|
||||
* @param cql must not be {@literal null} or empty.
|
||||
* @return the {@link CachedPreparedStatementCreator} for {@code cql}.
|
||||
*/
|
||||
public static CachedPreparedStatementCreator of(PreparedStatementCache cache, String cql) {
|
||||
|
||||
Assert.notNull(cache, "Cache must not be null");
|
||||
Assert.hasText(cql, "CQL statement must not be null");
|
||||
|
||||
return new CachedPreparedStatementCreator(cache, new SimpleStatement(cql));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@link CachedPreparedStatementCreator} given {@link PreparedStatementCache} and {@code cql} to
|
||||
* prepare. This method applies {@link QueryOptions} to the {@link com.datastax.driver.core.Statement} before
|
||||
* preparing it. Subsequent calls require the a CQL statement that {@link String#equals(Object) are equal} to the
|
||||
* previously used CQL string for a cache hit. Otherwise, the statement is likely to be re-prepared.
|
||||
*
|
||||
* @param cache must not be {@literal null}.
|
||||
* @param cql must not be {@literal null} or empty.
|
||||
* @param queryOptions must not be {@literal null}.
|
||||
* @return the {@link CachedPreparedStatementCreator} for {@code cql}.
|
||||
*/
|
||||
public static CachedPreparedStatementCreator of(PreparedStatementCache cache, String cql, QueryOptions queryOptions) {
|
||||
|
||||
Assert.notNull(cache, "Cache must not be null");
|
||||
Assert.hasText(cql, "CQL statement must not be null");
|
||||
Assert.notNull(queryOptions, "QueryOptions must not be null");
|
||||
|
||||
SimpleStatement statement = new SimpleStatement(cql);
|
||||
|
||||
QueryOptionsUtil.addQueryOptions(statement, queryOptions);
|
||||
|
||||
return new CachedPreparedStatementCreator(cache, statement);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the underlying {@link PreparedStatementCache}.
|
||||
*/
|
||||
public PreparedStatementCache getCache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.cql.core.PreparedStatementCreator#createPreparedStatement(com.datastax.driver.core.Session)
|
||||
*/
|
||||
@Override
|
||||
public PreparedStatement createPreparedStatement(Session session) throws DriverException {
|
||||
return cache.getPreparedStatement(session, statement, () -> session.prepare(statement));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cql.core.support;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.datastax.driver.core.Cluster;
|
||||
import com.datastax.driver.core.PreparedStatement;
|
||||
import com.datastax.driver.core.RegularStatement;
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
/**
|
||||
* {@link PreparedStatementCache} backed by a {@link Map} cache. Defaults to simple {@link ConcurrentHashMap} caching.
|
||||
* <p/>
|
||||
* Statements are cached with a key consisting of {@link Cluster}, {@code keyspace} and the {@code cql} text. Statement
|
||||
* options (idempotency, timeouts) apply from the statement that was initially prepared.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.0
|
||||
*/
|
||||
public class MapPreparedStatementCache implements PreparedStatementCache {
|
||||
|
||||
private final Map<CacheKey, PreparedStatement> cache;
|
||||
|
||||
/**
|
||||
* Create a new {@link MapPreparedStatementCache}.
|
||||
*
|
||||
* @param cache must not be {@literal null}.
|
||||
*/
|
||||
private MapPreparedStatementCache(Map<CacheKey, PreparedStatement> cache) {
|
||||
|
||||
Assert.notNull(cache, "Cache must not be null");
|
||||
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MapPreparedStatementCache} using {@link ConcurrentHashMap}.
|
||||
*
|
||||
* @return the new {@link MapPreparedStatementCache} backed by {@link ConcurrentHashMap}.
|
||||
*/
|
||||
public static MapPreparedStatementCache create() {
|
||||
return of(new ConcurrentHashMap<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link MapPreparedStatementCache} using the given {@link Map}.
|
||||
*
|
||||
* @return the new {@link MapPreparedStatementCache} backed the given {@link Map}.
|
||||
*/
|
||||
public static MapPreparedStatementCache of(Map<CacheKey, PreparedStatement> cache) {
|
||||
return new MapPreparedStatementCache(cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the underlying {@link Map cache}.
|
||||
*/
|
||||
public Map<CacheKey, PreparedStatement> getCache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.cql.core.support.PrepatedStatementCache#getPreparedStatement(com.datastax.driver.core.RegularStatement, com.datastax.driver.core.Session, java.util.function.Supplier)
|
||||
*/
|
||||
@Override
|
||||
public PreparedStatement getPreparedStatement(Session session, RegularStatement statement,
|
||||
Supplier<PreparedStatement> preparer) {
|
||||
|
||||
CacheKey cacheKey = new CacheKey(session, statement.toString());
|
||||
|
||||
return cache.computeIfAbsent(cacheKey, key -> session.prepare(statement));
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache key for {@link PreparedStatement} caching.
|
||||
*/
|
||||
@EqualsAndHashCode
|
||||
public static class CacheKey {
|
||||
|
||||
final Cluster cluster;
|
||||
final String keyspace;
|
||||
final String cql;
|
||||
|
||||
CacheKey(Session session, String cql) {
|
||||
|
||||
this.cluster = session.getCluster();
|
||||
this.keyspace = session.getLoggedKeyspace();
|
||||
this.cql = cql;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cql.core.support;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.datastax.driver.core.PreparedStatement;
|
||||
import com.datastax.driver.core.RegularStatement;
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
/**
|
||||
* Cache interface to synchronously prepare CQL statements.
|
||||
* <p />
|
||||
* Implementing classes of {@link PreparedStatementCache} come with own synchronization and cache implementation
|
||||
* characteristics. A cache implementation should optimize for reduction of preparation calls and cache statements using
|
||||
* Cassandras cache key which is specific to the Cluster, keyspace, and CQL text.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 2.0
|
||||
* @see PreparedStatement
|
||||
*/
|
||||
public interface PreparedStatementCache {
|
||||
|
||||
/**
|
||||
* Obtain a {@link PreparedStatement} by {@link Session} and {@link RegularStatement}.
|
||||
*
|
||||
* @param session must not be {@literal null}.
|
||||
* @param statement must not be {@literal null}.
|
||||
* @param preparer must not be {@literal null}.
|
||||
* @return the {@link PreparedStatement}.
|
||||
*/
|
||||
PreparedStatement getPreparedStatement(Session session, RegularStatement statement,
|
||||
Supplier<PreparedStatement> preparer);
|
||||
|
||||
/**
|
||||
* Create a default cache backed by a {@link java.util.concurrent.ConcurrentHashMap}.
|
||||
*
|
||||
* @return a new {@link MapPreparedStatementCache}.
|
||||
*/
|
||||
static PreparedStatementCache create() {
|
||||
return MapPreparedStatementCache.create();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cql.core.support;
|
||||
|
||||
import static com.datastax.driver.core.querybuilder.QueryBuilder.*;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.cql.AbstractKeyspaceCreatingIntegrationTest;
|
||||
|
||||
import com.datastax.driver.core.PreparedStatement;
|
||||
import com.datastax.driver.core.querybuilder.Insert;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link CachedPreparedStatementCreator}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class CachedPreparedStatementCreatorIntegrationTest extends AbstractKeyspaceCreatingIntegrationTest {
|
||||
|
||||
private static final AtomicBoolean initialized = new AtomicBoolean();
|
||||
|
||||
@Before
|
||||
public void before() throws Exception {
|
||||
|
||||
if (initialized.compareAndSet(false, true)) {
|
||||
getSession().execute("CREATE TABLE IF NOT EXISTS user (id text PRIMARY KEY, username text);");
|
||||
} else {
|
||||
session.execute("TRUNCATE user;");
|
||||
}
|
||||
}
|
||||
|
||||
@Test // DATACASS-403
|
||||
public void shouldRetainIdempotencyFlag() {
|
||||
|
||||
Insert insert = QueryBuilder.insertInto("user").value("id", bindMarker()).value("username", bindMarker());
|
||||
|
||||
assertThat(insert.isIdempotent()).isTrue();
|
||||
|
||||
PreparedStatementCache cache = PreparedStatementCache.create();
|
||||
PreparedStatement preparedStatement = CachedPreparedStatementCreator.of(cache, insert)
|
||||
.createPreparedStatement(session);
|
||||
|
||||
assertThat(preparedStatement.isIdempotent()).isTrue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright 2017 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cql.core.support;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import com.datastax.driver.core.Cluster;
|
||||
import com.datastax.driver.core.PreparedStatement;
|
||||
import com.datastax.driver.core.RegularStatement;
|
||||
import com.datastax.driver.core.Session;
|
||||
import com.datastax.driver.core.SimpleStatement;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link CachedPreparedStatementCreator}.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class CachedPreparedStatementCreatorUnitTests {
|
||||
|
||||
@Mock Session session;
|
||||
|
||||
@Mock Session otherSession;
|
||||
|
||||
@Mock Session otherKeyspaceSession;
|
||||
|
||||
@Mock Cluster cluster;
|
||||
|
||||
@Mock PreparedStatement preparedStatement;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
|
||||
when(session.getCluster()).thenReturn(cluster);
|
||||
when(otherSession.getCluster()).thenReturn(cluster);
|
||||
when(otherKeyspaceSession.getCluster()).thenReturn(cluster);
|
||||
|
||||
when(session.getLoggedKeyspace()).thenReturn("keyspace");
|
||||
when(otherSession.getLoggedKeyspace()).thenReturn("keyspace");
|
||||
when(otherKeyspaceSession.getLoggedKeyspace()).thenReturn("other");
|
||||
|
||||
when(session.prepare(any(RegularStatement.class))).thenReturn(preparedStatement);
|
||||
}
|
||||
|
||||
@Test // DATACASS-403
|
||||
public void shouldPrepareStatement() {
|
||||
|
||||
String cql = "SELECT foo FROM users;";
|
||||
|
||||
MapPreparedStatementCache cache = MapPreparedStatementCache.create();
|
||||
|
||||
CachedPreparedStatementCreator creator = CachedPreparedStatementCreator.of(cache, cql);
|
||||
|
||||
PreparedStatement result = creator.createPreparedStatement(session);
|
||||
|
||||
assertThat(result).isSameAs(preparedStatement);
|
||||
assertThat(creator.getCache()).isSameAs(cache);
|
||||
assertThat(cache.getCache()).hasSize(1);
|
||||
}
|
||||
|
||||
@Test // DATACASS-403
|
||||
public void shouldCachePreparedStatement() {
|
||||
|
||||
String cql = "SELECT foo FROM users;";
|
||||
|
||||
PreparedStatementCache cache = PreparedStatementCache.create();
|
||||
|
||||
assertThat(CachedPreparedStatementCreator.of(cache, cql).createPreparedStatement(session))
|
||||
.isSameAs(preparedStatement);
|
||||
assertThat(CachedPreparedStatementCreator.of(cache, cql).createPreparedStatement(session))
|
||||
.isSameAs(preparedStatement);
|
||||
|
||||
verify(session, atMost(1)).prepare(any(SimpleStatement.class));
|
||||
}
|
||||
|
||||
@Test // DATACASS-403
|
||||
public void shouldCachePreparedStatementAcrossSessions() {
|
||||
|
||||
String cql = "SELECT foo FROM users;";
|
||||
|
||||
PreparedStatementCache cache = PreparedStatementCache.create();
|
||||
|
||||
CachedPreparedStatementCreator creator = CachedPreparedStatementCreator.of(cache, cql);
|
||||
|
||||
assertThat(creator.createPreparedStatement(session)).isSameAs(preparedStatement);
|
||||
assertThat(creator.createPreparedStatement(otherSession)).isSameAs(preparedStatement);
|
||||
|
||||
verify(session, atMost(1)).prepare(any(SimpleStatement.class));
|
||||
verify(otherSession, never()).prepare(any(SimpleStatement.class));
|
||||
}
|
||||
|
||||
@Test // DATACASS-403
|
||||
public void shouldCachePreparedStatementOnKeyspaceLevel() {
|
||||
|
||||
String cql = "SELECT foo FROM users;";
|
||||
when(otherKeyspaceSession.prepare(any(RegularStatement.class))).thenReturn(preparedStatement);
|
||||
|
||||
PreparedStatementCache cache = PreparedStatementCache.create();
|
||||
|
||||
CachedPreparedStatementCreator creator = CachedPreparedStatementCreator.of(cache, cql);
|
||||
|
||||
assertThat(creator.createPreparedStatement(session)).isSameAs(preparedStatement);
|
||||
assertThat(creator.createPreparedStatement(otherKeyspaceSession)).isSameAs(preparedStatement);
|
||||
|
||||
verify(session).prepare(any(SimpleStatement.class));
|
||||
verify(otherKeyspaceSession).prepare(any(SimpleStatement.class));
|
||||
}
|
||||
|
||||
@Test // DATACASS-403
|
||||
public void shouldCacheBuiltPreparedStatement() {
|
||||
|
||||
RegularStatement statement = QueryBuilder.update("users").with(QueryBuilder.set("foo", "bar"));
|
||||
|
||||
PreparedStatementCache cache = PreparedStatementCache.create();
|
||||
|
||||
when(session.prepare(statement)).thenReturn(preparedStatement);
|
||||
|
||||
assertThat(CachedPreparedStatementCreator.of(cache, statement).createPreparedStatement(session))
|
||||
.isSameAs(preparedStatement);
|
||||
assertThat(CachedPreparedStatementCreator.of(cache, statement).createPreparedStatement(session))
|
||||
.isSameAs(preparedStatement);
|
||||
|
||||
assertThat(statement.isIdempotent()).isTrue();
|
||||
verify(session).prepare(statement);
|
||||
}
|
||||
|
||||
@Test // DATACASS-403
|
||||
public void shouldCacheSameBuiltPreparedStatements() {
|
||||
|
||||
RegularStatement firstStatement = QueryBuilder.update("users").with(QueryBuilder.set("foo", "bar"));
|
||||
RegularStatement secondStatement = QueryBuilder.update("users").with(QueryBuilder.set("foo", "bar"));
|
||||
|
||||
PreparedStatementCache cache = PreparedStatementCache.create();
|
||||
|
||||
when(session.prepare(firstStatement)).thenReturn(preparedStatement);
|
||||
|
||||
CachedPreparedStatementCreator.of(cache, firstStatement).createPreparedStatement(session);
|
||||
CachedPreparedStatementCreator.of(cache, secondStatement).createPreparedStatement(session);
|
||||
|
||||
verify(session).prepare(firstStatement);
|
||||
}
|
||||
|
||||
@Test // DATACASS-403
|
||||
public void shouldCacheAdoptDifferencesInCachedPreparedStatements() {
|
||||
|
||||
RegularStatement firstStatement = QueryBuilder.update("users").with(QueryBuilder.set("foo", "bar"));
|
||||
RegularStatement secondStatement = QueryBuilder.update("users").with(QueryBuilder.set("bar", "foo"));
|
||||
|
||||
PreparedStatementCache cache = PreparedStatementCache.create();
|
||||
|
||||
when(session.prepare(firstStatement)).thenReturn(preparedStatement);
|
||||
when(session.prepare(secondStatement)).thenReturn(preparedStatement);
|
||||
|
||||
CachedPreparedStatementCreator.of(cache, firstStatement).createPreparedStatement(session);
|
||||
CachedPreparedStatementCreator.of(cache, secondStatement).createPreparedStatement(session);
|
||||
|
||||
verify(session).prepare(firstStatement);
|
||||
verify(session).prepare(secondStatement);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user