平台核心Eventbus抛出数据集成异常

时间:2014-11-03 14:13:14

标签: grails

我正在使用插件平台核心和事件总线模块。我需要添加一些域assync,但我强制同步测试,在我的数据库,但异常DataIntegrityViolation每次我试图save()时抛出。这就是域结构:

  class Alocacao {
    static belongsTo = [tipoUnidade: TipoUnidade]
    //Anothers attrs and constraints
}

class TipoUnidade {

    static belongsTo = [ estabelecimento : Estabelecimento];    

    static hasMany = [alocacoes: Alocacao];

    List<Alocacao> alocacoes

    //Constraints and fields...

}

在我的控制器中我有这段代码:

tipoUnidadeService.save(tipoUnidadeInstance)
event('criarAlocacaoQuartoEvent', tipoUnidadeInstance, [fork: false])

在我的事件中听取了这个:

class AlocacaoService {

@Listener(topic="criarAlocacaoQuartoEvent", namespace="app")
def defaultAlocacaoCreator(EventMessage<TipoUnidade> message) {
   Canal canalSist = Canal.findByNomeIlike("%manual%")
   TipoUnidade quarto = TipoUnidade.get(message.data.id)
   def alocacaoSistema = new Alocacao(exclusivo: 0, nExclusivo: 0, data: tmp.toDate(), canal: canalSist, tipoUnidade: quarto).save(failOnError: true) //EXCEPTION!!
}
}

我不知道该代码会发生什么。

这是完整的例外:

util.JDBCExceptionReporter SQL Error: 1048, SQLState: 23000
util.JDBCExceptionReporter Column 'tipo_unidade_id' cannot be null
services.AlocacaoService could not insert: [br.com.qreserva.portal.domains.Alocacao]; SQL [insert into alocacao (version, canal_id, data, date_created, exclusivo, n_exclusivo, tipo_unidade_id, alocacoes_idx) values (?, ?, ?, ?, ?, ?, ?, ?)]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [br.com.qreserva.portal.domains.Alocacao]
org.springframework.dao.DataIntegrityViolationException: could not insert: [br.com.qreserva.portal.domains.Alocacao]; SQL [insert into alocacao (version, canal_id, data, date_created, exclusivo, n_exclusivo, tipo_unidade_id, alocacoes_idx) values (?, ?, ?, ?, ?, ?, ?, ?)]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [br.com.qreserva.portal.domains.Alocacao]
    at br.com.qreserva.portal.services.AlocacaoService.defaultAlocacaoCreator(AlocacaoService.groovy:178)
    at org.grails.plugin.platform.events.registry.DefaultEventsRegistry$ListenerHandler.invoke(DefaultEventsRegistry.java:238)
    at org.grails.plugin.platform.events.registry.DefaultEventsRegistry.invokeListeners(DefaultEventsRegistry.java:160)
    at org.grails.plugin.platform.events.publisher.DefaultEventsPublisher.event(DefaultEventsPublisher.java:79)
    at org.grails.plugin.platform.events.EventsImpl.event(EventsImpl.groovy:154)
    at org.grails.plugin.platform.events.EventsImpl$_closure1_closure5_closure9.doCall(EventsImpl.groovy:83)
    at br.com.qreserva.portal.controllers.TipoUnidadeController.salvar(TipoUnidadeController.groovy:126)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)
Caused by: org.hibernate.exception.ConstraintViolationException: could not insert: [br.com.qreserva.portal.domains.Alocacao]
    ... 10 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Column 'tipo_unidade_id' cannot be null
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
    at com.mysql.jdbc.Util.getInstance(Util.java:381)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1015)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3491)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3423)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1936)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2060)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2542)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1734)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2019)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1937)
    at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1922)
    at com.jolbox.bonecp.PreparedStatementHandle.executeUpdate(PreparedStatementHandle.java:203)
    ... 10 more

[编辑]

我创建此git project来说明我的问题并发生相同的错误

[溶液] 我使用belongsTo类中的addTo * attrs解决了这个问题。但为什么这个工作我不知道。

3 个答案:

答案 0 :(得分:1)

核心问题是

MySQLIntegrityConstraintViolationException: Column 'tipo_unidade_id' cannot be null

该列是tipoUnidade变量的外键(驼峰式tipoUnidade变为tipo_unidade作为列名,并添加了_id后缀,因为它是一个FK)这意味着那里的值为null,意味着TipoUnidade.get(message.data.id)返回null。如果message.data.id为空(可能是因为message.data不为空但尚未保存?),或者如果没有该id的记录,则会发生这种情况。

由于您正在处理异步代码,我猜测这是一个时间问题,message.data值尚未保存,但您尝试根据插入的值加载值

检查值,并考虑启用SQL日志记录,以便查看项目的插入和检索顺序。

答案 1 :(得分:1)

我和EventBus有同样的问题。问题是EventBus适用于线程。我想你也使用了交易。这两个对象都是在两个不同的线程中创建的,休眠无法保存其中一个,因为另一个不可用。

答案 2 :(得分:0)

根据Burt的反应,我会使用addTo *解决问题,并解决问题。

TipoUnidade quarto = TipoUnidade.get(message.data.id)
quarto.addToAlocacoes(new Alocacao(exclusivo: 0, nExclusivo: 0, data: tmp.toDate(), canal: canalSist))
quarto.save(failOnError: true)

THX。