Grails 模式多租户模式:GORM 侦听器仅适用于默认租户
Grails schema multitenancy mode: GORM listeners only working with default tenant
我正在使用 GORM 提供的架构模式将现有的 Grails 3 项目调整为多租户结构,但在指定租户时我无法让 GORM 侦听器工作。
我的监听器看起来像这样:
@CompileStatic
class VehicleListenerService {
@Listener(Vehicle)
void onPreInsertEvent(PreInsertEvent event) {
println "*** Vehicle preInsert"
event.entityAccess.setProperty('model', 'preInsert')
}
@Listener(Vehicle)
void onPreUpdateEvent(PreUpdateEvent event) {
println "*** Vehicle preUpdate"
event.entityAccess.setProperty('model', 'preUpdate')
}
}
因此每次创建或更新车辆时,都应将其模型更改为 preInsert 或 preUpdate。
当前租户由URL中指定的子域名决定。如果我访问没有子域的应用程序(通过 http://localhost:8080), the listener works as expected, but if I provide a subdomain (http://test.localhost:8080),侦听器不会执行任何操作,并且车辆模型不会更改。
我需要做什么才能让 GORM 侦听器与任何租户一起工作?
我创建了一个重现错误的示例项目 (https://github.com/sneira/mtschema)。
在 Grails Slack 频道的帮助和更多研究的帮助下,我想出了一个解决方案。
首先,侦听器服务必须扩展 AbstractPersistenceEventListener:
@CompileStatic
class VehicleListenerService extends AbstractPersistenceEventListener {
protected VehicleListenerService(Datastore datastore) {
super(datastore)
}
@Override
protected void onPersistenceEvent(AbstractPersistenceEvent event) {
String newModel =
event.eventType == EventType.PreInsert ? 'preInsert' : 'preUpdate'
event.entityAccess.setProperty('model', newModel)
}
@Override
boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
boolean supportsEvent = eventType.isAssignableFrom(PreInsertEvent) ||
eventType.isAssignableFrom(PreUpdateEvent)
return supportsEvent
}
}
现在我们可以为 Bootstrap.groovy 中的每个模式(默认模式除外)创建一个服务实例,并将其添加到我们的应用程序中:
def init = { servletContext ->
def ctx = grailsApplication.mainContext
['TEST', 'TEST2'].each { String name ->
HibernateDatastore ds = hibernateDatastore.getDatastoreForConnection(name)
VehicleListenerService listener = new VehicleListenerService(ds)
ctx.addApplicationListener(listener)
}
}
我已经将完整的代码上传到https://github.com/sneira/mtschema/tree/listeners。
我正在使用 GORM 提供的架构模式将现有的 Grails 3 项目调整为多租户结构,但在指定租户时我无法让 GORM 侦听器工作。
我的监听器看起来像这样:
@CompileStatic
class VehicleListenerService {
@Listener(Vehicle)
void onPreInsertEvent(PreInsertEvent event) {
println "*** Vehicle preInsert"
event.entityAccess.setProperty('model', 'preInsert')
}
@Listener(Vehicle)
void onPreUpdateEvent(PreUpdateEvent event) {
println "*** Vehicle preUpdate"
event.entityAccess.setProperty('model', 'preUpdate')
}
}
因此每次创建或更新车辆时,都应将其模型更改为 preInsert 或 preUpdate。
当前租户由URL中指定的子域名决定。如果我访问没有子域的应用程序(通过 http://localhost:8080), the listener works as expected, but if I provide a subdomain (http://test.localhost:8080),侦听器不会执行任何操作,并且车辆模型不会更改。
我需要做什么才能让 GORM 侦听器与任何租户一起工作?
我创建了一个重现错误的示例项目 (https://github.com/sneira/mtschema)。
在 Grails Slack 频道的帮助和更多研究的帮助下,我想出了一个解决方案。
首先,侦听器服务必须扩展 AbstractPersistenceEventListener:
@CompileStatic
class VehicleListenerService extends AbstractPersistenceEventListener {
protected VehicleListenerService(Datastore datastore) {
super(datastore)
}
@Override
protected void onPersistenceEvent(AbstractPersistenceEvent event) {
String newModel =
event.eventType == EventType.PreInsert ? 'preInsert' : 'preUpdate'
event.entityAccess.setProperty('model', newModel)
}
@Override
boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
boolean supportsEvent = eventType.isAssignableFrom(PreInsertEvent) ||
eventType.isAssignableFrom(PreUpdateEvent)
return supportsEvent
}
}
现在我们可以为 Bootstrap.groovy 中的每个模式(默认模式除外)创建一个服务实例,并将其添加到我们的应用程序中:
def init = { servletContext ->
def ctx = grailsApplication.mainContext
['TEST', 'TEST2'].each { String name ->
HibernateDatastore ds = hibernateDatastore.getDatastoreForConnection(name)
VehicleListenerService listener = new VehicleListenerService(ds)
ctx.addApplicationListener(listener)
}
}
我已经将完整的代码上传到https://github.com/sneira/mtschema/tree/listeners。