Ошибка возникает при добавлении наследования в domain: org.hibernate.TransientObjectException: объект ссылается на несохраненный переходный экземпляр

#hibernate #grails #grails-orm

#спящий режим #grails #grails-orm

Вопрос:

Мне трудно разобраться в сути проблемы, с которой я столкнулся. У меня есть два Domain Classes для моего приложения grails: HeadOfHousehold и Dependent . Они почти идентичны, за исключением нескольких мест; во-первых, HeadOfHousehold владеет с Dependent помощью конструкции: static hasMany = [dependents: Dependent] , и Dependent имеет static belongsTo = [headOfHousehold: HeadOfHousehold] , во-вторых, Dependent имеет свойство, String type которое может быть либо Spouse или Dependent while HeadOfHousehold имеет transient метод getType() , который просто возвращает Self , и, наконец, есть два свойства currentAddress и previousAddress которые также Domain object являются s, которые содержатся в HeadOfHousehold , в то время как any Dependent указывает на обратноена HeadOfHousehold адреса . Теперь у меня возникли проблемы с выполнением любого запроса, который использовал бы более одного аспекта Current Address Dependent , поэтому я решил объединить эти объекты с помощью наследования, чтобы я мог просто запросить родительский класс из двух и получить результаты от обоих HeadOfHousehold и Dependent .

Поэтому я объединил их следующим образом: Parent Class Person

 class Person {
    String firstName
    String lastName
    String middleName
    String suffix
    Date dateOfBirth
    Date dateAdded
    String driversLicenseNumber
    String driversLicenseState
    String ssn
    String gender
    Address currentAddress
    Address previousAddress
    MVR mvr
    CreditReport creditReport
    ClueAuto clueAuto
    ClueProperty clueProperty

    static transients =['reportDOB','reportDlNumberState','firstLastMiddleSuffix',
                    'reportAddressString']
    static constraints = {
            middleName blank: false, nullable: true
            suffix blank: true, nullable: true
        ssn matches: "[0-9]{9}"
        gender blank: true, nullable: true, matches: "M|F"
        currentAddress nullable: true
        previousAddress blank: true, nullable: true
        mvr nullable: true
        creditReport nullable: true
        clueAuto nullable: true
        clueProperty nullable: true
        dateAdded nullable: true
    }

    public String toString(){
        String returnValue = lastName   ", "   firstName   " "   middleName
        return returnValue.replaceAll("null"," ")
    }


    //   I'm not sure if this is correct place for these, but they deal with
    // the transformation necessary to create the order object to send it
    // off to the broker in a byte[].
    def getReportDOB(){//dealing with dates is stupid in java X_X
            if(dateOfBirth){
            GregorianCalendar calendar = new GregorianCalendar()
            calendar.setTime(dateOfBirth)
            return DatatypeFactory.newInstance().newXMLGregorianCalendar(calendar)
        }
    }

    def getReportDlNumberState(){
        return driversLicenseNumber  "_"   driversLicenseState
    }

    def getFirstLastMiddleSuffix(){
        return (firstName "_" lastName "_" middleName "_" suffix).replaceAll("null","")
    }

    def getReportAddressString(){
        if(!previousAddress.isEmpty()){
        return "0_HOME,1_BUSINESS"
        } else{
                return "0_HOME"
            }
    }

    //TODO This really shouldn't be necessary I need to figure out why it is.
        def convertGender(){
        switch(gender){
            case "M":
                return "M"
            case "F":
                return "F"
            default:
                return null
        }
        }
    }
  

Child Class Dependent

 class Dependent extends Person{
String type //relationship to head of household.


static belongsTo = [headOfHousehold: HeadOfHousehold]

static constraints = {

}

public String toString(){
    String returnValue = lastName   ", "   firstName   " "   middleName
    return returnValue.replaceAll("null","")
}

def beforeInsert(){
    currentAddress = headOfHousehold.currentAddress
    previousAddress = headOfHousehold.previousAddress
    dateAdded = new Date()
}
  

}

Child Class HeadOfHousehold

 class HeadOfHousehold extends Person{



static hasMany = [dependents: Dependent]
static transients =['type']

static mapping = {

}

static constraints = {


}

def getType(){
    return "Self"
}


}    
  

Теперь это отлично работает, за исключением того, что у меня возникли серьезные проблемы с созданием экземпляров объектов. Я продолжал получать сообщение об ошибке:

 Message: Error executing bootstraps; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: ....clients.Address
  

Который я решил, добавив адреса непосредственно в конструктор, а затем сразу же сохранив адреса
Таким образом:

 Address currentAddress = FactoryHelperPicardAndPike.createCurrentAddress()
  Address previousAddress = FactoryHelperPicardAndPike.createPreviousAddress()
  HeadOfHousehold hh = FactoryHelperPicardAndPike.createPicard(picardAdded, picardBirthDate, currentAddress, previousAddress)
  saveIt(currentAddress)
  saveIt(previousAddress)
  saveIt(hh)
  

Вместо:

 HeadOfHousehold hh2 = FactoryHelperPicardAndPike.createPike(pikeAdded, picardBirthDate) 
  Address currentAddress2 = FactoryHelperPicardAndPike.createPikeCurrentAddress() 
  Address previousAddress2 = FactoryHelperPicardAndPike.createPikePreviousAddress() 

  hh2.setCurrentAddress(currentAddress2)
  hh2.setPreviousAddress(previousAddress2)
  saveIt(currentAddress2)
  saveIt(previousAddress2)
  saveIt(hh2)
  

Я не совсем понимаю, в чем проблема; и почему это появилось только после того, как я добавил наследование. Я смог решить его только методом проб и ошибок, что не совсем полезно, когда я столкнусь с проблемой в будущем. Теперь я прочитал все вопросы, на которые я мог найти ссылки unsaved transient instance , и лучшее, что я могу понять, это ошибка, указывающая, что мой Address объект считается переходным процессом, пока он не будет сохранен, и по какой-то причине он не будет каскадно сохраняться с HeadOfHousehold помощью or Dependent . Я не понимаю, чем он отличается для унаследованного объекта от отдельного объекта. Итак, кто-нибудь может объяснить, почему я получаю ошибку с унаследованными объектами, а не наоборот? Кроме того, где-нибудь есть подробное объяснение ошибки? Я прочитал это, и это не совсем понятно для меня.

Я знаю, что это долго, и я ценю ваше внимание.