在 Grails 中映射遗留数据库表时避免表更改?

Posted

技术标签:

【中文标题】在 Grails 中映射遗留数据库表时避免表更改?【英文标题】:Avoiding table changes when mapping legacy database tables in Grails? 【发布时间】:2009-12-30 23:41:30 【问题描述】:

我有一个应用程序,其中包含一些从 Grails 域类自动生成的表和一个在 Grails 外部创建但正在由 Grails 域类映射的旧表(例如表 legacy)。映射遗留数据库中的列是微不足道的,但我想禁用 Grails 尝试为所述表处理的额外字段和索引的添加。

我的问题是:我如何指示 Grails 不要对 legacy 表进行 任何 表更改(例如添加索引、外键、版本列等更改) ?

请注意,我不想为所有表禁用自动模式生成/更新,仅对映射表 legacy 禁用。

【问题讨论】:

【参考方案1】:

我能够做这样的事情的唯一方法是自定义配置类:

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;
   

把它放在 src/java 中(因为一个奇怪的编译错误,它不能用 Groovy 编写)并使用 'configClass' 属性在 DataSource.groovy 中注册它:

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

【讨论】:

【参考方案2】:

我的解决方案有点简单。

在 Domain 类的映射部分,我只设置了 version false 并命名了 'id' 列。

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

【讨论】:

这在 2009 年首次提出问题时可能是不可能的;但是,现在肯定是正确的答案。【参考方案3】:

您可以尝试使用 Hibernate 注释来指定列名、表等内容,而不是创建普通的域类。有关更多信息,请参阅以下链接的“使用 Hibernate Annotations 映射”部分。 http://www.grails.org/Hibernate+Integration

【讨论】:

以上是关于在 Grails 中映射遗留数据库表时避免表更改?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 Grails 中配置对数据库的两个不同模式的访问?

使用遗留数据库的原则,从多个表中获取字段

在 Oracle SQL Developer 连接窗口中选择表时如何避免默认获取表定义

为啥 MyEclipse 的 Hibernate 逆向工程在映射某些表时会创建多个类?

插入表时如何避免数据不一致

关于程序中数据库报错“父项未找到”