我需要从客户端域中的某些地址字段计算坐标,因此为了将域类与此要求分离,我添加了一个自定义侦听器,该侦听器使用 Google Maps API 来获取正确的值。
一切正常,但调试'我已经意识到更新侦听器内部的域属性会启动另一个更新事件,并且我的侦听器会为每次更新调用两次 Google API 。
有人遇到这个问题??我究竟做错了什么??
领域:
class Client{
String address
String city
String country
String postalCode
double lat
double lng
....
}
服务:
class GoogleMapsService{
static transactional=false
def grailsApplication
def geocode(String address){
address=address.replaceAll(" ", "+")
def urlApi=grailsApplication.config.googleMaps.apiUrl+"&address=${address}"
def urlJSON = new URL(urlApi)
def geoCodeResultJSON = new JsonSlurper().parseText(urlJSON.getText())
return geoCodeResultJSON
}
}
事件监听器:
class ClientListener extends AbstractPersistenceEventListener{
public boolean supportsEventType(Class<? extends ApplicationEvent> eventClass) {
switch(eventClass){
case [PreInsertEvent,
PreUpdateEvent,
PostInsertEvent,
PostUpdateEvent,
PostDeleteEvent]:
return true
default:
return false
}
}
protected void onPersistenceEvent(AbstractPersistenceEvent event) {
if(!(event.entityObject instanceof Client)){
return
}
switch(event.eventType) {
//GOOGLE MAPS geocode
case [EventType.PreInsert,EventType.PreUpdate]:
this.updateCoords(event.entityObject)
break
//OTHER STUFF (notifications, no changing inside)
case EventType.PostUpdate:
//....
}
}
private String composeAddress(Client cli){
def resul=[cli.address,cli.city,cli.country,cli.postalCode]
return resul.findAll{it}.join(",")
}
private void updateCoords(Client cli){
def fullAddress=this.composeAddress(cli)
if(fullAddress){
def coords=googleMapsService.geocode(fullAddress)
if (coords.status=="OK"){
//**IMPORTANT STUFF THESE TWO LINES RAISE AN EVENT
cli.lat=coords.results.geometry.location.lat[0]
cli.lng=coords.results.geometry.location.lng[0]
}
}
}
}
更新:
实体在侦听器中为空,因此我无法从 preUpdate 使其工作,看起来有一个未解决的问题(http://jira.grails.org/browse/GRAILS-9374)
打算试试 SaveOrUpdate...
大更新:
我越来越近了,但仍然无法避免重复的呼叫。
由于我需要一个“saveOrUpdate”侦听器,而这个侦听器是特定于 Hibernate 的侦听器,因此我最终有两个侦听器:
- ClientMailListener(Grails 自定义监听器,postinsert,postupdate,postdelete,对象没有变化)
- ClientGeoListener(休眠监听器,映射为“保存更新”)
这个组合的状态是:
- 更新:好的,两个监听器都只调用一次
- 插入:KO!!,让我们更深入地了解一下。
1.它做了一个插入并调用postInsert grails监听器,为什么????
ClientMailListener.onPersistenceEvent(AbstractPersistenceEvent) line: 45
ClientMailListener(AbstractPersistenceEventListener).onApplicationEvent(ApplicationEvent) line: 46
SimpleApplicationEventMulticaster.multicastEvent(ApplicationEvent) line: 97
GrailsWebApplicationContext(AbstractApplicationContext).publishEvent(ApplicationEvent) line: 324
ClosureEventTriggeringInterceptor.publishEvent(AbstractEvent, AbstractPersistenceEvent) line: 163
ClosureEventTriggeringInterceptor.onPostInsert(PostInsertEvent) line: 129
EntityIdentityInsertAction.postInsert() line: 131
EntityIdentityInsertAction.execute() line: 90
ActionQueue.execute(Executable) line: 273
ClosureEventTriggeringInterceptor.performSaveOrReplicate(Object, EntityKey, EntityPersister, boolean, Object, EventSource, boolean) line: 250
ClosureEventTriggeringInterceptor(AbstractSaveEventListener).performSave(Object, Serializable, EntityPersister, boolean, Object, EventSource, boolean) line: 203
ClosureEventTriggeringInterceptor(AbstractSaveEventListener).saveWithGeneratedId(Object, String, Object, EventSource, boolean) line: 129
ClosureEventTriggeringInterceptor(DefaultSaveOrUpdateEventListener).saveWithGeneratedOrRequestedId(SaveOrUpdateEvent) line: 210
ClosureEventTriggeringInterceptor(DefaultSaveOrUpdateEventListener).entityIsTransient(SaveOrUpdateEvent) line: 195
ClosureEventTriggeringInterceptor(DefaultSaveOrUpdateEventListener).performSaveOrUpdate(SaveOrUpdateEvent) line: 117
ClosureEventTriggeringInterceptor(DefaultSaveOrUpdateEventListener).onSaveOrUpdate(SaveOrUpdateEvent) line: 93
ClosureEventTriggeringInterceptor.onSaveOrUpdate(SaveOrUpdateEvent) line: 108
SessionImpl.fireSaveOrUpdate(SaveOrUpdateEvent) line: 685
2.然后调用save-update监听器,更新de对象
ClientGeoListener.onSaveOrUpdate(SaveOrUpdateEvent) line: 34
SessionImpl.fireSaveOrUpdate(SaveOrUpdateEvent) line: 685
SessionImpl.saveOrUpdate(String, Object) line: 677
SessionImpl.saveOrUpdate(Object) line: 673
3.随后再次调用postUpdate grails 监听器,:(
最后更新
最后尝试只使用一个听众来保持简单。看起来重点是在插入之后执行休眠“保存更新”侦听器,详细信息:
如果我禁用自定义侦听器离开休眠侦听器 (GEO),则会发生以下情况:
1.插入客户端(空白坐标)并调用saveupdate监听器:
ClientGeoListener.onSaveOrUpdate(SaveOrUpdateEvent) line: 34
SessionImpl.fireSaveOrUpdate(SaveOrUpdateEvent) line: 685
SessionImpl.saveOrUpdate(String, Object) line: 677
2.坐标更新,有更新
抱歉这个大更新,想法?