2010-02-05 5 views
2

I ont les classes suivantes:Renommage clés étrangères composites GORM


class Catalog { 
    static mapping = { 
    id composite:['name', 'manufacturer'] 
    columns { 
     name column:'cat_name' 
     manufacturer column:'manuf_id' 
    } 
    } 
    String name 
    Manufacturer manufacturer 
} 

class Order { 
    static mapping = { 
    columns { 
     // How to rename foreign keys as cat_name, manuf_id? 
    } 
    } 
    Catalog catalog // creates catalog_name, catalog_manufacturer_name 
} 

Actuellement, une table de commande est générée avec les attributs CATALOG_NAME et catalog_manufacturer_name (qui référence les clés primaires composites de la table de catalogue).

Je dois renommer ces colonnes générées en cat_name et manuf_id dans la table Order pour travailler avec une base de données existante. Est-ce possible, et si oui comment?

Répondre

2

Il est impossible en utilisant la configuration de Gorm, mais vous pouvez le faire avec une classe de configuration personnalisée:

package com.foo.bar; 

import java.util.Collection; 
import java.util.Iterator; 

import org.codehaus.groovy.grails.orm.hibernate.cfg.DefaultGrailsDomainConfiguration; 
import org.hibernate.MappingException; 
import org.hibernate.mapping.Column; 
import org.hibernate.mapping.PersistentClass; 
import org.hibernate.mapping.RootClass; 

public class CompositeAwareHibernateConfiguration extends DefaultGrailsDomainConfiguration { 

    private static final long serialVersionUID = 1; 

    private boolean _alreadyProcessed; 

    @SuppressWarnings("unchecked") 
    @Override 
    protected void secondPassCompile() throws MappingException { 
     super.secondPassCompile(); 

     if (_alreadyProcessed) { 
     return; 
     } 

     for (PersistentClass pc : (Collection<PersistentClass>)classes.values()) { 
     if (pc instanceof RootClass) { 
      RootClass root = (RootClass)pc; 
      if ("com.foo.bar.Order".equals(root.getClassName())) { 
       for (Iterator iter = root.getTable().getColumnIterator(); iter.hasNext();) { 
        Column column = (Column)iter.next(); 
        if ("catalog_name".equals(column.getName())) { 
        column.setName("cat_name"); 
        } 
        else if ("catalog_manufacturer_id".equals(column.getName())) { 
        column.setName("manuf_id"); 
        } 
       } 
      } 
     } 
     } 

     _alreadyProcessed = true; 
    } 
} 

Mettez la classe dans src/java et l'enregistrer dans DataSource.groovy:

dataSource { 
    pooled = true 
    driverClassName = ... 
    username = ... 
    password = ... 
    configClass = com.foo.bar.CompositeAwareHibernateConfiguration 
} 
+0

Merci pour le code, mais il ne fonctionne pas pour moi. J'ai laissé tomber la table et l'a recréée avec les mêmes noms de table. – titaniumdecoy

+0

Dumb question, vous avez changé le nom du paquet de la classe de domaine de "com.foo.bar" droit? Ajoutez des instructions System.out.println() pour voir ce qui se passe. –

+0

Oui, j'ai changé le nom du paquet. S'il y a une erreur de syntaxe dans le code, il s'encrasse, mais les instructions println ne sont pas exécutées. J'ai même essayé d'écrire dans un fichier. Le code ne semble pas être exécuté pour une raison quelconque. – titaniumdecoy

2

J'ai écrit une solution pour n'importe quelle classe de domaine qui en a besoin et vous n'avez pas besoin de readapt à chaque fois.

class Catalog { 
    static mapping = { 
    id composite:['name', 'manufacturer'] 
    columns { 
     name column:'cat_name' 
     manufacturer column:'manuf_id' 
    } 
    } 
    String name 
    Manufacturer manufacturer 
} 

class Order { 
    Catalog catalog 
    static mapping = { 
    } 
    static foreigners = [ 
    catalog : [name : "catalog_name", 
       manufacturer: "catalog_manufacturer_name"] 
    ] 
} 

Ceci est la classe de configuration GORM que j'écris pour consommer les étrangers dans la classe de domaine.

package my.app.package 
import java.util.Collection; 
import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration; 
import org.hibernate.MappingException; 
import org.hibernate.mapping.Column; 
import org.hibernate.mapping.ForeignKey; 
import org.hibernate.mapping.PersistentClass; 
import org.hibernate.mapping.RootClass; 
class MyCustomGrailsAnotationConfiguration extends GrailsAnnotationConfiguration{ 
    private static final long serialVersionUID = 1; 
    private boolean _alreadyProcessed=false; 
    @SuppressWarnings("unchecked") 
    @Override 
    protected void secondPassCompile() throws MappingException { 
     super.secondPassCompile(); 
     if(_alreadyProcessed){ 
      return; 
     } 
     classes.values().each{rootClass -> 
      if(rootClass instanceof RootClass){ 
       def domainClass= null 
       Boolean hasForeigners=false 
       try{ 
        domainClass=Class.forName(rootClass.entityName,false,Thread.currentThread().getContextClassLoader()) 
        hasForeigners = domainClass.metaClass.hasProperty(domainClass, 'foreigners') 
       }catch(Exception e){} 
       if(domainClass && hasForeigners){ 
        rootClass?.table?.foreignKeyIterator?.each{fKey-> 
         fKey?.columnIterator?.each{column-> 
          domainClass.foreigners?.each{attrName,columns -> 
           columns.each{columnItmName,columnItmValue-> 
            def exp=attrName+"_" 
            columnItmName.split("").each{exp+=(it==~/[A-Z]/) ? "_"+it:it} 
            exp=exp.toLowerCase()+".(id)\$" 
            //println "Expression:"+exp 
            if(column.name.matches(exp)){ 
             //println "Match:"+column.name+" changing to "+columnItmValue 
             column.name=columnItmValue 
            } 
           } 
          } 
         } 
        } 
       } 
      } 
     } 
     _alreadyProcessed = true; 
    } 
} 

Mettez la classe my.app.package.MyCustomGrailsAnotationConfiguration.groovy dans src/Groovy/ma/app/paquet/MyCustomGrailsAnotationConfiguration.groovy et l'enregistrer dans DataSource.groovy:

dataSource { 
    pooled = true 
    driverClassName = ... 
    username = ... 
    password = ... 
    configClass = my.app.package.MyCustomGrailsAnotationConfiguration 
} 

J'espère Cela vous sera utile. Merci pour votre aide @carlosmain

+1

Merci, mais je ne travaille plus sur ce projet. Je suis sûr que quelqu'un d'autre le trouvera utile. – titaniumdecoy

4

Ce résolu mon problème (Grails 2.0.4):

http://jira.grails.org/browse/GRAILS-4504?focusedCommentId=64996&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-64996

Mon cas:

class GroupMessage implements Serializable { 

    Group group 
    Integer messageId 

    static mapping = { 
     datasources(['ds1']) 
     table 't_group_msg' 
     version false 
     id composite: ['group', 'messageId'], generator: 'assigned' 
     group column:'grpid' 
     messageId column:'msgid', type:int 
    } 
} 

class GroupMessageDetail implements Serializable { 

    GroupMessage groupMessage 
    Integer detailId 
    String message 
    String url 

    static mapping = { 
     datasources(['ds1']) 
     table 't_group_msg_det' 
     version false 
     id composite: ['groupMessage', 'detailId'], generator: 'assigned' 
     columns { 
      groupMessage { 
       column name: 'grpid' 
       column name: 'msgid' 
      } 
      detailId column:'id', type:int 
      message column:'sms' 
      url column:'url' 
     } 
} 
Questions connexes