我的Grails应用程序的域模型具有以下要求:
我将公共组织字段放入一个抽象的Organisation
类中,Charity
和Company
都扩展。我无法将此层次结构存储在单个表中,因为存在特定于每种组织类型的非可空字段。域模型的相关部分如下所示:
class User {
String name
static belongsTo = [organization: Organization]
static constraints = {
organization nullable: true
}
}
abstract class Organization {
String name
static hasMany = [users: User]
static mapping = {
tablePerHierarchy false
}
}
class Charity extends Organization {
// charity-specific fields go here
}
class Company extends Organization {
// company-specific fields go here
}
当我查看从该模型生成的MySQL模式时,组织公司和组织慈善机构之间的继承关系似乎已被完全忽略。虽然有一个带有名称列的组织表,但它与公司或慈善机构没有主要 - 外键关系
答案 0 :(得分:2)
organization_id
表中的预期users
FK。tablePerHierarchy false
),您最终会在数据库中隐含一对一的关系。 Charity
和Company
的主键值与父Organization
的PK值相同。 GORM / Hibernate3生成的模式似乎没有使用参照完整性约束来强制执行此模式。它是纯粹的Hibernate魔法。更详细一点here 答案 1 :(得分:1)
ORM不是RDBS。
tablePerHierarchy false
所以你有三张桌子:组织,慈善,公司。用户仅属于组织(不是慈善机构或公司)。你如何获得特定领域的价值? 有USER。我们了解组织,但我们不了解慈善机构或公司。我想你了......
我可以向您推荐三种解决方案:
1。 tablePerHierarchy为true(但您需要拥有可以为空的慈善机构\公司特定字段)
<强> 2 强>
class User {
static belongsTo = [charity: Charity, company: Company]
}
class Charity {
String name
static hasMany = [users: User]
// charity-specific fields go here
}
class Company {
String name
static hasMany = [users: User]
// company-specific fields go here
}
第3 强>
class User {
static belongsTo = [organization: Organization]
}
class Organization {
String name
Charity charity //nullable
Company company //nullable
static hasMany = [users: User]
}
class Charity {
static belongsTo = [organization: Organization]
// charity-specific fields go here
}
class Company {
static belongsTo = [organization: Organization]
// company-specific fields go here
}
答案 2 :(得分:1)
将下面的类添加到src/java
(此类不能用Groovy编写)
package org.example;
import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsAnnotationConfiguration;
import org.hibernate.MappingException;
import org.hibernate.mapping.JoinedSubclass;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.mapping.RootClass;
import java.util.Iterator;
public class TablePerSubclassConfiguration extends GrailsAnnotationConfiguration {
private static final long serialVersionUID = 1;
private boolean alreadyProcessed = false;
@Override
protected void secondPassCompile() throws MappingException {
super.secondPassCompile();
if (alreadyProcessed) {
return;
}
for (PersistentClass persistentClass : classes.values()) {
if (persistentClass instanceof RootClass) {
RootClass rootClass = (RootClass) persistentClass;
if (rootClass.hasSubclasses()) {
Iterator subclasses = rootClass.getSubclassIterator();
while (subclasses.hasNext()) {
Object subclass = subclasses.next();
// This test ensures that foreign keys will only be created for subclasses that are
// mapped using "table per subclass"
if (subclass instanceof JoinedSubclass) {
JoinedSubclass joinedSubclass = (JoinedSubclass) subclass;
joinedSubclass.createForeignKey();
}
}
}
}
}
alreadyProcessed = true;
}
}
然后在DataSource.groovy
中将其设置为配置类
dataSource {
configClass = 'org.example.TablePerSubclassConfiguration'
pooled = true
driverClassName = "org.h2.Driver"
username = "sa"
password = ""
dbCreate = "update"
url = "jdbc:h2:mem:testDb;MVCC=TRUE;LOCK_TIMEOUT=10000"
}
我已经向Grails提交了pull request来解决此问题。该修复程序包含在Grails 2.3.9中。