br.com.anteros.nosql.persistence.mongodb.session.SimpleMongoSession Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of Anteros-NoSql-Persistence-MongoDB Show documentation
Show all versions of Anteros-NoSql-Persistence-MongoDB Show documentation
Anteros NoSQL Persistence MongoDB.
package br.com.anteros.nosql.persistence.mongodb.session;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.bson.Document;
import com.mongodb.MongoException;
import com.mongodb.ReadPreference;
import com.mongodb.WriteConcern;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MapReduceIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.CountOptions;
import com.mongodb.client.model.DeleteOptions;
import com.mongodb.client.model.FindOneAndDeleteOptions;
import com.mongodb.client.model.FindOneAndReplaceOptions;
import com.mongodb.client.model.FindOneAndUpdateOptions;
import com.mongodb.client.model.ReplaceOptions;
import com.mongodb.client.model.ReturnDocument;
import com.mongodb.client.model.UpdateOptions;
import com.mongodb.client.result.DeleteResult;
import br.com.anteros.core.log.Logger;
import br.com.anteros.core.log.LoggerProvider;
import br.com.anteros.core.utils.Assert;
import br.com.anteros.core.utils.CollectionUtils;
import br.com.anteros.core.utils.ObjectUtils;
import br.com.anteros.core.utils.ResourceUtils;
import br.com.anteros.core.utils.StringUtils;
import br.com.anteros.nosql.persistence.client.NoSQLConnection;
import br.com.anteros.nosql.persistence.converters.Key;
import br.com.anteros.nosql.persistence.dialect.NoSQLDialect;
import br.com.anteros.nosql.persistence.metadata.NoSQLDescriptionEntity;
import br.com.anteros.nosql.persistence.metadata.NoSQLDescriptionEntityException;
import br.com.anteros.nosql.persistence.metadata.NoSQLDescriptionEntityManager;
import br.com.anteros.nosql.persistence.mongodb.aggregation.AggregationPipeline;
import br.com.anteros.nosql.persistence.mongodb.aggregation.AggregationPipelineImpl;
import br.com.anteros.nosql.persistence.mongodb.client.MongoConnection;
import br.com.anteros.nosql.persistence.mongodb.mapping.MongoObjectMapper;
import br.com.anteros.nosql.persistence.mongodb.query.InvalidDataAccessApiUsageException;
import br.com.anteros.nosql.persistence.mongodb.query.MongoQuery;
import br.com.anteros.nosql.persistence.mongodb.query.MongoUpdate;
import br.com.anteros.nosql.persistence.mongodb.query.SerializationUtils;
import br.com.anteros.nosql.persistence.mongodb.session.event.MongoAfterConvertEvent;
import br.com.anteros.nosql.persistence.mongodb.session.event.MongoAfterDeleteEvent;
import br.com.anteros.nosql.persistence.mongodb.session.event.MongoAfterLoadEvent;
import br.com.anteros.nosql.persistence.mongodb.session.event.MongoAfterSaveEvent;
import br.com.anteros.nosql.persistence.mongodb.session.event.MongoBeforeConvertEvent;
import br.com.anteros.nosql.persistence.mongodb.session.event.MongoBeforeDeleteEvent;
import br.com.anteros.nosql.persistence.mongodb.session.event.MongoBeforeSaveEvent;
import br.com.anteros.nosql.persistence.mongodb.session.event.MongoEventPublisher;
import br.com.anteros.nosql.persistence.proxy.ProxyHelper;
import br.com.anteros.nosql.persistence.session.FindAndModifyOptions;
import br.com.anteros.nosql.persistence.session.FindAndReplaceOptions;
import br.com.anteros.nosql.persistence.session.NoSQLEntityAdapter;
import br.com.anteros.nosql.persistence.session.NoSQLMappedDocument;
import br.com.anteros.nosql.persistence.session.NoSQLPersistenceContext;
import br.com.anteros.nosql.persistence.session.NoSQLResult;
import br.com.anteros.nosql.persistence.session.NoSQLSession;
import br.com.anteros.nosql.persistence.session.NoSQLSessionException;
import br.com.anteros.nosql.persistence.session.NoSQLSessionFactory;
import br.com.anteros.nosql.persistence.session.NoSQLSessionListener;
import br.com.anteros.nosql.persistence.session.ShowCommandsType;
import br.com.anteros.nosql.persistence.session.cache.DefaultNoSQLEntityCache;
import br.com.anteros.nosql.persistence.session.cache.NoSQLEntityCache;
import br.com.anteros.nosql.persistence.session.command.CommandNoSQL;
import br.com.anteros.nosql.persistence.session.event.NoSQLEvent;
import br.com.anteros.nosql.persistence.session.event.NoSQLEventPublisher;
import br.com.anteros.nosql.persistence.session.exception.NoSQLDataAccessException;
import br.com.anteros.nosql.persistence.session.exception.NoSQLExceptionTranslator;
import br.com.anteros.nosql.persistence.session.impl.SimpleNoSQLPersistenceContext;
import br.com.anteros.nosql.persistence.session.mapping.AbstractNoSQLObjectMapper;
import br.com.anteros.nosql.persistence.session.query.NoSQLCriteria;
import br.com.anteros.nosql.persistence.session.query.NoSQLQuery;
import br.com.anteros.nosql.persistence.session.query.NoSQLUpdate;
import br.com.anteros.nosql.persistence.session.transaction.NoSQLTransaction;
import br.com.anteros.nosql.persistence.session.transaction.NoSQLTransactionException;
import br.com.anteros.nosql.persistence.session.transaction.NoSQLTransactionFactory;
public class SimpleMongoSession implements MongoSession {
private static Logger LOG = LoggerProvider.getInstance().getLogger(NoSQLSession.class);
private static final Collection ITERABLE_CLASSES;
static {
Set iterableClasses = new HashSet<>();
iterableClasses.add(List.class.getName());
iterableClasses.add(Collection.class.getName());
iterableClasses.add(Iterator.class.getName());
ITERABLE_CLASSES = Collections.unmodifiableCollection(iterableClasses);
}
private NoSQLConnection connection;
private List listeners = new ArrayList();
private List commandQueue = new ArrayList();
private NoSQLSessionFactory sessionFactory;
private NoSQLDescriptionEntityManager descriptionEntityManager;
private NoSQLTransactionFactory transactionFactory;
private boolean formatCommands;
private NoSQLDialect dialect;
private ShowCommandsType[] showCommands;
private NoSQLPersistenceContext persistenceContext;
private NoSQLTransaction transaction;
private boolean validationActive;
private MongoObjectMapper mapper;
private NoSQLEntityCache cache;
private WriteConcern defaultWriteConcern;
private EntityOperations operations;
private NoSQLExceptionTranslator exceptionTranslator;
private ReadPreference readPreference;
private NoSQLEventPublisher eventPublisher = new MongoEventPublisher();
private boolean withoutTransactionControl;
public SimpleMongoSession(NoSQLSessionFactory sessionFactory, NoSQLConnection connection,
NoSQLDescriptionEntityManager descriptionEntityManager, NoSQLDialect dialect,
ShowCommandsType[] showCommands, boolean formatCommands, NoSQLTransactionFactory transactionFactory,
boolean validationActive, boolean withoutTransactionControl) {
this.sessionFactory = sessionFactory;
this.connection = connection;
this.descriptionEntityManager = descriptionEntityManager;
this.dialect = dialect;
this.showCommands = showCommands;
this.persistenceContext = new SimpleNoSQLPersistenceContext(this, descriptionEntityManager);
this.validationActive = validationActive;
this.mapper = new MongoObjectMapper(descriptionEntityManager);
this.cache = new DefaultNoSQLEntityCache();
// this.defaultWriteConcern = ((MongoConnection) connection).getWriteConcern(); // AQUI
this.operations = new EntityOperations(descriptionEntityManager, mapper);
this.exceptionTranslator = new MongoExceptionTranslator();
this.transactionFactory = transactionFactory;
this.withoutTransactionControl = withoutTransactionControl;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#flush()
*/
@Override
public void flush() throws Exception {
errorIfClosed();
for (CommandNoSQL command : commandQueue) {
command.execute();
}
commandQueue.clear();
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#forceFlush(java.util.Set)
*/
@Override
public void forceFlush(Set collectionNames) throws Exception {
errorIfClosed();
if (collectionNames != null) {
synchronized (commandQueue) {
boolean foundCommand = false;
for (CommandNoSQL command : commandQueue) {
if (collectionNames.contains(command.getTargetCollectionName().toUpperCase())) {
foundCommand = true;
break;
}
}
if (foundCommand) {
flush();
}
}
}
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#onBeforeExecuteCommit(br.com.anteros.nosql.persistence.client.NoSQLConnection)
*/
@Override
public void onBeforeExecuteCommit(NoSQLConnection connection) throws Exception {
flush();
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#onBeforeExecuteRollback(br.com.anteros.nosql.persistence.client.NoSQLConnection)
*/
@Override
public void onBeforeExecuteRollback(NoSQLConnection connection) throws Exception {
if (this.getConnection() == connection) {
synchronized (commandQueue) {
commandQueue.clear();
}
}
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#onAfterExecuteCommit(br.com.anteros.nosql.persistence.client.NoSQLConnection)
*/
@Override
public void onAfterExecuteCommit(NoSQLConnection connection) throws Exception {
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#onAfterExecuteRollback(br.com.anteros.nosql.persistence.client.NoSQLConnection)
*/
@Override
public void onAfterExecuteRollback(NoSQLConnection connection) throws Exception {
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#getDescriptionEntityManager()
*/
@Override
public NoSQLDescriptionEntityManager getDescriptionEntityManager() {
return descriptionEntityManager;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#getDialect()
*/
@Override
public NoSQLDialect getDialect() {
return dialect;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#getConnection()
*/
@Override
public NoSQLConnection getConnection() {
return connection;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#getPersistenceContext()
*/
@Override
public NoSQLPersistenceContext getPersistenceContext() {
return persistenceContext;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#addListener(br.com.anteros.nosql.persistence.session.NoSQLSessionListener)
*/
@Override
public void addListener(NoSQLSessionListener listener) {
if (!listeners.contains(listener))
listeners.add(listener);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#removeListener(br.com.anteros.nosql.persistence.session.NoSQLSessionListener)
*/
@Override
public void removeListener(NoSQLSessionListener listener) {
if (listeners.contains(listener))
listeners.remove(listener);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#getListeners()
*/
@Override
public List getListeners() {
return listeners;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#setFormatCommands(boolean)
*/
@Override
public void setFormatCommands(boolean format) {
this.formatCommands = format;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#isShowCommands()
*/
@Override
public boolean isShowCommands() {
return showCommands != null;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#isFormatCommands()
*/
@Override
public boolean isFormatCommands() {
return formatCommands;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#getDatabase()
*/
@Override
public MongoDatabase getDatabase() {
MongoConnection mongoConnection = (MongoConnection) getConnection();
if (transaction != null && transaction.isActive())
return mongoConnection.getDatabase(transaction);
else
return mongoConnection.getDatabase();
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#getDatabase(java.lang.String)
*/
@Override
public MongoDatabase getDatabase(String dbName) {
MongoConnection mongoConnection = (MongoConnection) getConnection();
if (transaction != null && transaction.isActive())
return mongoConnection.getDatabase(dbName, transaction);
else
return mongoConnection.getDatabase(dbName);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#dropCollection(java.lang.String)
*/
@Override
public void dropCollection(String collectionName) {
Assert.notNull(collectionName, "CollectionName must not be null!");
execute(collectionName, new CollectionCallback() {
public Void doInCollection(MongoCollection collection)
throws MongoException, NoSQLDataAccessException {
collection.drop();
if (LOG.isDebugEnabled()) {
LOG.debug("Dropped collection [{}]",
collection.getNamespace() != null ? collection.getNamespace().getCollectionName()
: collectionName);
}
return null;
}
});
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#isProxyObject(java.lang.Object)
*/
@Override
public boolean isProxyObject(Object object) throws Exception {
return ProxyHelper.isProxy(object);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#proxyIsInitialized(java.lang.Object)
*/
@Override
public boolean proxyIsInitialized(Object object) throws Exception {
return ProxyHelper.isUnFetched(object);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#cloneEntityManaged(java.lang.Object)
*/
@Override
public T cloneEntityManaged(Object object) throws Exception {
return null;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#evict(java.lang.Class)
*/
@Override
public void evict(Class> object) {
errorIfClosed();
persistenceContext.evict(object);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#evictAll()
*/
@Override
public void evictAll() {
errorIfClosed();
persistenceContext.evictAll();
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#isClosed()
*/
@Override
public boolean isClosed() throws Exception {
return getConnection() == null || getConnection().isClosed();
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#getTransaction()
*/
@Override
public NoSQLTransaction getTransaction() {
if (transaction == null || !transaction.isActive()) {
transaction = transactionFactory.createTransaction(getConnection(), getPersistenceContext());
}
return transaction;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#getNoSQLSessionFactory()
*/
@Override
public NoSQLSessionFactory getNoSQLSessionFactory() {
return sessionFactory;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#clear()
*/
@Override
public void clear() throws Exception {
internalClear();
}
private void internalClear() {
persistenceContext.evictAll();
persistenceContext.clearCache();
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#validationIsActive()
*/
@Override
public boolean validationIsActive() {
return validationActive;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#activateValidation()
*/
@Override
public void activateValidation() {
this.validationActive = true;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#deactivateValidation()
*/
@Override
public void deactivateValidation() {
this.validationActive = false;
}
@Override
protected void finalize() throws Throwable {
if (!this.isClosed())
this.close();
super.finalize();
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#close()
*/
@Override
public void close() throws Exception {
for (NoSQLSessionListener listener : listeners)
listener.onClose(this);
synchronized (commandQueue) {
commandQueue.clear();
}
if (connection != null && !connection.isClosed())
connection.close();
connection = null;
LOG.debug("Fechou session " + this);
}
protected void errorIfClosed() {
try {
if (isClosed()) {
throw new NoSQLSessionException("Sessão está fechada!");
}
} catch (Exception ex) {
throw new NoSQLSessionException("Sessão está fechada!", ex);
}
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#getIdentifier(T)
*/
@Override
public Object getIdentifier(T owner) throws Exception {
NoSQLDescriptionEntity descriptionEntity = descriptionEntityManager.getDescriptionEntity(owner.getClass());
if (descriptionEntity == null)
return null;
return descriptionEntity.getIdentifierValue(owner);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#collectionExists(java.lang.Class)
*/
@Override
public boolean collectionExists(Class entityClass) {
NoSQLDescriptionEntity descriptionEntity = getDescriptionEntity(entityClass);
String collectionName = descriptionEntity.getCollectionName();
return this.collectionExists(collectionName);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#collectionExists(java.lang.String)
*/
@Override
public boolean collectionExists(String collectionName) {
Assert.notNull(collectionName, "CollectionName must not be null!");
return execute(new DbCallback() {
public Boolean doInDB(MongoDatabase db) throws MongoException, NoSQLDataAccessException {
for (String name : db.listCollectionNames()) {
if (name.equals(collectionName)) {
return true;
}
}
return false;
}
});
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#createAggregation(java.lang.Class)
*/
@Override
public AggregationPipeline createAggregation(final Class> source) {
return new AggregationPipelineImpl(this, mapper, getCollection(source), source);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#createAggregation(java.lang.String, java.lang.Class)
*/
@Override
public AggregationPipeline createAggregation(final String collection, final Class> clazz) {
return new AggregationPipelineImpl(this, mapper, getCollection(collection), clazz);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#count(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.Class)
*/
@Override
public long count(NoSQLQuery query, Class> entityClass) {
Assert.notNull(entityClass, "Entity class must not be null!");
return count(query, entityClass, operations.determineCollectionName(entityClass));
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#count(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.Class, java.lang.String)
*/
@Override
public long count(NoSQLQuery query, Class> entityClass, String collectionName) {
return count(query, null, collectionName);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#count(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.String)
*/
@Override
public long count(NoSQLQuery query, String collectionName) {
Assert.notNull(query, "Query must not be null!");
Assert.hasText(collectionName, "Collection name must not be null or empty!");
CountOptions options = new CountOptions();
Document document = query.getQueryObject();
return execute(collectionName, collection -> collection.count(document, options));
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#createCollection(java.lang.Class)
*/
@Override
public MongoCollection createCollection(Class entityClass) throws Exception {
NoSQLDescriptionEntity descriptionEntity = getDescriptionEntity(entityClass);
String collectionName = descriptionEntity.getCollectionName();
return this.createCollection(collectionName);
}
protected NoSQLDescriptionEntity getDescriptionEntity(Class entityClass) {
NoSQLDescriptionEntity descriptionEntity = descriptionEntityManager.getDescriptionEntity(entityClass);
if (descriptionEntity == null) {
new NoSQLDescriptionEntityException(
"Entidade não encontrada na lista de entidades gerenciadas. " + entityClass.getName());
}
return descriptionEntity;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#createCollection(java.lang.String)
*/
@Override
public MongoCollection createCollection(String collectionName) throws Exception {
return getDatabase().getCollection(collectionName);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#dropCollection(java.lang.Class)
*/
@Override
public void dropCollection(Class entityClass) {
dropCollection(operations.determineCollectionName(entityClass));
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#execute(java.lang.Class, br.com.anteros.nosql.persistence.mongodb.session.CollectionCallback)
*/
@Override
public T execute(Class> entityClass, CollectionCallback callback) throws Exception {
Assert.notNull(entityClass, "EntityClass must not be null!");
return execute(operations.determineCollectionName(entityClass), callback);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#execute(br.com.anteros.nosql.persistence.mongodb.session.DbCallback)
*/
@Override
public T execute(DbCallback action) {
Assert.notNull(action, "DbCallback must not be null!");
try {
MongoDatabase db = prepareDatabase(this.getDatabase());
return action.doInDB(db);
} catch (RuntimeException e) {
throw translateRuntimeException(e, exceptionTranslator);
}
}
protected MongoDatabase prepareDatabase(MongoDatabase database) {
return database;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#execute(java.lang.String, br.com.anteros.nosql.persistence.mongodb.session.CollectionCallback)
*/
@Override
public T execute(String collectionName, CollectionCallback callback) {
Assert.notNull(collectionName, "CollectionName must not be null!");
Assert.notNull(callback, "CollectionCallback must not be null!");
try {
MongoCollection collection = getAndPrepareCollection(getDatabase(), collectionName);
return callback.doInCollection(collection);
} catch (RuntimeException e) {
throw translateRuntimeException(e, exceptionTranslator);
}
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#executeCommand(org.bson.Document)
*/
@Override
public Document executeCommand(Document command) throws Exception {
return getDatabase().runCommand(command);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#executeCommand(org.bson.Document, com.mongodb.ReadPreference)
*/
@Override
public Document executeCommand(Document command, ReadPreference readPreference) throws Exception {
return getDatabase().runCommand(command, readPreference);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#executeCommand(java.lang.String)
*/
@Override
public Document executeCommand(String jsonCommand) throws Exception {
return getDatabase().runCommand(Document.parse(jsonCommand), Document.class);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#executeQuery(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.String, br.com.anteros.nosql.persistence.mongodb.session.DocumentCallbackHandler)
*/
@Override
public void executeQuery(NoSQLQuery query, String collectionName, DocumentCallbackHandler dch)
throws Exception {
executeQuery(query, collectionName, dch, new QueryCursorPreparer(query, null));
}
protected void executeQuery(NoSQLQuery query, String collectionName,
DocumentCallbackHandler documentCallbackHandler, CursorPreparer preparer) {
Assert.notNull(query, "Query must not be null!");
Assert.notNull(collectionName, "CollectionName must not be null!");
Assert.notNull(documentCallbackHandler, "DocumentCallbackHandler must not be null!");
Document queryObject = query.getQueryObject();
Document sortObject = query.getSortObject();
Document fieldsObject = query.getFieldsObject();
if (LOG.isDebugEnabled()) {
LOG.debug("Executing query: {} sort: {} fields: {} in collection: {}",
SerializationUtils.serializeToJsonSafely(queryObject), sortObject, fieldsObject, collectionName);
}
this.executeQueryInternal(new FindCallback(queryObject, fieldsObject), preparer, documentCallbackHandler,
collectionName);
}
private void executeQueryInternal(CollectionCallback> collectionCallback,
CursorPreparer preparer, DocumentCallbackHandler callbackHandler, String collectionName) {
try {
MongoCursor cursor = null;
try {
FindIterable iterable = collectionCallback
.doInCollection(getAndPrepareCollection(getDatabase(), collectionName));
if (preparer != null) {
iterable = preparer.prepare(iterable);
}
cursor = iterable.iterator();
while (cursor.hasNext()) {
callbackHandler.processDocument(cursor.next());
}
} finally {
if (cursor != null) {
cursor.close();
}
}
} catch (RuntimeException e) {
throw translateRuntimeException(e, exceptionTranslator);
}
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#exists(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.Class)
*/
@Override
public boolean exists(NoSQLQuery query, Class> entityClass) {
return exists(query, entityClass, operations.determineCollectionName(entityClass));
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#exists(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.Class, java.lang.String)
*/
@Override
public boolean exists(NoSQLQuery query, Class> entityClass, String collectionName) {
if (query == null) {
throw new InvalidDataAccessApiUsageException("Query passed in to exist can't be null");
}
Assert.notNull(collectionName, "CollectionName must not be null!");
Document mappedQuery = query.getQueryObject();
return execute(collectionName, new ExistsCallback(mappedQuery));
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#exists(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.String)
*/
@Override
public boolean exists(NoSQLQuery query, String collectionName) {
return this.count(query, collectionName) > 0;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#find(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.Class)
*/
@Override
public List find(NoSQLQuery query, Class entityClass) {
return find(query, entityClass, operations.determineCollectionName(entityClass));
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#find(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.Class, java.lang.String)
*/
@Override
public List find(NoSQLQuery query, Class entityClass, String collectionName) {
Assert.notNull(query, "Query must not be null!");
Assert.notNull(collectionName, "CollectionName must not be null!");
Assert.notNull(entityClass, "EntityClass must not be null!");
return doFind(collectionName, query.getQueryObject(), query.getFieldsObject(), entityClass,
new QueryCursorPreparer(query, entityClass));
}
protected List doFind(String collectionName, Document query, Document fields, Class entityClass,
CursorPreparer preparer) {
return doFind(collectionName, query, fields, entityClass, preparer,
new ReadDocumentCallback<>(mapper, entityClass, collectionName));
}
protected List doFind(String collectionName, Document query, Document fields, Class entityClass,
CursorPreparer preparer, DocumentCallback objectCallback) {
if (LOG.isDebugEnabled()) {
LOG.debug("find using query: {} fields: {} for class: {} in collection: {}",
SerializationUtils.serializeToJsonSafely(query), fields, entityClass, collectionName);
}
return executeFindMultiInternal(new FindCallback(query, fields), preparer, objectCallback, collectionName);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findAll(java.lang.Class)
*/
@Override
public List findAll(Class entityClass) {
return findAll(entityClass, operations.determineCollectionName(entityClass));
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findAll(java.lang.Class, java.lang.String)
*/
@Override
public List findAll(Class entityClass, String collectionName) {
return executeFindMultiInternal(new FindCallback(new Document(), new Document()), null,
new ReadDocumentCallback<>(mapper, entityClass, collectionName), collectionName);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findAllAndRemove(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.Class)
*/
@Override
public List findAllAndRemove(NoSQLQuery query, Class entityClass) {
return findAllAndRemove(query, entityClass, operations.determineCollectionName(entityClass));
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findAllAndRemove(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.Class, java.lang.String)
*/
@Override
public List findAllAndRemove(NoSQLQuery query, Class entityClass, String collectionName)
{
return doFindAndDelete(collectionName, query, entityClass);
}
protected List doFindAndDelete(String collectionName, NoSQLQuery query, Class entityClass)
{
List result = find(query, entityClass, collectionName);
if (!CollectionUtils.isEmpty(result)) {
NoSQLQuery byIdInQuery = operations.getByIdInQuery(result);
remove(byIdInQuery, entityClass, collectionName);
}
return result;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findAllAndRemove(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.String)
*/
@SuppressWarnings("unchecked")
@Override
public List findAllAndRemove(NoSQLQuery query, String collectionName) {
return (List) findAllAndRemove(query, Object.class, collectionName);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findAndModify(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, br.com.anteros.nosql.persistence.session.query.NoSQLUpdate, java.lang.Class)
*/
@Override
public T findAndModify(NoSQLQuery query, NoSQLUpdate update, Class entityClass){
return findAndModify(query, update, new FindAndModifyOptions(), entityClass,
operations.determineCollectionName(entityClass));
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findAndModify(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, br.com.anteros.nosql.persistence.session.query.NoSQLUpdate, java.lang.Class, java.lang.String)
*/
@Override
public T findAndModify(NoSQLQuery query, NoSQLUpdate update, Class entityClass,
String collectionName) {
return findAndModify(query, update, new FindAndModifyOptions(), entityClass, collectionName);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findAndModify(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, br.com.anteros.nosql.persistence.session.query.NoSQLUpdate, br.com.anteros.nosql.persistence.session.FindAndModifyOptions, java.lang.Class)
*/
@Override
public T findAndModify(NoSQLQuery query, NoSQLUpdate update, FindAndModifyOptions options,
Class entityClass) {
return findAndModify(query, update, options, entityClass, operations.determineCollectionName(entityClass));
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findAndModify(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, br.com.anteros.nosql.persistence.session.query.NoSQLUpdate, br.com.anteros.nosql.persistence.session.FindAndModifyOptions, java.lang.Class, java.lang.String)
*/
@Override
public T findAndModify(NoSQLQuery query, NoSQLUpdate update, FindAndModifyOptions options,
Class entityClass, String collectionName) {
Assert.notNull(query, "Query must not be null!");
Assert.notNull(update, "Update must not be null!");
Assert.notNull(options, "Options must not be null!");
Assert.notNull(entityClass, "EntityClass must not be null!");
Assert.notNull(collectionName, "CollectionName must not be null!");
FindAndModifyOptions optionsToUse = FindAndModifyOptions.of(options);
return doFindAndModify(collectionName, query.getQueryObject(), query.getFieldsObject(),
getMappedSortObject(query, entityClass), entityClass, update, optionsToUse);
}
protected T doFindAndRemove(String collectionName, Document query, Document fields, Document sort,
Class entityClass) {
if (LOG.isDebugEnabled()) {
LOG.debug("findAndRemove using query: {} fields: {} sort: {} for class: {} in collection: {}",
SerializationUtils.serializeToJsonSafely(query), fields, sort, entityClass, collectionName);
}
return executeFindOneInternal(new FindAndRemoveCallback(query, fields, sort),
new ReadDocumentCallback<>(mapper, entityClass, collectionName), collectionName);
}
protected T doFindAndModify(String collectionName, Document query, Document fields, Document sort,
Class entityClass, NoSQLUpdate update, FindAndModifyOptions options) {
if (options == null) {
options = new FindAndModifyOptions();
}
NoSQLDescriptionEntity descriptionEntity = entityClass == null ? null
: descriptionEntityManager.getDescriptionEntity(entityClass);
increaseVersionForUpdateIfNecessary(descriptionEntity, update);
if (LOG.isDebugEnabled()) {
LOG.debug(
"findAndModify using query: {} fields: {} sort: {} for class: {} and update: {} "
+ "in collection: {}",
SerializationUtils.serializeToJsonSafely(query), fields, sort, entityClass,
SerializationUtils.serializeToJsonSafely(update), collectionName);
}
return executeFindOneInternal(new FindAndModifyCallback(query, fields, sort, update.getUpdateObject(), options),
new ReadDocumentCallback<>(mapper, entityClass, collectionName), collectionName);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findAndReplace(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, S, br.com.anteros.nosql.persistence.session.FindAndReplaceOptions, java.lang.Class, java.lang.String, java.lang.Class)
*/
@Override
public T findAndReplace(NoSQLQuery query, S replacement, FindAndReplaceOptions options,
Class entityType, String collectionName, Class resultType) {
Assert.notNull(query, "Query must not be null!");
Assert.notNull(replacement, "Replacement must not be null!");
Assert.notNull(options, "Options must not be null! Use FindAndReplaceOptions#empty() instead.");
Assert.notNull(entityType, "EntityType must not be null!");
Assert.notNull(collectionName, "CollectionName must not be null!");
Assert.notNull(resultType, "ResultType must not be null! Use Object.class instead.");
Assert.isTrue(query.getLimit() <= 1, "Query must not define a limit other than 1 ore none!");
Assert.isTrue(query.getOffset() <= 0, "Query must not define skip.");
Document mappedQuery = query.getQueryObject();
Document mappedFields = query.getFieldsObject();
Document mappedSort = query.getSortObject();
Document mappedReplacement = (Document) operations.forEntity(replacement).toMappedDocument().getDocument();
return doFindAndReplace(collectionName, mappedQuery, mappedFields, mappedSort, null, entityType,
mappedReplacement, options, resultType);
}
protected T doFindAndReplace(String collectionName, Document mappedQuery, Document mappedFields,
Document mappedSort, com.mongodb.client.model.Collation collation, Class> entityType,
Document replacement, FindAndReplaceOptions options, Class resultType) {
if (LOG.isDebugEnabled()) {
LOG.debug(
"findAndReplace using query: {} fields: {} sort: {} for class: {} and replacement: {} "
+ "in collection: {}",
SerializationUtils.serializeToJsonSafely(mappedQuery),
SerializationUtils.serializeToJsonSafely(mappedFields),
SerializationUtils.serializeToJsonSafely(mappedSort), entityType,
SerializationUtils.serializeToJsonSafely(replacement), collectionName);
}
maybeEmitEvent(new MongoBeforeSaveEvent(replacement, replacement, collectionName));
return executeFindOneInternal(
new FindAndReplaceCallback(mappedQuery, mappedFields, mappedSort, replacement, collation, options),
new ProjectingReadCallback<>(mapper, entityType, resultType, collectionName), collectionName);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findAndRemove(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.Class)
*/
@Override
public T findAndRemove(NoSQLQuery query, Class entityClass) {
return findAndRemove(query, entityClass, operations.determineCollectionName(entityClass));
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findAndRemove(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.Class, java.lang.String)
*/
@Override
public T findAndRemove(NoSQLQuery query, Class entityClass, String collectionName){
Assert.notNull(query, "Query must not be null!");
Assert.notNull(entityClass, "EntityClass must not be null!");
Assert.notNull(collectionName, "CollectionName must not be null!");
return doFindAndRemove(collectionName, query.getQueryObject(), query.getFieldsObject(),
getMappedSortObject(query, entityClass), entityClass);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findById(java.lang.Object, java.lang.Class)
*/
@Override
public T findById(Object id, Class entityClass) {
return findById(id, entityClass, operations.determineCollectionName(entityClass));
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findById(java.lang.Object, java.lang.Class, java.lang.String)
*/
@Override
public T findById(Object id, Class entityClass, String collectionName) {
Assert.notNull(id, "Id must not be null!");
Assert.notNull(entityClass, "EntityClass must not be null!");
Assert.notNull(collectionName, "CollectionName must not be null!");
String idKey = operations.getIdPropertyName(entityClass);
Object newId = operations.convertIdProperty(entityClass,id);
return doFindOne(collectionName, new Document(idKey, newId), new Document(), entityClass);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findOne(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.Class)
*/
@Override
public T findOne(NoSQLQuery query, Class entityClass) {
return findOne(query, entityClass, operations.determineCollectionName(entityClass));
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#findOne(br.com.anteros.nosql.persistence.session.query.NoSQLQuery, java.lang.Class, java.lang.String)
*/
@Override
public T findOne(NoSQLQuery query, Class entityClass, String collectionName) {
Assert.notNull(query, "Query must not be null!");
Assert.notNull(entityClass, "EntityClass must not be null!");
Assert.notNull(collectionName, "CollectionName must not be null!");
if (ObjectUtils.isEmpty(query.getSortObject())) {
return doFindOne(collectionName, query.getQueryObject(), query.getFieldsObject(), entityClass);
} else {
query.limit(1);
List results = find(query, entityClass, collectionName);
return results.isEmpty() ? null : results.get(0);
}
}
protected T doFindOne(String collectionName, Document query, Document fields, Class entityClass) {
if (LOG.isDebugEnabled()) {
LOG.debug("findOne using query: {} fields: {} for class: {} in collection: {}",
SerializationUtils.serializeToJsonSafely(query), fields, entityClass, collectionName);
}
return executeFindOneInternal(new FindOneCallback(query, fields),
new ReadDocumentCallback<>(this.mapper, entityClass, collectionName), collectionName);
}
private T executeFindOneInternal(CollectionCallback collectionCallback,
DocumentCallback objectCallback, String collectionName) {
try {
T result = objectCallback
.doWith(collectionCallback.doInCollection(getAndPrepareCollection(getDatabase(), collectionName)));
return result;
} catch (Exception e) {
throw translateRuntimeException(e, exceptionTranslator);
}
}
private MongoCollection getAndPrepareCollection(MongoDatabase db, String collectionName) {
try {
MongoCollection collection = db.getCollection(collectionName, Document.class);
collection = prepareCollection(collection);
return collection;
} catch (RuntimeException e) {
throw translateRuntimeException(e, exceptionTranslator);
}
}
protected MongoCollection prepareCollection(MongoCollection collection) {
if (this.readPreference != null) {
collection = collection.withReadPreference(readPreference);
}
return collection;
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#getCollectionName(java.lang.Class)
*/
@Override
public String getCollectionName(Class> entityClass) {
NoSQLDescriptionEntity descriptionEntity = getDescriptionEntity(entityClass);
return descriptionEntity.getCollectionName();
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#getCollectionName(java.lang.Object)
*/
@Override
public String getCollectionName(Object entity) {
return null == entity ? null : getCollectionName(entity.getClass());
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#getCollectionNames()
*/
@Override
public Set getCollectionNames() {
return execute(new DbCallback>() {
public Set doInDB(MongoDatabase db) throws MongoException, NoSQLDataAccessException {
Set result = new LinkedHashSet<>();
for (String name : db.listCollectionNames()) {
result.add(name);
}
return result;
}
});
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#group(br.com.anteros.nosql.persistence.session.query.NoSQLCriteria, java.lang.String, br.com.anteros.nosql.persistence.mongodb.session.GroupBy, java.lang.Class)
*/
@Override
public GroupByResults group(NoSQLCriteria criteria, String inputCollectionName, GroupBy groupBy,
Class entityClass) throws Exception {
Document document = groupBy.getGroupByObject();
document.put("ns", inputCollectionName);
Document query = criteria.getCriteriaObject();
if (criteria == null) {
document.put("cond", null);
} else {
document.put("cond", query);
}
// If initial document was a JavaScript string, potentially loaded by Spring's
// Resource abstraction, load it and
// convert to Document
if (document.containsKey("initial")) {
Object initialObj = document.get("initial");
if (initialObj instanceof String) {
String initialAsString = replaceWithResourceIfNecessary((String) initialObj);
document.put("initial", Document.parse(initialAsString));
}
}
if (document.containsKey("$reduce")) {
document.put("$reduce",
replaceWithResourceIfNecessary(ObjectUtils.nullSafeToString(document.get("$reduce"))));
}
if (document.containsKey("$keyf")) {
document.put("$keyf", replaceWithResourceIfNecessary(ObjectUtils.nullSafeToString(document.get("$keyf"))));
}
if (document.containsKey("finalize")) {
document.put("finalize",
replaceWithResourceIfNecessary(ObjectUtils.nullSafeToString(document.get("finalize"))));
}
Document commandObject = new Document("group", document);
if (LOG.isDebugEnabled()) {
LOG.debug("Executing Group with Document [{}]", SerializationUtils.serializeToJsonSafely(commandObject));
}
Document commandResult = executeCommand(commandObject, this.readPreference);
if (LOG.isDebugEnabled()) {
LOG.debug("Group command result = [{}]", commandResult);
}
@SuppressWarnings("unchecked")
Iterable resultSet = (Iterable) commandResult.get("retval");
List mappedResults = new ArrayList<>();
DocumentCallback callback = new ReadDocumentCallback<>(mapper, entityClass, inputCollectionName);
for (Document resultDocument : resultSet) {
mappedResults.add(callback.doWith(resultDocument));
}
return new GroupByResults<>(mappedResults, commandResult);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#group(java.lang.String, br.com.anteros.nosql.persistence.mongodb.session.GroupBy, java.lang.Class)
*/
@Override
public GroupByResults group(String inputCollectionName, GroupBy groupBy, Class entityClass)
throws Exception {
return group(null, inputCollectionName, groupBy, entityClass);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#insert(java.util.Collection, java.lang.Class)
*/
@SuppressWarnings("unchecked")
@Override
public Collection insert(Collection extends Object> batchToSave, Class> entityClass) throws Exception {
Assert.notNull(batchToSave, "BatchToSave must not be null!");
return (Collection) doInsertBatch(operations.determineCollectionName(entityClass), batchToSave);
}
/* (non-Javadoc)
* @see br.com.anteros.nosql.persistence.mongodb.session.MongoSession#insert(java.util.Collection, java.lang.String)
*/
@SuppressWarnings("unchecked")
@Override
public Collection insert(Collection extends Object> batchToSave, String collectionName) throws Exception {
Assert.notNull(batchToSave, "BatchToSave must not be null!");
Assert.notNull(collectionName, "CollectionName must not be null!");
return (Collection) doInsertBatch(collectionName, batchToSave);
}
@SuppressWarnings("unchecked")
protected Collection doInsertBatch(String collectionName, Collection extends T> batchToSave)
throws Exception {
List documentList = new ArrayList<>();
List initializedBatchToSave = new ArrayList<>(batchToSave.size());
for (T uninitialized : batchToSave) {
NoSQLEntityAdapter entity = operations.forEntity(uninitialized);
T toSave = entity.initializeVersionProperty();
toSave = (T) maybeEmitEvent(new MongoBeforeConvertEvent(toSave, new Document(), collectionName))
.getSource();
Document document = (Document) entity.toMappedDocument().getDocument();
MongoBeforeSaveEvent beforeSaveEvent = new MongoBeforeSaveEvent(toSave, document, collectionName);
maybeEmitEvent(beforeSaveEvent);
documentList.add(document);
initializedBatchToSave.add(toSave);
}
List