Author: tchemit Date: 2011-03-17 14:32:57 +0100 (Thu, 17 Mar 2011) New Revision: 2228 Url: http://nuiton.org/repositories/revision/topia/2228 Log: try to solve Anomalie #1399: Database migration must not run if database schema doesn't exists improve migration engine class Modified: trunk/topia-service-migration/src/main/java/org/nuiton/topia/migration/TopiaMigrationEngine.java Modified: trunk/topia-service-migration/src/main/java/org/nuiton/topia/migration/TopiaMigrationEngine.java =================================================================== --- trunk/topia-service-migration/src/main/java/org/nuiton/topia/migration/TopiaMigrationEngine.java 2011-03-17 09:59:22 UTC (rev 2227) +++ trunk/topia-service-migration/src/main/java/org/nuiton/topia/migration/TopiaMigrationEngine.java 2011-03-17 13:32:57 UTC (rev 2228) @@ -31,6 +31,7 @@ import org.hibernate.cfg.Configuration; import org.nuiton.topia.TopiaContext; import org.nuiton.topia.TopiaException; +import org.nuiton.topia.TopiaNotFoundException; import org.nuiton.topia.TopiaRuntimeException; import org.nuiton.topia.event.TopiaContextAdapter; import org.nuiton.topia.event.TopiaContextEvent; @@ -45,6 +46,7 @@ import org.nuiton.util.VersionUtil; import org.nuiton.util.VersionUtil.VersionComparator; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; @@ -88,6 +90,13 @@ /** Drapeau pour savoir si la base est versionnée ou non */ protected boolean dbNotVersioned; + /** + * A flag to know if none of the dealed entities tables exists in db. + * + * @since 2.5.3 + */ + protected boolean dbEmpty; + /** Un drapeau pour effectuer la migration au demarrage (initialise en pre-init) */ protected boolean migrateOnInit; @@ -198,17 +207,17 @@ log.debug("Use callback - " + callbackStr); } - migrateOnInit = Boolean.valueOf(config.getProperty(MIGRATION_MIGRATE_ON_INIT, "true")); + migrateOnInit = Boolean.valueOf(config.getProperty(MIGRATION_MIGRATE_ON_INIT, String.valueOf(Boolean.TRUE))); if (log.isDebugEnabled()) { log.debug("Migrate on init - " + migrateOnInit); } - showSql = Boolean.valueOf(config.getProperty(MIGRATION_SHOW_SQL, "false")); + showSql = Boolean.valueOf(config.getProperty(MIGRATION_SHOW_SQL, String.valueOf(Boolean.FALSE))); if (log.isDebugEnabled()) { log.debug("Show sql - " + showSql); } - showProgression = Boolean.valueOf(config.getProperty(MIGRATION_SHOW_PROGRESSION, "false")); + showProgression = Boolean.valueOf(config.getProperty(MIGRATION_SHOW_PROGRESSION, String.valueOf(Boolean.FALSE))); if (log.isDebugEnabled()) { log.debug("Show progression - " + showProgression); } @@ -228,7 +237,7 @@ configuration.addClass(aClass); } - versionConfiguration = creaHibernateConfiguration(configuration); + versionConfiguration = createHibernateConfiguration(configuration); init = true; @@ -290,16 +299,28 @@ Version version = callback.getApplicationVersion(); - log.info(_("topia.migration.start.migration", version.getVersion(), dbVersion.getVersion())); + log.info(_("topia.migration.start.migration", + version.getVersion(), + dbVersion.getVersion()) + ); if (log.isDebugEnabled()) { log.debug("Migrate schema to version = " + dbVersion); log.debug("is db not versionned ? = " + dbNotVersioned); + log.debug("is db empty ? = " + dbEmpty); log.debug("TMSVersion exists = " + versionTableExist); } + if (dbEmpty) { + + // db is empty (no table, no migration to apply) + return true; + } + if (versionTableExist && dbVersion.equals(version)) { - log.info(_("topia.migration.skip.migration.db.is.up.to.date")); + if (log.isInfoEnabled()) { + log.info(_("topia.migration.skip.migration.db.is.up.to.date")); + } // la base est a jour return true; } @@ -317,7 +338,9 @@ // on a trouvee une table depreciee tmsVersion avec la bonne version de base // il suffit donc d'enregister la version dans la nouvelle table - log.info(_("topia.migration.skip.migration.db.is.up.to.date")); + if (log.isInfoEnabled()) { + log.info(_("topia.migration.skip.migration.db.is.up.to.date")); + } // la base est a jour mais il faut migrer la table saveApplicationVersion(); return true; @@ -326,7 +349,9 @@ SortedSet<Version> allVersions = new TreeSet<Version>(new VersionComparator()); allVersions.addAll(Arrays.asList(callback.getAvailableVersions())); - log.info(_("topia.migration.available.versions", allVersions)); + if (log.isInfoEnabled()) { + log.info(_("topia.migration.available.versions", allVersions)); + } // tell if migration is needed boolean needToMigrate = false; @@ -343,9 +368,13 @@ ); if (versionsToApply.isEmpty()) { - log.info(_("topia.migration.skip.migration.no.version.to.apply")); + if (log.isInfoEnabled()) { + log.info(_("topia.migration.skip.migration.no.version.to.apply")); + } } else { - log.info(_("topia.migration.migrate.versions", versionsToApply)); + if (log.isInfoEnabled()) { + log.info(_("topia.migration.migrate.versions", versionsToApply)); + } // perform the migration needToMigrate = callback.doMigration(rootContext, @@ -399,7 +428,7 @@ if (log.isDebugEnabled()) { log.debug("Save version = " + version); - log.debug("table exists = " + versionTableExist); + log.debug("Table exists = " + versionTableExist); log.debug("Detected version = " + dbVersion); } @@ -431,7 +460,9 @@ // delete all previous data in table TMSVersionDAO.deleteAll(tx); - log.info(_("topia.migration.saving.db.version", version)); + if (log.isInfoEnabled()) { + log.info(_("topia.migration.saving.db.version", version)); + } // create new version and store it in table TMSVersion tmsVersion = @@ -475,8 +506,9 @@ * Recupere depuis la base les états internes du service : * <p/> * <ul> - * <li>versionTableExist</li> - * <li>dbVersion</li> + * <li>{@link #versionTableExist}</li> + * <li>{@link #dbVersion}</li> + * <li>{@link #dbEmpty}</li> * </ul> */ protected void detectDbVersion() { @@ -490,6 +522,14 @@ return; } + // compute dbempty field value + dbEmpty = detectDbEmpty(); + + if (log.isDebugEnabled()) { + log.debug("Db is empty : " + dbEmpty); + } + + Version v = null; try { @@ -498,6 +538,9 @@ TopiaUtil.isSchemaExist(versionConfiguration, TMSVersion.class.getName()); + // check if at least one class exists in db + + if (log.isDebugEnabled()) { log.debug("Table " + TMSVersionDAO.TABLE_NAME + " exist = " + versionTableExist); } @@ -513,7 +556,7 @@ Configuration conf = new Configuration(); conf.addXML(TMSVersionDAO.LEGACY_MAPPING); - legacyVersionConfiguration = creaHibernateConfiguration(conf); + legacyVersionConfiguration = createHibernateConfiguration(conf); legacyVersionTableExist = TopiaUtil.isSchemaExist(legacyVersionConfiguration, TMSVersion.class.getName()); @@ -552,6 +595,54 @@ } } + /** + * Detects if there is some schema existing for at least one of the dealed + * entity of the underlying db context. + * + * @return {@code true} if there is no schema for any of the dealed entities, + * {@code false} otherwise. + * @since 2.5.3 + */ + protected boolean detectDbEmpty() { + + boolean result = true; + + try { + // get db real hibernate configuration + Configuration rootConfiguration = + rootContext.getHibernateConfiguration(); + + // get all dealed classes + List<Class<?>> persistenceClasses = + new ArrayList<Class<?>>(rootContext.getPersistenceClasses()); + + // remove the tmsversion class + persistenceClasses.remove(TMSVersion.class); + + for (Class<?> persistenceClass : persistenceClasses) { + + boolean tableExist = + TopiaUtil.isSchemaExist(rootConfiguration, + persistenceClass.getName() + ); + if (tableExist) { + + // at least one table exists + result = false; + + if (log.isDebugEnabled()) { + log.debug("Detected table for " + persistenceClass); + } + break; + } + } + } catch (TopiaNotFoundException e) { + throw new RuntimeException(e); + } + + return result; + } + protected Version getVersion(boolean versionTableExist, String tableName) { if (!versionTableExist) { @@ -587,7 +678,26 @@ } } + /** + * Creates the hibernate configuration to be used by the service. + * + * @param configuration the incoming hibernate configuration + * @return the complete configuration usable by the service + * @deprecated since 2.5.3, prefer to use the method {@link #createHibernateConfiguration(Configuration)} + */ + @Deprecated protected Configuration creaHibernateConfiguration(Configuration configuration) { + return createHibernateConfiguration(configuration); + } + + /** + * Creates the hibernate configuration to be used by the service. + * + * @param configuration the incoming hibernate configuration + * @return the complete configuration usable by the service + * @since 2.5.3 + */ + protected Configuration createHibernateConfiguration(Configuration configuration) { Properties config = rootContext.getConfig(); Properties prop = new Properties();