无法级联保存或删除嵌入式类引用工作 [英] can't get cascade save nor delete on embedded class ref to work
问题描述
我已经创建了两个简单的grails V3域类,其中位置嵌入属性类型在父级Venue中,如下所示:
import java .time.LocalDate
$ b $ class class Venue {
字符串名称
LocalDate dateCreated
LocalDate lastVisited
LocalDate lastUpdated
GeoAddress位置
$ b $ static $ has $%$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $'$' true
location nullable:true
static mapping = {
位置级联:all-delete-orphan,lazy:false //渴望获取策略
$ b类地理地址{
字符串addressLine1
字符串addressLine2
字符串addressLine3
字符串城镇
字符串县
字符串国家=英国
字符串邮政编码
静态belongsTo =地点
静态约束= {
addressLine1可为空:true
addressLine2可空:true
addressLine3可空:true
可空:true
可空:true
国家可空:true
邮编可为空:true
}
}
然而,当我写一个集成测试 - 我发现级联创建的位置没有工作(我必须保存的位置不再是瞬间传递到场地之前。也当我运行与冲洗场地上的删除:真正启用,并查询地址我仍然得到返回的嵌入式地址 - 我认为与刷新:真正我会看到我的地理地址级联删除,但我的测试失败,因为我当我使用GeoAddress.get(loc.id)时,不会得到null
@Integration
@Rollback
class VenueIntegrationSpec扩展了规范{
void'使用地址的测试场地(){
当:使用嵌入式传递保存创建场地和地址
GeoAddress地址=新地理地址(addressLine1:myhouse,镇:Ipswich,县:萨福克,邮编:IP4 2TH)
address.save()//必须先保存 - 否则地点保存失败
Venue v =新Venue(名称:bistro,位置:地址)
def result = v.save()
然后:检索场地并检查其位置位置热切地加载
Venue lookupVenue = Venue.get( v.id)
GeoAddress loc = lookupVenue.location
loc.postcode ==IP4 2TH
loc.town ==Ipswich
when:我们删除了场地,它删除了嵌入的位置(地址)
v.delete(flush:true)
GeoAddress lookupLoc = GeoAddress.get(loc.id)
then :address should disppear
lookupLoc == null
}
我想过我已经正确设置了这一点,但显然我没有。可以说明为什么我的级联动作为Venue.save()和delete()不会级联到我的嵌入式位置(GeoAddress)条目。
谢谢前进
确定 - 我仔细阅读并寻找差异 - 并且在我传递给我之前保存嵌入式地理地址像这样的场地构造(修改后的简单测试)
当我在创建GeoAddress后添加额外的a.save()时,测试将失败。如果我评论保存并重新运行 - 它工作正常。不知道这是一个功能还是一个错误。由于GeoAddress有一个stati belongsTo = Venue声明,因此会进行传递保存。
//新测试 - 重用嵌入式实体 - 作品
voidGeoLocation测试(){
当:
GeoAddress a =新地理地址(城镇:ipswich)
a.save()
地点v =新地点(名称:小酒馆,位置:a)
assert v.save(flush:true)
Venue lookupVenue = Venue.get(v.id)
GeoAddress ta = lookupVenue.location
assert ta.town ==ipswich
//尝试删除
v.delete(flush:true)
then:retrieve temp
GeoAddress.findAll()。size()== 0
}
如果任何人都可以对我的bug和功能发表评论 - 那么如果有必要,我可以在grails项目上提出一个bug来修复它。否则我只需要仔细测试,并确保我在代码中做了正确的事情
i've created two simple grails V3 domain classes where location is embedded attribute type in parent Venue like this
import java.time.LocalDate
class Venue {
String name
LocalDate dateCreated
LocalDate lastVisited
LocalDate lastUpdated
GeoAddress location
static hasOne = [location:GeoAddress]
static embedded =['location']
static constraints = {
lastVisited nullable:true
location nullable:true
}
static mapping = {
location cascade: "all-delete-orphan", lazy:false //eager fetch strategy
}
}
class GeoAddress {
String addressLine1
String addressLine2
String addressLine3
String town
String county
String country = "UK"
String postcode
static belongsTo = Venue
static constraints = {
addressLine1 nullable:true
addressLine2 nullable:true
addressLine3 nullable:true
town nullable:true
county nullable:true
country nullable:true
postcode nullable:true
}
}
however when i write an integration test - i found the cascade create for location didnt work (i have to save the location its no longer tranient before passing to venue. also when i run a delete on the venue with flush:true enabled, and query for the address i still get the returned embedded address - i thought with the flush:true i'd see my GeoAddress cascade delete, but my test fails as i dont get a null when using GeoAddress.get(loc.id) as i was expecting
@Integration
@Rollback
class VenueIntegrationSpec extends Specification {
void "test venue with an address" () {
when: "create a venue and an address using transitive save on embedded "
GeoAddress address = new GeoAddress (addressLine1: "myhouse", town: "Ipswich", county: "suffolk", postcode : "IP4 2TH")
address.save() //have to save first - else Venue save fails
Venue v = new Venue (name: "bistro", location: address)
def result = v.save()
then: "retrieve venue and check its location loaded eagerly "
Venue lookupVenue = Venue.get(v.id)
GeoAddress loc = lookupVenue.location
loc.postcode == "IP4 2TH"
loc.town == "Ipswich"
when: " we delete the venue, it deletes the embedded location (Address)"
v.delete (flush:true)
GeoAddress lookupLoc = GeoAddress.get (loc.id)
then: "address should disppear"
lookupLoc == null
}
I thought i had set up this correctly but clearly i haven't. can any elucidate as to why my cascade actions for Venue.save(), and delete() don't cascade to my embedded location (GeoAddress) entry.
thanks in advance
ok - i read closely and looked for the difference - and it occurs if i save the embedded GeoAddress before i pass to the venue constructor like this (modified simple test)
when i add the extra a.save(), after creating the GeoAddress, the test will fail. if i comment the save out and rerun - it works fine. Not sure if this is a feature or a bug. Venue should do transitive save as the GeoAddress has an stati belongsTo = Venue declaration.
//new test - reuse embedded entity - works
void "test with GeoLocation" () {
when: ""
GeoAddress a = new GeoAddress(town:"ipswich")
a.save()
Venue v = new Venue (name: "bistro", location: a)
assert v.save(flush:true)
Venue lookupVenue = Venue.get(v.id)
GeoAddress ta = lookupVenue.location
assert ta.town == "ipswich"
//try delete
v.delete (flush:true)
then : " retrieve temp"
GeoAddress.findAll().size() == 0
}
if any one can comment on bug vs feature for me - then if necessary i can raise a bug on the grails project to get it fixed. Else i'll just have to test carefully and make sure i do the right thing in my code
这篇关于无法级联保存或删除嵌入式类引用工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!