`

Grails GORM中的映射(一对一 一对多 多对多)

 
阅读更多

本文来自:fair-jm.iteye.com 转截请注明出处

 

来自:

http://grails.org/doc/latest/guide/single.html#GORM

配合手册里的例子 做了些小试验 

这篇博文是里面6.1~6.2的内容 官方的指南写得很详细很好啊...

 

Grails的ORM的底层实现还是用的hibernate(在现在最新的2.3.3中是hibernate3)

 

快速开始:

grails create-domain-class helloworld.Person

增加属性:

class Person {
    String name
    Integer age
    Date lastVisit
} //id是自动生成的 所以不用自己创建(当然自己设定个 Integer id 是完全没问题的)

 

 

基本的CRUD操作:

创建(c):

def p = new Person(name: "Fred", age: 40, lastVisit: new Date())
p.save()

 

 

读取(R):

def p=Person.get(1) //1是id
assert 1==p.id

 

用只读方式读取

def p=Person.read(1)

 

用代理(proxy)方式读取(这和hibernate中的load是一样的):

def p = Person.load(1)

 

 

更新(U):

U的操作就是先读再存:

def p = Person.get(1)
p.name = "Bob"
p.save()

 

 

删除(D):

def p = Person.get(1)
p.delete()

 

 

 

 

 

6.2中是关于一对一 一对多 多对多的内容:

多对一和一对一关系:

//Face类
class Face {
    Nose nose
}

//nose类
class Nose {
    static belongsTo = [face:Face]
}

这样在数据库中建立的表是:

 


 可见外键是由face维护的
 

保存的话通过:

new Face(nose:new Nose()).save()

因为belongsTo是将控制权给对方 所以

new Nose(face:new Face()).save() // will cause an error 

是错误的 face还是瞬时态的 不能被保存

 

删除Face的话对应的Nose也会被删除

def f = Face.get(1)
f.delete() // both Face and Nose deleted

 

但如果让一个Nose被多于一个的Face关联

那么删除任意一个Face会抛出异常的(那个Nose还被其他的Face关联)

所以这样的做法不是真正的一对一 而是nose对face的一个一对多关系 为了保险 限制一下nose的唯一

static constraints={
 nose(unique:true)
}

Face对Nose是级联的保存 更新和删除

 

 

 

真正的一对一:

class Face {
    static hasOne = [nose:Nose]
}

class Nose {
    Face face
}

这样的话 外键字段是在nose中的face_id中

 

在Nose中是不能级联保存Face的

有了hasOne就不能单独保存任何一方了

在试验中 不设置Face的Nose属性 不设置Nose的Face属性都不能被正常的save

 

删除face nose也会被级联删除

不过单独删除Nose是没问题的

Nose.withTransaction{
 Nose.get(2).delete() //删除一个Nose
}

是可行的 从face中查询也只是得到null而已

 

自引用的例子:

如果有多个相同类型的属性在里面 并且这些属性都是自引用的(引用自身表)

那么grails的映射关系就需要人为指定一下:

class Person {
    String name
    Person parent
    static belongsTo = [ supervisor: Person ]
    static constraints = { supervisor nullable: true }
}

他会把parent和supervisor当作是同一个联系的两个不同的方向

如果你在A1上设置了parent A2 那么会在A2上设置supervisor为A1

我把这个问题详细说一下 按以上代码输入后:

表结构:



 

执行下列代码:

import orm_test.*

Person.withTransaction{
 new Person(name:"cc",parent:new Person(name:"fairjm")).save()
}

   

  同一个关系的不同方向 就如上图所示

 
 

用mappedBy可以解决:

class Person {
    String name
    Person parent
    static belongsTo = [ supervisor: Person ]
    static mappedBy = [ supervisor: "none", parent: "none" ]
    static constraints = { supervisor nullable: true }
}

mappedBy是指导如何映射的 这样的"none"是表示不映射对方类(也就是Person啦)的任意一个属性

(最开始 grails会将Parent映射到对方的supervisor的

也就是类似:

static mappedBy = [ supervisor: "parent", parent: "supervisor" ]

)

关于一个类中有多个相同类型的属性的映射问题都要通过mappedBy来手工指定映射关系解决掉

 

 

 

 

一对多:

class Author {
    static hasMany = [books: Book]
    String name
}
class Book {
    String title
}

这是一个单向的一对多 grails默认用一张中间表的形式:



 

def a = Author.get(1)
for (book in a.books) {
    println book.title
}

 

默认是懒加载的形式

 

这样做的默认会级联更新和保存 但不会级联删除

import orm_test.*

Author.withTransaction{
/* def au=new Author(name:"cc")
 au.books=[new Book(title:"book1"),new Book(title:"book2")]
 au.save()*/
 Author.get(1).delete() //不会导致book被删除
}

 

 

实现级联删除要用belongsTo 原先的单向关系也会变成一个双向的一对多关系:

class Author {
    static hasMany = [books: Book]
    String name
}
class Book {
    static belongsTo = [author: Author]
    String title
}

 以上设置的话 表的结构会发生变化 不会有中间表了 外键字段被加在了多的一端:

  
  

import orm_test.*

Author.withTransaction{
/*
 def au=new Author(name:"cc")
 au.books=[new Book(title:"book1",author:au),new Book(title:"book2",author:au)]  //这边必须显示指定au了 book那多了一个属性不是~~ 不过没有addToBooks方法 但多对多的时候就会有..
 au.save()
 */
 Author.get(7).delete() //会导致book被删除
}

 

 

用mappedBy解决一个类下多个同类型属性的问题:

class Airport {
    static hasMany = [outboundFlights: Flight, inboundFlights: Flight]
    static mappedBy = [outboundFlights: "departureAirport",
                       inboundFlights: "destinationAirport"]
}
class Flight {
    Airport departureAirport
    Airport destinationAirport
}

 

 

 

 

 

 

 

 

 

多对多:

class Book {
    static belongsTo = Author
    static hasMany = [authors:Author]
    String title
}


class Author {
    static hasMany = [books:Book]
    String name
}

 多对多生产的中间表:


Author负责关系的维护 

(Book是不能向author表插入新Author的 也就是Book不能在addToAuthors的时候用一个瞬时态的对象)

new Author(name:"Stephen King")
        .addToBooks(new Book(title:"The Stand"))
        .addToBooks(new Book(title:"The Shining"))
        .save()

 这样是可以的

book不会被级联删除..

实验了下

 

实验一:

Author.withTransaction{
def p=new Author(name:"cc")
p.addToBooks(new Book(title:"book1")).addToBooks(new Book(title:"book2")).save() //可以级联保存book
}
Book.list()
Author.withTransaction{ //用户删除的话 中间表的条目会被删除 但是book不会被删除
for( def a:Author.list())
{
 a.delete(); //删除所有用户
}
}
Book.list() //还存在

 

实验二:

import orm_test.*
Author.withTransaction{
 def p=new Author(name:"cc")
 p.addToBooks(new Book(title:"book1")).addToBooks(new Book(title:"book2")).save()
}
Author.withTransaction{
 def p=new Author(name:"cc2") //新增一个用户cc2
 p.save()
}
Book.withTransaction{
Book.findByTitle("book1").addToAuthors(Author.findByName("cc2")).save() //中间表更新了状态
}

查询也是没有问题的:

import orm_test.*
Book.withTransaction{
def b=Book.findByTitle("book1")
b.authors?.toString()
}

 文档里还说 多对多关系现在的脚手架还不支持

 

  

以后的内容有空再更新了~~

  • 大小: 2.1 KB
  • 大小: 2.5 KB
  • 大小: 3.5 KB
  • 大小: 3.3 KB
  • 大小: 2.9 KB
  • 大小: 5.8 KB
  • 大小: 5.8 KB
0
0
分享到:
评论

相关推荐

    使用GORM构建Spring Boot应用程序 Grails指南_ Grails框架.pdf

    在本教程中,我们将探讨如何使用GORM(Grails Object-Relational Mapping)构建Spring Boot应用程序。GORM是Grails框架的核心部分,它为开发者提供了简单、强大的数据持久化功能,支持Hibernate和MongoDB等数据库。...

    Grails Persistence with GORM and GSQL

    - **定义类之间的关系**:讲解了如何在GORM中定义一对多、多对多等关系类型,并探讨了如何处理这些关系的查询和更新。 - **定义树形关系**:介绍了一种特殊的关系类型——树形结构,以及如何在GORM中表示这种结构...

    grails中文入门简介

    GORM支持基本的CRUD操作,并且在领域建模方面提供了强大的支持,包括一对一、一对多和多对多的关联。GORM支持继承,可以方便地实现模型的层次结构。GORM中的高级特性包括自定义映射选项、事务编程以及乐观锁和悲观锁...

    精通 Grails 使用 Ajax 实现多对多关系

    在多对多关系中,两个实体类之间存在一对多的双向关联,即每个实例可以与多个实例相关联,反之亦然。以书(Book)和作者(Author)为例,一本书可以有多个作者,一个作者也可能参与多本书的创作。在数据库层面,这...

    grails使用freemarker.rar

    压缩包内的“one2many”可能是一个示例或教程,涉及到一对一(one-to-one)、一对多(one-to-many)或多对一(many-to-one)的关系映射。在数据库设计中,这些关系是常见的实体间关联。在Grails与GORM中,处理这种...

    Grails1.1中文文档.rar

    Grails 是一个基于 Groovy 语言的开源Web应用程序框架,旨在简化Web应用开发过程,提高开发效率。它借鉴了Ruby on Rails的许多设计原则,但选择了Java平台作为基础,因此可以充分利用Java生态系统中的丰富资源。...

    grails 中文手册

    - GORM 是 Grails 提供的持久化框架,它提供了对数据库操作的简便接口,包括CRUD(创建、读取、更新、删除)操作。 - GORM 支持领域驱动设计(Domain-Driven Design),领域模型可以直接映射到数据库表,通过注解...

    grails-用户手册

    Grails的URL映射非常灵活,可以在`UrlMappings.groovy` 文件中定义,使URL更加语义化,便于SEO优化。 八、构建与部署 Grails使用Gradle作为构建工具,提供了`grails war` 命令生成可部署的WAR文件,方便在各种Java...

    grails 中文第二版

    - 支持多种关联方式,如多对一、一对多等。 - 支持组合和继承,增加了模型的灵活性。 - 支持集合、列表和映射等数据结构。 **持久化基础** - 支持对象的保存和更新操作。 - 支持对象的删除操作。 - 支持级联更新和...

    grails1.1中文文档

    无论是对Groovy语言的学习,还是对MVC架构的理解,或是如何利用GORM操作数据库,这份文档都将提供详尽的解释和示例,是Grails入门者的宝贵参考资料。通过学习,开发者可以迅速掌握Grails 1.1,从而高效地构建现代Web...

    the definitive guide to grails 2

    在Grails框架中,域模型(Domain Classes)是用于表示业务实体的对象,它们通常映射到数据库中的表。通过GORM(Grails Object Relational Mapping),Grails提供了自动的ORM支持,使得开发者无需编写复杂的SQL语句...

    Grails 中文参考手册

    - **领域建模**:GORM提供了强大的领域模型支持,包括不同类型的关联(一对一、一对多、多对多)和组合、继承等概念。 - **持久化操作**:包括对象的保存、更新、删除,以及级联操作和加载策略。 - **查询**:...

    grails框架数据查询

    在Grails中,我们可以轻松处理对象间的关联,如一对一、一对多、多对一、多对多关系。例如,一个User可以有多个Role,可以这样查询: ```groovy def user = User.get(1) def roles = user.roles ``` ### 4. 分页和...

    grails项目配置

    在Grails中,一对多关系是通过在模型类中定义`hasMany`属性来实现的。例如,如果有一个`User`类和一个`Post`类,用户可以有多个帖子,那么在`User`类中会有一行代码: ```groovy static hasMany = [posts: Post] ...

    Grails权威指南.pdf

    - **Relationships**:支持一对一、一对多、多对多等关系映射,例如belongsTo、hasMany、hasOne等。 - **Criteria API**:用于构建灵活的数据库查询,避免硬编码SQL。 5. **Ajax集成**: - **AJAX in Grails**:...

    grails-core源码

    3. **Domain Classes**:Grails的领域模型类,基于Groovy,具有自动持久化的能力,通过`GORM(Grails Object Relational Mapping)`与数据库交互。 4. **Controllers**:控制层负责处理HTTP请求,调用业务逻辑,并...

    一步一步学grails(4)

    在本教程中,我们将深入探讨如何使用GORM处理1:M(一对一到多)关系。教程中提到的项目涉及到五个核心领域类,它们之间的关系构建了一个完整的生产计划系统。 首先,我们来看`Planning`领域类,它是生产计划的核心...

Global site tag (gtag.js) - Google Analytics