org.springframework.data.cassandra.core.cql.CachedPreparedStatementCreator Maven / Gradle / Ivy
Show all versions of spring-data-cassandra Show documentation
/*
* Copyright 2013-2023 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
*
* https://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.cassandra.core.cql;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
import com.datastax.oss.driver.api.core.CqlIdentifier;
import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.DriverException;
import com.datastax.oss.driver.api.core.cql.PreparedStatement;
/**
* This {@link PreparedStatementCreator} maintains a static cache of all prepared statements for the duration of the JVM
* runtime, more specific the lifecycle of the associated {@link ClassLoader}. When preparing statements with Cassandra,
* each Statement should be prepared once and only once due to the overhead of preparing the statement.
*
* {@link CachedPreparedStatementCreator} is thread-safe and does not require external synchronization when used by
* concurrent threads.
*
* @author David Webb
* @author Mark Paluch
* @deprecated since 2.0. This class uses an unsafe, static held cache.
*/
@Deprecated
public class CachedPreparedStatementCreator implements PreparedStatementCreator {
private static final Map> CACHE = new ConcurrentHashMap<>();
protected final Log log = LogFactory.getLog(getClass());
private final String cql;
/**
* Create a {@link PreparedStatementCreator} from the provided CQL.
*
* @param cql must not be empty or {@literal null}.
*/
public CachedPreparedStatementCreator(String cql) {
Assert.hasText(cql, "CQL is required to create a PreparedStatement");
this.cql = cql;
}
/**
* Returns the CQL statement on which the {@link PreparedStatement} will be based.
*
* @return a String containing the CQL of the {@link PreparedStatement}.
*/
public String getCql() {
return this.cql;
}
/* (non-Javadoc)
* @see org.springframework.data.cassandra.core.cql.PreparedStatementCreator#createPreparedStatement(com.datastax.oss.driver.api.core.CqlSession)
*/
@Override
public PreparedStatement createPreparedStatement(CqlSession session) throws DriverException {
CqlIdentifier keyspace = session.getKeyspace().orElse(CqlIdentifier.fromCql("unknown"));
String cacheKey = keyspace.asInternal().concat("|").concat(this.cql);
log.debug(String.format("Cacheable PreparedStatement in Keyspace %s", keyspace.asCql(true)));
Map sessionCache = getOrCreateSessionLocalCache(session);
return getOrPrepareStatement(session, cacheKey, sessionCache);
}
@SuppressWarnings("all")
private Map getOrCreateSessionLocalCache(CqlSession session) {
Map sessionMap = CACHE.get(session);
if (sessionMap == null) {
synchronized (session) {
if (CACHE.containsKey(session)) {
sessionMap = CACHE.get(session);
} else {
sessionMap = new ConcurrentHashMap();
CACHE.put(session, sessionMap);
}
}
}
return sessionMap;
}
@SuppressWarnings("all")
private PreparedStatement getOrPrepareStatement(CqlSession session, String cacheKey,
Map sessionCache) {
PreparedStatement preparedStatement = sessionCache.get(cacheKey);
if (preparedStatement == null) {
synchronized (sessionCache) {
if (sessionCache.containsKey(cacheKey)) {
log.debug("Found cached PreparedStatement");
preparedStatement = sessionCache.get(cacheKey);
} else {
log.debug("No cached PreparedStatement found... creating and caching");
preparedStatement = session.prepare(this.cql);
sessionCache.put(cacheKey, preparedStatement);
}
}
}
return preparedStatement;
}
}