jodd.db.oom.DbEntityManager Maven / Gradle / Ivy
// Copyright (c) 2003-present, Jodd Team (http://jodd.org)
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
package jodd.db.oom;
import jodd.cache.TypeCache;
import jodd.db.oom.naming.ColumnNamingStrategy;
import jodd.db.oom.naming.TableNamingStrategy;
import jodd.log.Logger;
import jodd.log.LoggerFactory;
import jodd.util.ClassUtil;
import jodd.util.StringUtil;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
/**
* DbOom Entity manager.
*
* Important: configure settings before entity registration!
*
* Mapping definitions are used only by a result set mapper (such as {@link jodd.db.oom.mapper.ResultSetMapper})
* to lookup for an entity from table name. Table names are read from result-set meta data, for example.
* It is not needed to use mappings at all: in that case just provide entity types during the conversion of
* result set to objects.
*/
public class DbEntityManager {
private static final Logger log = LoggerFactory.getLogger(DbEntityManager.class);
private final DbOomConfig dbOomConfig;
public DbEntityManager(final DbOomConfig dbOomConfig) {
this.dbOomConfig = dbOomConfig;
}
// ---------------------------------------------------------------- registration
protected String[] primitiveEntitiesPrefixes = new String[] {
"java.lang.",
"jodd.mutable.",
int.class.getName(),
long.class.getName(),
float.class.getName(),
double.class.getName(),
short.class.getName(),
boolean.class.getName(),
byte.class.getName()};
public String[] getPrimitiveEntitiesPrefixes() {
return primitiveEntitiesPrefixes;
}
/**
* Specifies array of class name prefixes that will be mapped directly to column.
*/
public void setPrimitiveEntitiesPrefixes(final String... primitiveEntitiesPrefixes) {
this.primitiveEntitiesPrefixes = primitiveEntitiesPrefixes;
}
protected TypeCache descriptorsMap = TypeCache.createDefault();
protected Map entityNamesMap = new HashMap<>();
protected Map tableNamesMap = new NamedValuesHashMap<>();
/**
* Lookups {@link DbEntityDescriptor} for some type and registers the type if is new.
*
* Returns null
for core classes from java
run-time packages!
* Some types are not entities, i.e. domain objects. Instead, primitive entities
* are simply mapped to one column.
*/
public DbEntityDescriptor lookupType(final Class type) {
String typeName = type.getName();
if (StringUtil.startsWithOne(typeName, primitiveEntitiesPrefixes) != -1) {
return null;
}
DbEntityDescriptor ded = descriptorsMap.get(type);
if (ded == null) {
ded = registerType(type);
}
return ded;
}
/**
* Lookups for {@link jodd.db.oom.DbEntityDescriptor} that was registered with this manager.
* Returns null
if name not found.
*/
public DbEntityDescriptor lookupName(final String typeName) {
return entityNamesMap.get(typeName);
}
/**
* Lookups for {@link jodd.db.oom.DbEntityDescriptor} that was registered with this manager.
* Returns null
if table name not found. Lookup is case-insensitive.
*/
public DbEntityDescriptor lookupTableName(final String tableName) {
return tableNamesMap.get(tableName);
}
/**
* Registers just type and entity names. Enough for most usages.
*/
public DbEntityDescriptor registerType(final Class type) {
DbEntityDescriptor ded = createDbEntityDescriptor(type);
DbEntityDescriptor existing = descriptorsMap.put(type, ded);
if (log.isDebugEnabled()) {
log.debug("Register " + type.getName() + " as " + ded.getTableName());
}
if (existing != null) {
if (ded.getType() == type) {
return ded;
}
throw new DbOomException("Type already registered: " + existing.getType());
}
existing = entityNamesMap.put(ded.getEntityName(), ded);
if (existing != null) {
throw new DbOomException("Name '" + ded.getEntityName() + "' already mapped to an entity: " + existing.getType());
}
return ded;
}
/**
* Registers entity. {@link #registerType(Class) Registers types} and table names.
*/
public DbEntityDescriptor registerEntity(final Class type) {
DbEntityDescriptor ded = registerType(type);
DbEntityDescriptor existing = tableNamesMap.put(ded.getTableName(), ded);
if (existing != null) {
if (ded.getType() == type) {
return ded;
}
throw new DbOomException("Entity registration failed! Table '" + ded.getTableName() + "' already mapped to an entity: " + existing.getType());
}
return ded;
}
/**
* Registers entity. Existing entity will be removed if exist, so no exception will be thrown.
*/
public DbEntityDescriptor registerEntity(final Class type, final boolean force) {
if (force) {
removeEntity(type);
}
return registerEntity(type);
}
/**
* Removes entity and returns removed descriptor.
*/
public DbEntityDescriptor removeEntity(final Class type) {
DbEntityDescriptor ded = descriptorsMap.remove(type);
if (ded == null) {
ded = createDbEntityDescriptor(type);
}
entityNamesMap.remove(ded.getEntityName());
tableNamesMap.remove(ded.getTableName());
return ded;
}
/**
* Creates {@link DbEntityDescriptor}.
*/
protected DbEntityDescriptor createDbEntityDescriptor(final Class type) {
final String schemaName = dbOomConfig.getSchemaName();
final TableNamingStrategy tableNames = dbOomConfig.getTableNames();
final ColumnNamingStrategy columnNames = dbOomConfig.getColumnNames();
return new DbEntityDescriptor<>(type, schemaName, tableNames, columnNames);
}
// ---------------------------------------------------------------- stats
/**
* Returns total number of registered entity names.
*/
public int getTotalNames() {
return entityNamesMap.size();
}
/**
* Returns total number of registered table names.
*/
public int getTotalTableNames() {
return tableNamesMap.size();
}
/**
* Returns total number of registered types.
*/
public int getTotalTypes() {
return descriptorsMap.size();
}
/**
* Resets the manager and clears descriptors maps.
*/
public void reset() {
descriptorsMap.clear();
entityNamesMap.clear();
tableNamesMap.clear();
}
/**
* Creates new entity instances.
*/
public E createEntityInstance(final Class type) {
try {
return ClassUtil.newInstance(type);
} catch (Exception ex) {
throw new DbOomException(ex);
}
}
public void forEachEntity(final Consumer consumer) {
descriptorsMap.forEachValue(consumer);
}
}