grails not-null属性引用null或transient值:backref

时间:2015-01-20 02:16:08

标签: grails gorm transient

最近我试图修复Grails" not-null属性引用空值或瞬态值"没有太多运气的例外。

我有4个域类:

条形码:

class Barcode {

   BarcodeConfiguration barcodeConfiguration //holds where/how many barcodes should print, and which sequence iterates
   AppUser creationUser
   Date dateCreated = new Date()//bug in gorm means I have to do this manually

   //scannable barcode consists of prefix + sequenceId. These typically form the text as well, but not always
   String prefix //typically 3 letters description (eg: HIP, PAT, VAC). Denormalized from barcodeConfiguration to improve queries and ensure truth if barcodeConfig updated later.
   Long sequenceId //id printed for the sequence in barcodeConfiguration
   String text //text that describes the barcode - typically prefix + sequenceId, but different for controls where CTR1_[0-9]+ is used instead of CTR1
   BatchRes batch
   Boolean active = true

   static constraints = {
      batch(nullable: true)
      ...
   }
}

BatchRes:

class BatchRes {

   def springSecurityService
   def sessionFactory

   Pipeline pipeline
   AppUser operator

   List<Barcode> barcodes

   static hasMany = [
      selectedControls: ControlLot,
      barcodes: Barcode
   ]
}

批号:

class Lot implements Comparable<Lot> {

   static auditable = true

   // note: belongsTo seems to be needed for cascading validation (without custom validator)
   static belongsTo = [sample:Sample]
   static hasMany = [containers:Container]
   Integer lotNumber
   static constraints = {
      // enforce uniqueness of lotNumber among lots for a given Sample
      lotNumber(unique:'sample', validator:{it > 0})
   }
}

ControlLot:

class ControlLot extends Lot {
   public static final String BARCODE_PREFIX = "CTR"

   boolean passQC = false
   boolean active = false

   Date passQCDate
   Container sourceContainer
}

ControlLotService:

class ControlLotService {

   ControlLot createControlLot(ControlLotCommand command) {
      ControlSample sample = ControlSample.get(command.controlId)
      // container first
      ControlContainer sourceContainer = new ControlContainer()

      BarcodeConfiguration barcodeConfiguration = BarcodeConfiguration.findByName(ControlLot.BARCODE_PREFIX)
      sourceContainer.barcodeObject = barcodeService.createBarcode(barcodeConfiguration, null, null,
      sample.name)
      sourceContainer.save(flush: true)
      // lot second
      ControlLot controlLot = new ControlLot()
      controlLot.sample = sample
      controlLot.lotNumber = sourceContainer.barcodeObject.sequenceId
      controlLot.sourceContainer = sourceContainer
      controlLot.save(flush: true)
      controlLot.sourceContainer.lot = controlLot
      controlLot.save()
      return controlLot
   }
}

BarcodeService:

class BarcodeService {

   Barcode createBarcode(BarcodeConfiguration barcodeConfig,
                         BatchRes batch = null,
                         Long sequenceId = null,
                         String text = null) {
      if (!sequenceId){
         sequenceId = getSequenceNumber(batch, barcodeConfig)
      }
      // use blank constructor to fix HERO-302
      Barcode barcode = new Barcode()
      if(batch) {
         barcode.batch = batch
      }
      barcode.barcodeConfiguration = barcodeConfig
      barcode.prefix = barcodeConfig.prefix
      barcode.sequenceId = sequenceId
      barcode.text = text?:barcodeConfig.prefix + sequenceId
      barcode.creationUser = springSecurityService.currentUser as AppUser
      if (batch){
         log.info("Adding ${barcode} to ${batch}")
         batch.addToBarcodes(barcode)
         batch.save()//Following http://grails.org/doc/2.3.x/guide/GORM.html#sets,ListsAndMaps example Saves cascade down from one to many
      }
      else{
         barcode.save(flush: true)//need to explicitly save barcode if not attached to batch
      }
      barcodeConfig.isEditable = false
      barcode
   }
}

我收到以下错误消息:

2015-01-14 11:05:01,386 [http-bio-9090-exec-46] ERROR org.codehaus.groovy.grails.orm.hibernate.events.PatchedDefaultFlushEventListener  - Could not synchronize databa
se state with session
org.hibernate.PropertyValueException: not-null property references a null or transient value: com.gsg.enterprise.domain.lims.Barcode._BatchRes_barcodesBackref
    at com.gsg.enterprise.service.BarcodeService.createBarcode(BarcodeService.groovy:78)
    at GrailsMelodyGrailsPlugin$_closure4_closure16_closure17.doCall(GrailsMelodyGrailsPlugin.groovy:184)
    at com.gsg.enterprise.service.ControlService.createControlLot(ControlService.groovy:107)
    at GrailsMelodyGrailsPlugin$_closure4_closure16_closure17.doCall(GrailsMelodyGrailsPlugin.groovy:184)
    at com.gsg.enterprise.domain.lims.ControlLotController$_saveNew_closure4.doCall(ControlLotController.groovy:176)
    at com.gsg.enterprise.domain.lims.ControlLotController.saveNew(ControlLotController.groovy:171)
    at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:200)
    at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
    at net.bull.javamelody.JspWrapper.invoke(JspWrapper.java:151)
    at net.bull.javamelody.JdbcWrapper$DelegatingInvocationHandler.invoke(JdbcWrapper.java:277)
    at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:208)
    at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:181)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:619)
2015-01-14 11:05:01,447 [http-bio-9090-exec-46] ERROR grails.app.controllers.com.gsg.enterprise.domain.lims.ControlLotController  - not-null property references a nul
l or transient value: com.gsg.enterprise.domain.lims.Barcode._BatchRes_barcodesBackref; nested exception is org.hibernate.PropertyValueException: not-null property re
ferences a null or transient value: com.gsg.enterprise.domain.lims.Barcode._BatchRes_barcodesBackref
org.springframework.dao.DataIntegrityViolationException: not-null property references a null or transient value: com.gsg.enterprise.domain.lims.Barcode._BatchRes_barc
odesBackref; nested exception is org.hibernate.PropertyValueException: not-null property references a null or transient value: com.gsg.enterprise.domain.lims.Barcode.
_BatchRes_barcodesBackref
    at com.gsg.enterprise.service.BarcodeService.createBarcode(BarcodeService.groovy:78)
    at GrailsMelodyGrailsPlugin$_closure4_closure16_closure17.doCall(GrailsMelodyGrailsPlugin.groovy:184)
    at com.gsg.enterprise.service.ControlService.createControlLot(ControlService.groovy:107)
    at GrailsMelodyGrailsPlugin$_closure4_closure16_closure17.doCall(GrailsMelodyGrailsPlugin.groovy:184)
    at com.gsg.enterprise.domain.lims.ControlLotController$_saveNew_closure4.doCall(ControlLotController.groovy:176)
    at com.gsg.enterprise.domain.lims.ControlLotController.saveNew(ControlLotController.groovy:171)
    at grails.plugin.cache.web.filter.PageFragmentCachingFilter.doFilter(PageFragmentCachingFilter.java:200)
    at grails.plugin.cache.web.filter.AbstractFilter.doFilter(AbstractFilter.java:63)
    at net.bull.javamelody.JspWrapper.invoke(JspWrapper.java:151)
    at net.bull.javamelody.JdbcWrapper$DelegatingInvocationHandler.invoke(JdbcWrapper.java:277)
    at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:208)
    at net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:181)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:619)
Caused by: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.gsg.enterprise.domain.lims.Barcode._BatchRes_barcodesBackref

我使用的Grails版本是2.2.1版本

0 个答案:

没有答案