Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
152 changes: 81 additions & 71 deletions cayenne-server/src/main/java/org/apache/cayenne/access/DbLoader.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,12 @@
****************************************************************/
package org.apache.cayenne.access;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import org.apache.cayenne.access.loader.DbLoaderConfiguration;
import org.apache.cayenne.access.loader.ManyToManyCandidateEntity;
import org.apache.cayenne.access.loader.filters.DbPath;
import org.apache.cayenne.access.loader.filters.EntityFilters;
import org.apache.cayenne.access.loader.filters.Filter;
import org.apache.cayenne.access.loader.filters.FiltersConfig;
import org.apache.cayenne.access.loader.filters.DbPath;
import org.apache.cayenne.dba.DbAdapter;
import org.apache.cayenne.dba.TypesMapping;
import org.apache.cayenne.map.DataMap;
Expand All @@ -59,7 +45,23 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import static org.apache.cayenne.access.loader.filters.FilterFactory.*;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;

import static org.apache.cayenne.access.loader.filters.FilterFactory.NULL;
import static org.apache.cayenne.access.loader.filters.FilterFactory.TRUE;
import static org.apache.cayenne.access.loader.filters.FilterFactory.include;

/**
* Utility class that does reverse engineering of the database. It can create
Expand Down Expand Up @@ -95,7 +97,7 @@ public DbLoader(Connection connection, DbAdapter adapter, DbLoaderDelegate deleg

/**
* Creates new DbLoader with specified naming strategy.
*
*
* @since 3.0
*/
public DbLoader(Connection connection, DbAdapter adapter, DbLoaderDelegate delegate, ObjectNameGenerator strategy) {
Expand Down Expand Up @@ -135,7 +137,7 @@ public boolean isCreatingMeaningfulPK() {

/**
* Returns database connection used by this DbLoader.
*
*
* @since 3.0
*/
public Connection getConnection() {
Expand All @@ -144,7 +146,7 @@ public Connection getConnection() {

/**
* Returns DbAdapter associated with this DbLoader.
*
*
* @since 1.1
*/
public DbAdapter getAdapter() {
Expand All @@ -153,7 +155,7 @@ public DbAdapter getAdapter() {

/**
* Retrieves catalogs for the database associated with this DbLoader.
*
*
* @return List with the catalog names, empty Array if none found.
*/
public List<String> getCatalogs() throws SQLException {
Expand All @@ -162,7 +164,7 @@ public List<String> getCatalogs() throws SQLException {

/**
* Retrieves the schemas for the database.
*
*
* @return List with the schema names, empty Array if none found.
*/
public List<String> getSchemas() throws SQLException {
Expand All @@ -184,9 +186,9 @@ private static List<String> getStrings(ResultSet rs) throws SQLException {
/**
* Returns all the table types for the given database. Types may be such as
* Typical types are "TABLE",
* "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
* "LOCAL TEMPORARY", "ALIAS", "SYNONYM"., etc.
*
* "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY",
* "LOCAL TEMPORARY", "ALIAS", "SYNONYM"., etc.
*
* @return List of Strings, empty array if nothing found.
*/
public List<String> getTableTypes() throws SQLException {
Expand All @@ -206,12 +208,9 @@ public List<String> getTableTypes() throws SQLException {
/**
* Returns all tables for given combination of the criteria. Tables returned
* as DbEntities without any attributes or relationships.
*
*
* @param config
*
* @param types
* The types of table names to retrieve, null returns all types.
* @param types The types of table names to retrieve, null returns all types.
* @return
* @since 3.2
*/
Expand All @@ -231,12 +230,10 @@ public Map<DbPath, Map<String, DbEntity>> getTables(DbLoaderConfiguration config
}

/**
*
* @param filters
* @param dbPath
* @param types
* @return Map<TableName, DbEntity>
*
* @throws SQLException
*/
private Map<String, DbEntity> getDbEntities(FiltersConfig filters, DbPath dbPath, String[] types) throws SQLException {
Expand Down Expand Up @@ -280,13 +277,11 @@ private Map<String, DbEntity> getDbEntities(FiltersConfig filters, DbPath dbPath

/**
* Loads dbEntities for the specified tables.
*
* @param map
* DataMap to be populated with DbEntities.
*
* @param map DataMap to be populated with DbEntities.
* @param config
* @param tables
* The list of org.apache.cayenne.ashwood.dbutil.Table objects
* for which DbEntities must be created. @return false if loading must be immediately aborted.
* @param tables The list of org.apache.cayenne.ashwood.dbutil.Table objects
* for which DbEntities must be created. @return false if loading must be immediately aborted.
*/
public List<DbEntity> loadDbEntities(DataMap map, DbLoaderConfiguration config, Map<DbPath, Map<String, DbEntity>> tables) throws SQLException {
/** List of db entities to process. */
Expand All @@ -299,8 +294,20 @@ public List<DbEntity> loadDbEntities(DataMap map, DbLoaderConfiguration config,
// if so, consult the delegate what to do
DbEntity oldEnt = map.getDbEntity(dbEntity.getName());
if (oldEnt != null) {
Collection<ObjEntity> oldObjEnt = map.getMappedEntities(oldEnt);
if (!oldObjEnt.isEmpty()) {
for (ObjEntity objEntity : oldObjEnt) {
LOGGER.debug("Delete ObjEntity: " + objEntity.getName());
map.removeObjEntity(objEntity.getName(), true);
delegate.objEntityRemoved(objEntity);
}
}

LOGGER.debug("Overwrite DbEntity: " + oldEnt.getName());
map.removeDbEntity(oldEnt.getName(), true);
delegate.dbEntityRemoved(oldEnt);
}

map.addDbEntity(dbEntity);

// notify delegate
Expand Down Expand Up @@ -432,9 +439,9 @@ private DbAttribute loadDbAttribute(ResultSet rs) throws SQLException {
* Creates an ObjEntity for each DbEntity in the map. ObjEntities are
* created empty without
*/
protected void loadObjEntities(DataMap map, DbLoaderConfiguration config, Collection<DbEntity> entities) {
protected Collection<ObjEntity> loadObjEntities(DataMap map, DbLoaderConfiguration config, Collection<DbEntity> entities) {
if (entities.isEmpty()) {
return;
return null;
}

Collection<ObjEntity> loadedEntities = new ArrayList<ObjEntity>(entities.size());
Expand All @@ -443,14 +450,14 @@ protected void loadObjEntities(DataMap map, DbLoaderConfiguration config, Collec
for (DbEntity dbEntity : entities) {

// check if there are existing entities
// TODO: performance. This is an O(n^2) search and it shows on
// YourKit profiles. Pre-cache mapped entities perhaps (?)
Collection<ObjEntity> existing = map.getMappedEntities(dbEntity);
if (!existing.isEmpty()) {
loadedEntities.addAll(existing);
continue;
}

// TODO: performance. This is an O(n^2) search and it shows on
// YourKit profiles. Pre-cache mapped entities perhaps (?)
Collection<ObjEntity> existing = map.getMappedEntities(dbEntity);
if (!existing.isEmpty()) {
loadedEntities.addAll(existing);
continue;
}

String objEntityName = DefaultUniqueNameGenerator.generate(NameCheckers.objEntity, map,
nameGenerator.createObjEntityName(dbEntity));
Expand All @@ -466,6 +473,8 @@ protected void loadObjEntities(DataMap map, DbLoaderConfiguration config, Collec

// update ObjEntity attributes and relationships
createEntityMerger(map).synchronizeWithDbEntities(loadedEntities);

return loadedEntities;
}

/**
Expand Down Expand Up @@ -625,7 +634,7 @@ protected void postProcessMasterDbRelationship(DbRelationship relationship, Expo
/**
* Flattens many-to-many relationships in the generated model.
*/
private void flattenManyToManyRelationships(DataMap map) {
private void flattenManyToManyRelationships(DataMap map, Collection<ObjEntity> loadedObjEntities) {
Collection<ObjEntity> entitiesForDelete = new LinkedList<ObjEntity>();

for (ObjEntity curEntity : map.getObjEntities()) {
Expand All @@ -641,10 +650,11 @@ private void flattenManyToManyRelationships(DataMap map) {
for (ObjEntity curDeleteEntity : entitiesForDelete) {
map.removeObjEntity(curDeleteEntity.getName(), true);
}
loadedObjEntities.removeAll(entitiesForDelete);
}

private void fireObjEntitiesAddedEvents(DataMap map) {
for (ObjEntity curEntity : map.getObjEntities()) {
private void fireObjEntitiesAddedEvents(Collection<ObjEntity> loadedObjEntities) {
for (ObjEntity curEntity : loadedObjEntities) {
// notify delegate
if (delegate != null) {
delegate.objEntityAdded(curEntity);
Expand Down Expand Up @@ -678,31 +688,31 @@ public String[] getDefaultTableTypes() {
* Performs database reverse engineering and generates DataMap that contains
* default mapping of the tables and views. By default will include regular
* tables and views.
*
*
* @since 1.0.7
* @deprecated since 4.0 use
* {@link #load(org.apache.cayenne.map.DataMap, DbLoaderConfiguration, String...)}
* method that supports catalogs.
* {@link #load(org.apache.cayenne.map.DataMap, DbLoaderConfiguration, String...)}
* method that supports catalogs.
*/
@Deprecated
public DataMap loadDataMapFromDB(String schemaPattern, String tablePattern, DataMap dataMap) throws SQLException {
public DataMap loadDataMapFromDB(String schemaPattern, String tablePattern, DataMap dataMap) throws SQLException {

DbLoaderConfiguration configuration = new DbLoaderConfiguration();
configuration.setFiltersConfig(new FiltersConfig(new EntityFilters(new DbPath(null, schemaPattern),
include(tablePattern), TRUE, NULL)));
DbLoaderConfiguration configuration = new DbLoaderConfiguration();
configuration.setFiltersConfig(new FiltersConfig(new EntityFilters(new DbPath(null, schemaPattern),
include(tablePattern), TRUE, NULL)));

load(dataMap, configuration);
return dataMap;
}
load(dataMap, configuration);
return dataMap;
}

/**
* Performs database reverse engineering and generates DataMap object that
* contains default mapping of the tables and views. Allows to limit types
* of tables to read.
*
*
* @deprecated since 4.0 use
* {@link #load(org.apache.cayenne.map.DataMap, DbLoaderConfiguration, String...)}
* method that supports catalogs.
* {@link #load(org.apache.cayenne.map.DataMap, DbLoaderConfiguration, String...)}
* method that supports catalogs.
*/
@Deprecated
public DataMap loadDataMapFromDB(String schemaPattern, String tablePattern, String[] tableTypes, DataMap dataMap)
Expand All @@ -729,7 +739,7 @@ private Filter<String> transformPatternToFilter(String tablePattern) {
}

/**
* Performs database reverse engineering based on the specified config
* Performs database reverse engineering based on the specified config
* and fills the specified
* DataMap object with DB and object mapping info.
*
Expand All @@ -742,10 +752,10 @@ public void load(DataMap dataMap, DbLoaderConfiguration config, String... tableT

if (entities != null) {
loadDbRelationships(config, tables);
Collection<ObjEntity> loadedObjEntities = loadObjEntities(dataMap, config, entities);

loadObjEntities(dataMap, config, entities);
flattenManyToManyRelationships(dataMap);
fireObjEntitiesAddedEvents(dataMap);
flattenManyToManyRelationships(dataMap, loadedObjEntities);
fireObjEntitiesAddedEvents(loadedObjEntities);
}
}

Expand Down Expand Up @@ -773,7 +783,7 @@ public DataMap load(DbLoaderConfiguration config) throws SQLException {
* currently this method is NOT CALLED from "loadDataMapFromDB" and should
* be invoked explicitly by the user. </i>
* </p>
*
*
* @since 1.1
* @deprecated since 4.0 use loadProcedures(DataMap, String, String, String) that supports "catalog" pattern.
*/
Expand All @@ -794,7 +804,7 @@ public void loadProceduresFromDB(String schemaPattern, String namePattern, DataM
* currently this method is NOT CALLED from "loadDataMapFromDB" and should
* be invoked explicitly by the user. </i>
* </p>
*
*
* @since 4.0
*/
public Map<String, Procedure> loadProcedures(DataMap dataMap, DbLoaderConfiguration config)
Expand Down Expand Up @@ -822,7 +832,7 @@ private void loadProceduresColumns(DbLoaderConfiguration config, Map<String, Pro

String schema = columnsRS.getString("PROCEDURE_SCHEM");
String name = columnsRS.getString("PROCEDURE_NAME");
String key = (schema == null ? "" : schema + '.') + name ;
String key = (schema == null ? "" : schema + '.') + name;
Procedure procedure = procedures.get(key);
if (procedure == null) {
continue;
Expand Down Expand Up @@ -926,7 +936,7 @@ private Map<String, Procedure> loadProcedures(FiltersConfig filters, DbPath dbPa
procedure.setSchema(rs.getString("PROCEDURE_SCHEM"));

if (filters.filter(new DbPath(procedure.getCatalog(), procedure.getSchema()))
.procedureFilter().isInclude(procedure)) {
.procedureFilter().isInclude(procedure)) {
LOGGER.info("skipping Cayenne PK procedure: " + name);
continue;
}
Expand All @@ -951,7 +961,7 @@ private Map<String, Procedure> loadProcedures(FiltersConfig filters, DbPath dbPa

/**
* Sets new naming strategy for reverse engineering
*
*
* @since 3.0
*/
public void setNameGenerator(ObjectNameGenerator strategy) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@

package org.apache.cayenne.access;

import org.apache.cayenne.CayenneException;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.ObjEntity;

Expand All @@ -30,13 +29,6 @@
*/
public interface DbLoaderDelegate {

/**
* Returns true to tell DbLoader that it is OK to overwrite DbEntity that
* already exists in the model. If loading process should be stopped
* immediately, an exception is thrown.
*/
boolean overwriteDbEntity(DbEntity entity) throws CayenneException;

void dbEntityAdded(DbEntity entity);

void dbEntityRemoved(DbEntity entity);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
****************************************************************/
package org.apache.cayenne.access.loader;

import org.apache.cayenne.CayenneException;
import org.apache.cayenne.access.DbLoaderDelegate;
import org.apache.cayenne.map.DbEntity;
import org.apache.cayenne.map.ObjEntity;
Expand All @@ -28,11 +27,6 @@
*/
public class DefaultDbLoaderDelegate implements DbLoaderDelegate {

@Override
public boolean overwriteDbEntity(DbEntity entity) throws CayenneException {
return false;
}

@Override
public void dbEntityAdded(DbEntity entity) {

Expand Down
Loading