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