org.datanucleus.store.mongodb.MongoDBSchemaHandler Maven / Gradle / Ivy
/**********************************************************************
Copyright (c) 2014 Andy Jefferson and others. All rights reserved.
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.
Contributors:
...
**********************************************************************/
package org.datanucleus.store.mongodb;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import org.datanucleus.ClassLoaderResolver;
import org.datanucleus.exceptions.NucleusException;
import org.datanucleus.metadata.AbstractClassMetaData;
import org.datanucleus.metadata.AbstractMemberMetaData;
import org.datanucleus.metadata.ClassMetaData;
import org.datanucleus.metadata.ClassPersistenceModifier;
import org.datanucleus.metadata.IdentityType;
import org.datanucleus.metadata.IndexMetaData;
import org.datanucleus.metadata.RelationType;
import org.datanucleus.metadata.UniqueMetaData;
import org.datanucleus.store.StoreData;
import org.datanucleus.store.StoreManager;
import org.datanucleus.store.connection.ManagedConnection;
import org.datanucleus.store.schema.AbstractStoreSchemaHandler;
import org.datanucleus.store.schema.naming.NamingFactory;
import org.datanucleus.store.schema.table.Column;
import org.datanucleus.store.schema.table.CompleteClassTable;
import org.datanucleus.store.schema.table.MemberColumnMapping;
import org.datanucleus.store.schema.table.Table;
import org.datanucleus.util.Localiser;
import org.datanucleus.util.NucleusLogger;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
/**
* Handler for schema operations with MongoDB datastores.
*/
public class MongoDBSchemaHandler extends AbstractStoreSchemaHandler
{
public MongoDBSchemaHandler(StoreManager storeMgr)
{
super(storeMgr);
}
/* (non-Javadoc)
* @see org.datanucleus.store.schema.AbstractStoreSchemaHandler#createSchemaForClasses(java.util.Set, java.util.Properties, java.lang.Object)
*/
@Override
public void createSchemaForClasses(Set classNames, Properties props, Object connection)
{
DB db = (DB)connection;
ManagedConnection mconn = null;
try
{
if (db == null)
{
mconn = storeMgr.getConnection(-1);
db = (DB)mconn.getConnection();
}
Iterator classIter = classNames.iterator();
ClassLoaderResolver clr = storeMgr.getNucleusContext().getClassLoaderResolver(null);
while (classIter.hasNext())
{
String className = classIter.next();
AbstractClassMetaData cmd = storeMgr.getMetaDataManager().getMetaDataForClass(className, clr);
if (cmd != null)
{
createSchemaForClass(cmd, db);
}
}
}
finally
{
if (mconn != null)
{
mconn.release();
}
}
}
protected void createSchemaForClass(AbstractClassMetaData cmd, DB db)
{
if (cmd.isEmbeddedOnly() || cmd.getPersistenceModifier() != ClassPersistenceModifier.PERSISTENCE_CAPABLE)
{
// No table required here
return;
}
if (cmd instanceof ClassMetaData && ((ClassMetaData) cmd).isAbstract())
{
// No table required here
return;
}
StoreData storeData = storeMgr.getStoreDataForClass(cmd.getFullClassName());
Table table = null;
if (storeData != null)
{
table = storeData.getTable();
}
else
{
table = new CompleteClassTable(storeMgr, cmd, null);
}
String collectionName = table.getName();
DBCollection collection = null;
if (isAutoCreateTables() && !db.collectionExists(collectionName))
{
// Create collection (if not existing)
if (cmd.hasExtension(MongoDBStoreManager.CAPPED_SIZE_EXTENSION_NAME))
{
Set collNames = db.getCollectionNames();
if (!collNames.contains(collectionName))
{
// Collection specified as "capped" with a size and doesn't exist so create it
DBObject options = new BasicDBObject();
options.put("capped", "true");
Long size = Long.valueOf(cmd.getValueForExtension(MongoDBStoreManager.CAPPED_SIZE_EXTENSION_NAME));
options.put("size", size);
if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled())
{
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("MongoDB.Schema.CreateClass", cmd.getFullClassName(), collectionName));
}
db.createCollection(collectionName, options);
}
else
{
DBObject options = new BasicDBObject();
if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled())
{
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("MongoDB.Schema.CreateClass", cmd.getFullClassName(), collectionName));
}
collection = db.createCollection(collectionName, options);
}
}
else
{
DBObject options = new BasicDBObject();
if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled())
{
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("MongoDB.Schema.CreateClass", cmd.getFullClassName(), collectionName));
}
collection = db.createCollection(collectionName, options);
}
}
ClassLoaderResolver clr = storeMgr.getNucleusContext().getClassLoaderResolver(null);
if (autoCreateConstraints)
{
// Create indexes
if (collection == null && !db.getCollectionNames().contains(collectionName))
{
NucleusLogger.DATASTORE_SCHEMA.warn("Cannot create constraints for " + cmd.getFullClassName() +
" since collection of name " + collectionName + " doesn't exist (enable autoCreateTables?)");
return;
}
else if (collection == null)
{
collection = db.getCollection(collectionName);
}
// Class-level indexes
NamingFactory namingFactory = storeMgr.getNamingFactory();
AbstractClassMetaData theCmd = cmd;
while (theCmd != null)
{
IndexMetaData[] clsIdxMds = theCmd.getIndexMetaData();
if (clsIdxMds != null)
{
for (int i=0;i mappings = table.getMemberColumnMappings();
for (MemberColumnMapping mapping : mappings)
{
Column column = mapping.getColumn(0);
RelationType relType = mapping.getMemberMetaData().getRelationType(clr);
UniqueMetaData unimd = mapping.getMemberMetaData().getUniqueMetaData();
if (relType == RelationType.NONE && unimd != null) // Don't allow on relation fields since MongoDB would equate two null rows as breaking the constraint (on a String field)
{
BasicDBObject query = new BasicDBObject();
query.append(column.getName(), 1);
if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled())
{
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("MongoDB.Schema.CreateClassIndex", unimd.getName(), collectionName, query));
}
String idxName = unimd.getName();
if (idxName == null)
{
idxName = namingFactory.getConstraintName(cmd.getName(), mapping.getMemberMetaData(), unimd);
}
collection.createIndex(query, idxName, true);
}
else
{
IndexMetaData idxmd = mapping.getMemberMetaData().getIndexMetaData();
if (idxmd != null)
{
BasicDBObject query = new BasicDBObject();
query.append(column.getName(), 1);
String idxName = namingFactory.getConstraintName(cmd.getName(), mapping.getMemberMetaData(), idxmd);
if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled())
{
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("MongoDB.Schema.CreateClassIndex", idxName, collectionName, query));
}
collection.createIndex(query, idxName, idxmd.isUnique());
}
}
}
}
}
private DBObject getDBObjectForIndex(AbstractClassMetaData cmd, IndexMetaData idxmd, Table table)
{
BasicDBObject idxObj = new BasicDBObject();
if (idxmd.getNumberOfColumns() > 0)
{
String[] idxcolNames = idxmd.getColumnNames();
for (int j=0;j 0)
{
String[] idxMemberNames = idxmd.getMemberNames();
for (int i=0;i 0)
{
String[] unicolNames = unimd.getColumnNames();
for (int j=0;j classNames, Properties props, Object connection)
{
DB db = (DB)connection;
ManagedConnection mconn = null;
try
{
if (db == null)
{
mconn = storeMgr.getConnection(-1);
db = (DB)mconn.getConnection();
}
Iterator classIter = classNames.iterator();
ClassLoaderResolver clr = storeMgr.getNucleusContext().getClassLoaderResolver(null);
while (classIter.hasNext())
{
String className = classIter.next();
AbstractClassMetaData cmd = storeMgr.getMetaDataManager().getMetaDataForClass(className, clr);
if (cmd != null)
{
StoreData storeData = storeMgr.getStoreDataForClass(cmd.getFullClassName());
Table table = null;
if (storeData != null)
{
table = storeData.getTable();
}
else
{
table = new CompleteClassTable(storeMgr, cmd, null);
}
DBCollection collection = db.getCollection(table.getName());
collection.dropIndexes();
if (NucleusLogger.DATASTORE_SCHEMA.isDebugEnabled())
{
NucleusLogger.DATASTORE_SCHEMA.debug(Localiser.msg("MongoDB.SchemaDelete.Class", cmd.getFullClassName(), table.getName()));
}
collection.drop();
}
}
}
finally
{
if (mconn != null)
{
mconn.release();
}
}
}
/* (non-Javadoc)
* @see org.datanucleus.store.schema.AbstractStoreSchemaHandler#validateSchema(java.util.Set, java.util.Properties, java.lang.Object)
*/
@Override
public void validateSchema(Set classNames, Properties props, Object connection)
{
boolean success = true;
DB db = (DB)connection;
ManagedConnection mconn = null;
try
{
if (db == null)
{
mconn = storeMgr.getConnection(-1);
db = (DB)mconn.getConnection();
}
Iterator classIter = classNames.iterator();
ClassLoaderResolver clr = storeMgr.getNucleusContext().getClassLoaderResolver(null);
while (classIter.hasNext())
{
String className = classIter.next();
AbstractClassMetaData cmd = storeMgr.getMetaDataManager().getMetaDataForClass(className, clr);
if (cmd != null)
{
// Validate the schema for the class
StoreData storeData = storeMgr.getStoreDataForClass(cmd.getFullClassName());
Table table = null;
if (storeData != null)
{
table = storeData.getTable();
}
else
{
table = new CompleteClassTable(storeMgr, cmd, null);
}
String tableName = table.getName();
if (!db.collectionExists(tableName))
{
success = false;
String msg = Localiser.msg("MongoDB.SchemaValidate.Class", cmd.getFullClassName(), tableName);
System.out.println(msg);
NucleusLogger.DATASTORE_SCHEMA.error(msg);
continue;
}
String msg = "Table for class="+cmd.getFullClassName() + " with name="+tableName + " validated";
NucleusLogger.DATASTORE_SCHEMA.info(msg);
DBCollection dbColl = db.getCollection(tableName);
List indices = new ArrayList(dbColl.getIndexInfo());
IndexMetaData[] idxmds = cmd.getIndexMetaData();
if (idxmds != null && idxmds.length > 0)
{
for (int i=0;i indices, String idxName, DBObject idxObj, boolean unique)
{
if (indices == null || indices.isEmpty())
{
return null;
}
Iterator idxIter = indices.iterator();
while (idxIter.hasNext())
{
DBObject index = idxIter.next();
DBObject obj = null;
String name = (String) index.get("name");
if (name.equals(idxName))
{
obj = index;
if (unique)
{
boolean flag = (Boolean) index.get("unique");
if (!flag)
{
continue;
}
}
boolean equal = true;
DBObject key = (DBObject)index.get("key");
if (key.toMap().size() != idxObj.toMap().size())
{
equal = false;
}
else
{
Iterator indicKeyIter = key.keySet().iterator();
while (indicKeyIter.hasNext())
{
String fieldKey = indicKeyIter.next();
Object fieldValue = key.get(fieldKey);
if (!idxObj.containsField(fieldKey))
{
equal = false;
}
else
{
Object idxObjValue = idxObj.get(fieldKey);
if (!idxObjValue.equals(fieldValue))
{
equal = false;
}
}
}
}
if (equal)
{
return obj;
}
}
}
return null;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy