简体   繁体   中英

Avoiding table changes when mapping legacy database tables in Grails?

I have an applicaton that contains some tables that are auto-generated from Grails domain classes and one legacy table (say table legacy ) that have been created outside of Grails but are being mapped by Grails domain classes. Mapping the columns in the legacy database is trivial, but I would like to disable the adding of extra fields and indexes that Grails tries to take care of for said table.

My question is:

Please note that I do not want to disable the automatic schema generation/updating for all tables, only for the mapped table legacy .

The only way I've been able to do stuff like this is a custom Configuration class:

package com.foo.bar;

import java.util.ArrayList;
import java.util.List;

import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.HSQLDialect;
import org.hibernate.tool.hbm2ddl.DatabaseMetadata;

public class DdlFilterConfiguration extends GrailsAnnotationConfiguration {

   private static final String[] IGNORE_NAMES = { "legacy" };

   @Override
   public String[] generateSchemaCreationScript(Dialect dialect) throws HibernateException {
      return prune(super.generateSchemaCreationScript(dialect), dialect);
   }

   @Override
   public String[] generateDropSchemaScript(Dialect dialect) throws HibernateException {
      return prune(super.generateDropSchemaScript(dialect), dialect);
   }

   @Override
   public String[] generateSchemaUpdateScript(Dialect dialect, DatabaseMetadata databaseMetadata) throws HibernateException {
      return prune(super.generateSchemaUpdateScript(dialect, databaseMetadata), dialect);
   }

   private String[] prune(String[] script, Dialect dialect) {
      if (dialect instanceof HSQLDialect) {
         // do nothing for test env
         return script;
      }

      List<String> pruned = new ArrayList<String>();
      for (String command : script) {
         if (!isIgnored(command)) {
            pruned.add(command);
         }
      }

      return pruned.toArray(new String[pruned.size()]);
   }

   private boolean isIgnored(String command) {
      command = command.toLowerCase();
      for (String table : IGNORED_NAMES) {
         if (command.startsWith("create table " + table + " ") ||
               command.startsWith("alter table " + table + " ") ||
               command.startsWith("drop table " + table + " ")) {
            return true;
         }
      }
      return false;
   }
}

Put this in src/java (it can't be written in Groovy because of a weird compilation error) and register it in DataSource.groovy using the 'configClass' attribute:

dataSource {
   pooled = true
   driverClassName = ...
   username = ...
   password = ...
   dialect = ...
   configClass = com.foo.bar.DdlFilterConfiguration
}

My solution was a bit simpler.

in the mapping section of the Domain class, I just set version false and I named the 'id' column.

class DomainClass {
    static mapping = {
        table 'legacyName'
        version false
        columns{
            id column: 'legacy_id'
        }
    }
}

You can try using Hibernate annotations to specify things such as column name, table, etc instead of creating a normal domain class. For more info see the "Mapping with Hibernate Annotations" section of the following link. http://www.grails.org/Hibernate+Integration

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM