我正在 Grails 中开发一个基于 Web 的应用程序。我遇到过一种情况,我想尝试禁止 GORM 在表中的字段上创建外键约束。
我有一个域类,它是类层次结构的一部分。域类本质上充当到目标域的链接。目标域可以是不同的类型,并且该链接域的每个子类都被设计为为每个特定类型的链接项提供链接。这些链接的项目具有某些共同的行为,即实现相同的接口,但在其他方面有所不同,因为它们存储在不同的表中。
在此链接域表中,有一列表示所链接到的项目的 ID。所有链接的项目都具有相同的基于整数的 id。问题是 GORM 尝试为同一表列创建多个外键约束,每个链接域子类都有一个外键约束,代表不同类型的链接项。我知道我可以为每次的 id 建立单独的列,其中其他 id 列将为空,但这看起来有点混乱。如果有一种方法可以告诉 GORM 我不希望它在该列上创建外键约束(因为不同的外键使用同一列),这将解决问题。
我知道问题在于引用完整性以及是否可以将链接键值放入外部表中不存在的列中,但应用程序应该防止这种情况发生。
如果失败的话,我将不得不手动加载链接的项目,而不是依赖 GORM 自动完成。
经过相对较短的谷歌搜索后,我找到了 Burt Beckwith 的博客文章:http://burtbeckwith.com/blog/?p=465这解释了 GORM 定制的基础知识。通过以下配置类,我设法阻止创建我不想创建的密钥。在 Burt 的示例中,需要一个 RootClass,但这不符合我的需要,因此省略了检查。
package com.myapp;
import com.myapp.objects.SomeClass;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration;
import org.hibernate.MappingException;
import org.hibernate.mapping.ForeignKey;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass;
import java.util.Collection;
import java.util.Iterator;
public class DomainConfiguration extends GrailsAnnotationConfiguration {
private static final long serialVersionUID = 1;
private boolean _alreadyProcessed;
@SuppressWarnings({"unchecked", "rawtypes"})
@Override
protected void secondPassCompile() throws MappingException {
super.secondPassCompile();
if(_alreadyProcessed) {
return;
}
Log log = LogFactory.getLog(DomainConfiguration.class.getName());
for(PersistentClass pc : (Collection<PersistentClass>) classes.values()) {
boolean preventFkCreation = false;
String fkReferencedEntityNameToPrevent = null;
if("com.myapp.objects.SomeClassWithUnwantedFkThatHasSomeClassAsAMember".equals(pc.getClassName())) {
preventFkCreation = true;
fkReferencedEntityNameToPrevent = SomeClass.class.getName();
}
if(preventFkCreation) {
for(Iterator iter = pc.getTable().getForeignKeyIterator(); iter.hasNext(); ) {
ForeignKey fk = (ForeignKey) iter.next();
if(fk.getReferencedEntityName().equals(fkReferencedEntityNameToPrevent)) {
iter.remove();
log.info("Prevented creation of foreign key referencing " + fkReferencedEntityNameToPrevent + " in " + pc.getClassName() + ".");
}
}
}
}
_alreadyProcessed = true;
}
}
通过将配置类放入 datasource.groovy 来将其引入 Grails:
dataSource {
...
...
configClass = 'com.myapp.DomainConfiguration
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)