GORM域映射问题

时间:2015-08-19 16:25:36

标签: sql grails model mapping gorm

我有一个复杂的域模型,我试图实施,但我遇到了一些麻烦。 (最重要的是,我对这一切都很陌生!)

我有一个具有多个角色和多个测试的用户域。角色域工作得很好。 Test域有点复杂,因为它需要两个外键而不是像Role域中那样只有一个。第一个外键是user_id,第二个是uni_id(大学ID)。

用户域模型包含以下内容

class User {

    static hasMany = [roles:Role, tests:Test]

    Integer userId
    ...

    static mapping = {
        table 'user_data'
        id generator: 'assigned', name: 'userId', type: 'long'
        userId column: 'user_id'
        version false

        roles joinTable:[name:'user_role', key:'user_id']

        tests joinTable:[name:'user_test', key:'user_id'] // Here is where I run into trouble
    }

    static constraints = {
    }
}

测试域包含

class Test {

    static belongsTo = User
    static hasMany = [users:User]
    static hasOne = [uni:Uni]

    Integer testId // primary key
    String testType 

    static mapping = {
        table 'test'
        id generator: 'assigned', name: 'testId', type: 'long'
        testId column: 'test_id'
        users joinTable:[name:'user_test', key:'test_id']
        uni joinTable:[name:'user_test', key:'test_id'] // If I leave this out, everything is groovy
        version false
    }

    static constraints = {
    }
}

和Uni域包含

class Uni {

    static belongsTo = Test
    static hasMany = [tests:Test]

    Integer uniId // primary key
    String shortName 
    String fullName 

    static mapping = {
        table 'uni'
        id generator: 'assigned', name: 'uniId', type: 'long'
        uniId column: 'uni_id'
        version false

        tests joinTable:[name:'user_test', key:'uni_id']
    }

    static constraints = {
    }
}

如果不清楚,我尝试做的是将大学ID,测试ID和用户ID拉入表user_test,以根据用户ID找到他们已经进行的测试。有一个简单的方法吗?

我遇到的各种错误让我相信,由于某种原因,它会尝试在test而不是user_test上执行所有操作。例如,

Unsuccessful: alter table test add uni_id int not null

我希望能够通过user.tests.testTypeuser.tests.uni.fullName访问与特定用户相关的测试和大学信息。我究竟做错了什么?更重要的是,有更好的方法吗?!提前谢谢!

编辑1:我刚才想到的一些有趣的事情......用户可以进行多次测试,但反之则不然。特定测试永远不会在多个人之间共享。所以我认为这会改变一些事情......如果我想出任何新的东西,我会做一些阅读和发布。

编辑2:这是角色域

class Role {

  static belongsTo = User
  static hasMany = [users:User]

  Integer roleId
  String shortName
  String roleName
  Integer roleLevel

  static mapping = {
    table 'role'
    id generator: 'assigned', name: 'roleId', type: 'long'
    roleId column: 'role_id'
    users joinTable:[name:'user_role', column:'user_id', key:'role_id']
    version false
  }

    static constraints = {
    }
}

编辑3:我现在正在尝试将所有测试信息存储在Test域模型中,只需选择Uni名称作为Test中的字段存储,但在尝试此操作时会出现奇怪的错误。我的新文件看起来像这样

class User {

    static hasMany = [roles:Role, tests:Test]

    Integer userId

    static mapping = {
        table 'user_data'
        id generator: 'assigned', name: 'userId', type: 'long'
        userId column: 'user_id'
        version false

        roles joinTable:[name:'user_role', key:'user_id']
    }

    static constraints = {
    }
}

class Test {

    static belongsTo = User

    Integer testId // primary key
    Integer testTypeId
    String testTypeName
    String testUni
    Date testDate

    static mapping = {
        table 'test'
        id generator: 'assigned', name: 'testId', type: 'long'
        testId column: 'test_id'
        version false
    }

    static constraints = {
    }
}

但是现在我尝试运行它时出现以下错误Caused by: org.hibernate.MappingException: Missing type or column for column[tests_test] on domain[User] referencing[Test]

知道那是什么意思吗?

2 个答案:

答案 0 :(得分:1)

好的,您遇到的一个问题是您尝试与Test-to-Unit关联共享User-to-Test关联连接表。那不行。

让我们用数据库术语来看待它。我不是ASCII艺术专家,所以我希望这个图表不会让你的眼睛流血。

user_data (userId) |---|< (user_id) user_test (test_id) >|---| (testId) test

上图显示了User和Test域类之间多对多关联的数据库实现。您可以看到 user_data.userId 指向 user_test.user_id user_test.test_id 的链接指向 test.testId

现在,它开始变得奇怪了。 Test和Uni之间有两种不同的关联:双向一对一和一对多。我只是不明白。但我想说明你的连接表的一个重要问题,所以在这里。

test (testId) |---|< (test_id) user_test (uni_id) >|---| (uniId) uni

因为你为两个不同的关联使用了相同的连接表(user_test),所以你要求GORM创建一个这样的表:

USER_TEST
- USER_ID
- TEST_ID
- UNIT_ID

GORM不会这样做,因为连接表应该只有两个字段。不仅如此,而且您还在数据库术语中定义了多对多,而在GORM术语中则是双向一对一和一对多。哎哟!

TODO

我建议的第一个更改是为Test-Uni关联使用不同的连接表。

答案 1 :(得分:0)

最后让一切正常(在对域模型进行了一些修改之后)

class User {

    static hasMany = [roles:Role, tests:Test]

    Integer userId

    static mapping = {
        table 'user_data'
        id generator: 'assigned', name: 'userId', type: 'long'
        userId column: 'user_id'
        version false

        roles joinTable:[name:'user_role', column:'role_id', key:'user_id']
    }

    static constraints = {
    }
}

class Test {

    User user
    Integer testId // primary key
    String testType
    String testUni
    Date testDate

    static mapping = {
        table 'test'
        id generator: 'assigned', name: 'testId', type: 'long'
        testId column: 'test_id'
        version false
    }

    static constraints = {
    }
}

class Uni {

    Integer uniId // primary key
    String shortName 
    String fullName 

    static mapping = {
        table 'uni'
        id generator: 'assigned', name: 'uniId', type: 'long'
        uniId column: 'uni_id'
        version false
    }

    static constraints = {
    }
}

所以现在我正在做的是从我的GSP的下拉选项卡中选择大学,并将其作为字符串testUni保存在Test中。然后,最大的变化是删除三者之间的所有joinTables并将User user添加到Test。我仍然有点模糊为什么我之前做的事情没有工作,但我不会抱怨工作的应用程序!