11package grails.gorm.tests
22
3- import grails.persistence .Entity
4- import org.grails.datastore.mapping.proxy.EntityProxy
3+ import grails.gorm.annotation .Entity
4+ import org.grails.datastore.mapping.proxy.ProxyHandler
55
66class BuiltinUniqueConstraintWorksWithTargetProxiesConstraintsSpec extends GormDatastoreSpec {
77
8- void " modified domains object works as expected" () {
9- given : " I have a Domain OBJECT"
10- final Referenced object = new Referenced (name : " object" ). save(failOnError : true )
11- assert ! (object instanceof EntityProxy )
12-
13- and : " I have another Domain OBJECT with the same name"
14- final Referenced another = new Referenced (name : " object" )
15- assert ! (object instanceof EntityProxy )
8+ void " test unique constraint on root instance" () {
9+
10+ given :
11+ ContactDetails contactDetails1 = new ContactDetails (phoneNumber : " +1-202-555-0105" ). save(failOnError : true )
12+ ContactDetails contactDetails2 = new ContactDetails (phoneNumber : " +1-202-555-0105" )
13+ session. flush()
14+ session. clear()
1615
1716 when : " I try to validate the another object"
18- another . validate()
17+ contactDetails2 . validate()
1918
2019 then : " another should have an error on name because it is duplicated"
21- another . hasErrors()
22- another . errors. hasFieldErrors(" name " )
23- another . errors. getFieldError(" name " ). codes. contains(" unique.name " )
20+ contactDetails2 . hasErrors()
21+ contactDetails2 . errors. hasFieldErrors(" phoneNumber " )
22+ contactDetails2 . errors. getFieldError(" phoneNumber " ). codes. contains(" unique.phoneNumber " )
2423
2524 cleanup :
26- object ?. delete( flush : true )
25+ ContactDetails . deleteAll(contactDetails1 )
2726 }
2827
29- void " modified Referenced domains object works as expected" () {
30- given : " I have a Domain OBJECT"
31- final Referenced object = new Referenced (name : " object" ). save(failOnError : true )
32- assert ! (object instanceof EntityProxy )
33- and : " a root referencing it"
34- final Root parent = new Root (ref : object). save(failOnError : true )
35- assert ! (parent instanceof EntityProxy )
28+ void " test unique constraint for the associated child object" () {
3629
37- and : " I have another Domain OBJECT with the same name "
38- final Referenced anotherReferenced = new Referenced ( name : " object " )
39- assert ! (object instanceof EntityProxy )
40- final Root anotherRoot = new Root ( ref : anotherReferenced )
41- assert ! (parent instanceof EntityProxy )
30+ given :
31+ ContactDetails contactDetails1 = new ContactDetails ( phoneNumber : " +1-202-555-0105 " ) . save( failOnError : true )
32+ Patient patient1 = new Patient ( contactDetails : contactDetails1) . save( failOnError : true )
33+ session . flush( )
34+ session . clear( )
4235
43- when : " I try to validate the another object"
44- anotherRoot. validate()
36+ when :
37+ Patient patient2 = new Patient (contactDetails : new ContactDetails (phoneNumber : " +1-202-555-0105" ))
38+ patient2. validate()
4539
46- then : " another should have an error on name because it is duplicated "
47- anotherRoot . hasErrors()
48- anotherRoot . errors. hasFieldErrors(" Referenced.name " )
49- anotherRoot . errors. getFieldError(" Referenced.name " ). codes. contains(" unique.name " )
40+ then :
41+ patient2 . hasErrors()
42+ patient2 . errors. hasFieldErrors(" contactDetails.phoneNumber " )
43+ patient2 . errors. getFieldError(" contactDetails.phoneNumber " ). codes. contains(" unique.phoneNumber " )
5044
5145 cleanup :
52- object ?. delete( flush : true )
53- parent ?. delete( flush : true )
46+ Patient . deleteAll(patient1 )
47+ ContactDetails . deleteAll(contactDetails1 )
5448 }
5549
56- void " unmodified Referenced proxies object doesnt fail unique constraint checking" () {
57- given : " I have a Domain OBJECT"
58- Long ReferencedId , parentId
59- Root . withNewSession {
60- Root . withNewTransaction {
61- final Referenced object = new Referenced (name : " object" ). save(failOnError : true )
62- final Root parent = new Root (ref : object). save(failOnError : true )
63-
64- ReferencedId = object. id
65- parentId = parent. id
66- }
67- }
68- and :
69- int tries = 20
70- while (! Root . exists(parentId) && ! Referenced . exists(ReferencedId ) && tries-- > 0 ) {
71- sleep(50 )
72- }
73-
74- and : " I access the parent, forcing the Referenced to be initialized"
75-
76- def parent = Root . findAll()[0 ]
77- assert parent. ref instanceof EntityProxy
78- parent. ref. name == " object"
79-
80- when : " I try to validate the the parent (which then tries to validate the Referenced)"
81- parent. validate()
82-
83- then : " parent.Referenced should not have any errors!"
84- ! parent. hasErrors()
85- ! parent. errors. hasFieldErrors(" Referenced.name" )
86- ! parent. errors. getFieldError(" Referenced.name" ). codes. contains(" unique.name" )
50+ void " test unique constraint on the unmodified association loaded as initialized proxy" () {
8751
88- cleanup :
52+ given :
53+ final ProxyHandler proxyHandler = session. mappingContext. getProxyHandler()
54+ ContactDetails contactDetails = new ContactDetails (phoneNumber : " +1-202-555-0105" ). save(failOnError : true )
55+ Patient patient = new Patient (contactDetails : contactDetails). save(failOnError : true )
56+ Long patientId = patient. id
57+ session. flush()
58+ session. clear()
59+
60+ when :
61+ patient = Patient . get(patientId)
62+ patient. contactDetails. phoneNumber = " +1-202-555-0105"
8963
90- Root . withNewSession {
91- Root . withNewTransaction {
92- Referenced . get(ReferencedId )?. delete(flush : true )
93- Root . get(parentId)?. delete(flush : true )
94- }
95- }
96- tries = 20
97- while (Root . exists(parentId) && Referenced . exists(ReferencedId ) && tries-- > 0 ) {
98- sleep(50 )
99- }
64+ then :
65+ proxyHandler. isProxy(patient. contactDetails)
66+
67+ expect :
68+ patient. validate()
69+
70+ cleanup :
71+ Patient . deleteAll(patient)
72+ ContactDetails . deleteAll(patient. contactDetails)
10073 }
10174
10275 @Override
10376 List getDomainClasses () {
104- [Referenced , Root ]
77+ [ContactDetails , Patient ]
10578 }
10679}
10780
10881@Entity
109- class Referenced {
82+ class ContactDetails implements Serializable {
11083
111- String name
84+ String phoneNumber
11285
11386 static constraints = {
114- name nullable : false , unique : true
87+ phoneNumber nullable : false , unique : true
11588 }
11689}
11790
11891@Entity
119- class Root {
92+ class Patient implements Serializable {
12093
121- Referenced ref
94+ ContactDetails contactDetails
12295
12396 static constraints = {
124- ref nullable : false
97+ contactDetails nullable : false
12598 }
12699
127100 static mapping = {
128- ref lazy : false
129- id generator : ' snowflake'
101+ contactDetails lazy : true
130102 }
131- }
103+ }
0 commit comments