Grails里DOMAIN类的一对一,一对多,多对多关系总结及集成测试
终于干完这一章节,收获很多啊。
和DJANGO有类似,也有不同。
User.groovy:
package com.grailsinaction
class User {
String loginId
String password
Date dateCreated
static hasOne = [profile: Profile]
static hasMany = [posts: Post, tags: Tag, following: User]
static mapping = {posts sort: 'dateCreated'}
static constraints = {
loginId size: 3..20, unique: true, nullable: false
password size: 6..8, nullable:false, validator: { passwd, user -> passwd != user.loginId }
profile nullable: true
}
}
Profile.groovy:
package com.grailsinaction
class Profile {
User user
byte[] photo
String fullName
String bio
String homepage
String email
String timezone
String country
String jabberAddress
static constraints = {
fullName blank: false
bio nullable: true, maxSize: 1000
homepage url:true, nullable: true
email email: true, blank: false
photo nullable:true, maxSize: 2 * 1024 * 1024
country nullable: true
timezone nullable: true
jabberAddress email: true, nullable: true
}
}
Post.groovy:
package com.grailsinaction
class Post {
String content
Date dateCreated
static constraints = {
content blank: false
}
static belongsTo = [user: User]
static hasMany = [tags: Tag]
static mapping = { sort dateCreated: "desc"}
}
Tag.groovy:
package com.grailsinaction
class Tag {
String name
User user
static constraints = {
name blank: false
}
static hasMany = [posts: Post]
static belongsTo = [User, Post]
}
UserIntegrationSpec.groovy:
package com.grailsinaction
import grails.test.mixin.integration.Integration
import grails.transaction.*
import spock.lang.*
@Integration
@Rollback
class UserIntegrationSpec extends Specification {
def setup() {
}
def cleanup() {
}
def "Saving our first user to the database"() {
given: "A brand new user"
def joe = new User(loginId: 'Joe', password: 'secret')
when: "the user is saved"
joe.save()
then: "it saved successfully and can be found in the database"
joe.errors.errorCount == 0
joe.id != null
User.get(joe.id).loginId == joe.loginId
}
def "Updating a saved user changes its properties"() {
given: "An existing user"
def existingUser = new User(loginId: 'Joe', password: 'secret')
existingUser.save(failOnError: true)
when: "A property is changed"
def foundUser = User.get(existingUser.id)
foundUser.password = 'sesame'
foundUser.save(failOnError: true)
then: "The change is reflected in the database"
User.get(existingUser.id).password == 'sesame'
}
def "Deleting an existing user removes it from the database"() {
given: "An existing user"
def user = new User(loginId: 'Joe', password: 'secret')
user.save(failOnError: true)
when: "The user is deleted"
def foundUser = User.get(user.id)
foundUser.delete(flush: true)
then: "The user is removed from the database"
!User.exists(foundUser.id)
}
def "Saving a user with invalid properties causes an error"() {
given: "A user which fails several field validations"
def user = new User(loginId: 'Joe', password: 'tiny')
when: "The user is validated"
user.validate()
then:
user.hasErrors()
"size.toosmall" == user.errors.getFieldError("password").code
"tiny" == user.errors.getFieldError("password").rejectedValue
!user.errors.getFieldError("loginId")
}
def "Recovering from a failed save by fixing invalid properties"() {
given: "A user that has invalid properties"
def chuck = new User(loginId: 'chuck', password: 'tiny')
assert chuck.save() == null
assert chuck.hasErrors()
when: "We fix the invalid properties"
chuck.password = "fistfist"
chuck.validate()
then: "The user saves and validates fine"
!chuck.hasErrors()
chuck.save()
}
def "Ensure a user can follow other users"() {
given: "A set of baseline users"
def joe = new User(loginId: 'joe', password: 'password').save()
def jane = new User(loginId: 'jane', password: 'password').save()
def jill = new User(loginId: 'jill', password: 'password').save()
when: "Joe follows Jan & Jill, and Jill follows Jane"
joe.addToFollowing(jane)
joe.addToFollowing(jill)
jill.addToFollowing(jane)
then: "Follower counts should match follow people"
2 == joe.following.size()
1 == jill.following.size()
}
}
PostIntegrationSpec.groovy:
package com.grailsinaction
import grails.test.mixin.integration.Integration
import grails.transaction.*
import spock.lang.*
@Integration
@Rollback
class PostIntegrationSpec extends Specification {
def setup() {
}
def cleanup() {
}
def "Adding posts to user links post to user"() {
given: "A brand new user"
def user = new User(loginId: 'joe', password: 'secret')
user.save(failOnError: true)
when: "Several posts are added to the user"
user.addToPosts(new Post(content: "First post.....w002!"))
user.addToPosts(new Post(content: "Second post......"))
user.addToPosts(new Post(content: "Third post...."))
then: "The user has a list of posts attached"
3 == User.get(user.id).posts.size()
}
def "Ensure posts linked to a user can be retrieved"() {
given: "A user with several posts"
def user = new User(loginId: 'joe', password: 'secret')
user.addToPosts(new Post(content: "First"))
user.addToPosts(new Post(content: "Second"))
user.addToPosts(new Post(content: "Third"))
user.save(failOnError: true)
when: "The user is retrieved by their id"
def foundUser = User.get(user.id)
def sortedPostContent = foundUser.posts.collect {
it.content
}.sort()
then: "The posts appear on the retrieved user "
sortedPostContent == ['First', 'Second', 'Third']
}
def "Exercise tagging several post with various tags"() {
given: "A user with a set of tags"
def user = new User(loginId: 'joe', password: 'secret')
def tagGroovy = new Tag(name:"groovy")
def tagGrails = new Tag(name:"grails")
user.addToTags(tagGroovy)
user.addToTags(tagGrails)
user.save(failOnError: true)
when:"The user tags two fresh posts"
def groovyPost = new Post(content: "A groovy post")
user.addToPosts(groovyPost)
groovyPost.addToTags(tagGroovy)
def bothPost = new Post(content: "A groovy and grails post")
user.addToPosts(bothPost)
bothPost.addToTags(tagGroovy)
bothPost.addToTags(tagGrails)
then:
user.tags*.name.sort() == ['grails', 'groovy']
1 == groovyPost.tags.size()
2 == bothPost.tags.size()
}
}



Grails里DOMAIN类的一对一,一对多,多对多关系总结及集成测试的更多相关文章
- SQLAlchemy_定义(一对一/一对多/多对多)关系
目录 Basic Relationship Patterns One To Many One To One Many To Many Basic Relationship Patterns 基本关系模 ...
- JPA级联(一对一 一对多 多对多)注解【实际项目中摘取的】并非自己实际应用
下面把项目中的用户类中有个:一对一 一对多 多对多的注解对应关系列取出来用于学习 说明:项目运行正常 问题类:一对多.一对一.多对多 ============一对多 一方的设置 @One ...
- Python进阶----表与表之间的关系(一对一,一对多,多对多),增删改查操作
Python进阶----表与表之间的关系(一对一,一对多,多对多),增删改查操作,单表查询,多表查询 一丶表与表之间的关系 背景: 由于如果只使用一张表存储所有的数据,就会操作数 ...
- mybatis 一对一 一对多 多对多
一对一 一对多 多对多
- SSAS中事实表中的数据如果因为一对多或多对多关系复制了多份,在维度上聚合的时候还是只算一份
SSAS事实表中的数据,有时候会因为一对多或多对多关系发生复制变成多份,如下图所示: 图1 我们可以从上面图片中看到,在这个例子中,有三个事实表Fact_People_Money(此表用字段Money ...
- JPA实体关系映射:@ManyToMany多对多关系、@OneToMany@ManyToOne一对多多对一关系和@OneToOne的深度实例解析
JPA实体关系映射:@ManyToMany多对多关系.@OneToMany@ManyToOne一对多多对一关系和@OneToOne的深度实例解析 今天程序中遇到的错误一 org.hibernate.A ...
- day 69-70 一对一 一对多 多对一联表查询
day 69 orm操作之表关系,多对多,多对一 多对一/一对多, 多对多{类中的定义方法} day69 1. 昨日内容回顾 1. 单表增删改查 2. 单表查询API 返回QuerySet对象的: 1 ...
- 使用NHibernate(7)-- 一对一 && 一对多 && 多对多
1, 一对一. 对于数据量比较大的时候,考虑查询的性能,肯能会把一个对象的属性分到两个表中存放:比如用户和用户资料,经常使用的一般是Id和用户名,用户资料(学校,籍贯等)是不经常被查询的,所以就会分成 ...
- JPA 一对一 一对多 多对一 多对多配置
1 JPA概述 1.1 JPA是什么 JPA (Java Persistence API) Java持久化API.是一套Sun公司 Java官方制定的ORM 方案,是规范,是标准 ,sun公司自己并没 ...
随机推荐
- to_string作用
- 数据清洗——python定位csv中的特定字符位置
之前发过一篇关于定位csv中的特殊字符的,主要是用到了python的自带的函数,近期又遇到了一些新的问题,比如isdigit()的缺点在于不能判断浮点型,以及小数中有多个小数点的情况.发现还是正则表达 ...
- js基础---数据类型转换
js中数据类型: 简单数据类型: number:233,-34,0x23,023 string:"hello"或者'hello' boolean:true.false undefi ...
- Python3之切片的道理
list的切片有三个参数:起点,终点,步长 list[::-1] 相当于起点为最后的一个,终点为第一个,然后一次减少一个 更多的看下面的测试 >>> a = [0,1,2,3,4,5 ...
- ArcGIS Android工程迁移到其他电脑不能打开的问题
问题描述:当我把已经做好的ArcGIS Android工程想在其他电脑运行时,总是会提示报错.而报错的地方,正是出现在下面这条语句上. compile 'com.esri.arcgisruntime: ...
- JS——for
打印两行星星: <script> for (var i = 0; i < 2; i++) { for (var j = 0; j < 10; j++) { document.w ...
- C#——反射动态创建类的实例
“反射”其实就是利用程序集的元数据信息. 反射可以有很多方法,编写程序时请先导入 System.Reflection 命名空间. 若要反射当前项目中的类(即当前项目已经引用它了),可以使用下面的写法. ...
- SQl基本操作——视图
视图适合频繁查询的表:将一个查询结果作为虚拟表提供给开发人员.安全性高,视图只能查询不能修改,它是一张虚拟表.查询方便,逻辑清晰,但是性能低,一般情况下不如自己写sql语句. --创建视图 creat ...
- cookie和sessionStorage 、localStorage 对比
相同点:都存储在客户端 不同点:1.存储大小 cookie数据大小不能超过4k. sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或 ...
- Style在Android中的继承关系
Style在Android中的继承关系 Android的Styles(样式)和Themes(主题)非常类似Web开发里的CSS,方便开发者将页面内容和布局呈现分开.Style和Theme在Androi ...