hibernate - 使用GORM进行多次链式保存

标签 hibernate grails groovy gorm

我们正在尝试保存通过外键约束链接在一起的多个域对象,并且使GORM无法正常工作。

域类:

class Degree {

/* Default (injected) attributes of GORM */
Long    id
Long    version

/* Automatic timestamping of GORM */
Date    dateCreated
Date    lastUpdated

String department
String subject
String catalogYear
String level
String type
Long   totalCredits
Double cumulativeGPArequired    
String capstone
String comment
String updatedBy

static hasMany = [degreeBlocks: DegreeBlock]    // tells GORM to associate other domain objects for a 1-n mapping

static mapping = {
    sort "id"
   version false
   table 'degree'
   columns{
           id column: 'id'
           department column: 'department'
           subject column: 'subject'
           catalogYear column: 'catalog_year'
           level column: 'degree_level'
           type column: 'type'
           totalCredits column: 'total_credits'
           cumulativeGPArequired column: 'cume_gpa_req'
           capstone column: 'capstone'
           comment column: 'degree_comment'                
           dateCreated column: 'date_created'
           lastUpdated column: 'last_updated'
           updatedBy column: 'updated_by'
   }
   id generator:'sequence', params:[sequence:'degree_id_sequence']
}   

static constraints = {
    department(nullable: true, maxSize: 30)
    subject(nullable: true, maxSize: 30 )
    catalogYear(nullable: true, maxSize: 9 )
    level(nullable: true, maxSize: 15)
    type(nullable: true, maxSize: 30)
    totalCredits(nullable: true, maxSize: 3)
    cumulativeGPArequired(nullable: true, maxSize: 3)       
    capstone(nullable: true, maxSize: 30)
    comment(nullable: true, maxSize: 2000)
    lastUpdated(nullable: true)
    updatedBy(nullable: true)
}

@Override   // Override toString for a nicer / more descriptive UI 
public String toString() {
    return "${subject}";
}
}

class DegreeBlock {

/* Default (injected) attributes of GORM */
Long    id
Long    version

/* Automatic timestamping of GORM */
Date    dateCreated
Date    lastUpdated

String  blockType
String  comment


static hasMany   = [courseBlocks: CourseBlock]  // TELLS GORM TO ASSOCIATE OTHER DOMAIN OBJECTS FOR A 1-N MAPPING
static belongsTo = [degree: Degree] // TELLS GORM TO CASCADE COMMANDS: E.G., DELETE THIS OBJECT IF THE "PARENT" IS DELETED.

static mapping = {
    sort "id"
    version true
    table 'degree_block'
    columns{
           id column: 'id'
           level column: 'degree_level'
           blockType column: 'block_type'
           comment column: 'block_comment'
           dateCreated column: 'date_created'
           lastUpdated column: 'last_updated'
   }
    id generator:'sequence', params:[sequence:'degree_block_id_sequence']
}      
 static constraints = {
     blockType(nullable: true, maxSize: 50)
     comment(nullable: true, maxSize: 2000)
     lastUpdated(nullable: true)
   }


/*
 * Methods of the Domain Class
 */
@Override   // Override toString for a nicer / more descriptive UI 
public String toString() {
    return "${blockType}";
}
}

class CourseBlock {

/* Default (injected) attributes of GORM */
Long    id
Long    version

/* Automatic timestamping of GORM */
Date    dateCreated
Date    lastUpdated

String name
String rule
String credits
String eval
String prereqNotes
String comment

static hasMany = [courses: Course] // tells GORM to associate other domain objects for a 1-n mapping
static belongsTo = [degreeBlock: DegreeBlock] // tells GORM to cascade commands: e.g., delete this object if the "parent" is deleted.

static mapping = {
    sort "id"
    version false
    table 'degree'
    columns{
           id column: 'id'
           name column: 'name'
           rule column: 'rule'
           credits column: 'credits'
           eval column: 'eval'
           prereqNotes column: 'prereq_notes'
           comment column: 'course_comment'
           dateCreated column: 'date_created'
           lastUpdated column: 'last_updated'
   }
   id generator:'sequence', params:[sequence:'course_block_id_sequence']
}


static constraints = {
    name(nullable: true, maxSize: 80)
    rule(nullable: true, maxSize: 80 )
    credits(nullable: true, maxSize: 10 )
    eval(nullable: true, maxSize: 4)
    prereqNotes(nullable: true, maxSize: 2000)
    comment(nullable: true, maxSize: 2000)
    lastUpdated(nullable: true)
}

/*
 * Methods of the Domain Class
 */
@Override   // Override toString for a nicer / more descriptive UI 
public String toString() {
    return "${name}";
}
}

class Course {

/* Default (injected) attributes of GORM */
Long    id
Long    version

/* Automatic timestamping of GORM */
Date    dateCreated
Date    lastUpdated

String subject
String courseNumber
String title
String credits
String term

static belongsTo = [courseBlock:CourseBlock] // tells GORM to cascade commands: e.g., delete this object if the "parent" is deleted.

static mapping = {
    sort "id"
   version false
   table 'degree'
   columns{
           id column: 'id'
           subject column: 'subject_code'
           courseNumber column: 'course_number'
           title column: 'title'
           credits column: 'credits'
           term column: 'term'
           dateCreated column: 'date_created'
           lastUpdated column: 'last_updated'
   }
   id generator:'sequence', params:[sequence:'course_id_sequence']
}

static constraints = {
    subject(nullable: true, maxSize: 5 )
    courseNumber(nullable: true, maxSize: 5 )
    title(nullable: true, maxSize: 80)
    credits(nullable: true, maxSize: 8)
    term(nullable: true, maxSize: 10)
    lastUpdated(nullable: true)
}

/*
 * Methods of the Domain Class
 */
@Override   // Override toString for a nicer / more descriptive UI 
public String toString() {
    return "${subject} ${courseNumber}";
}
}

服务方法代码:
def saveDegree(params){
    def degree = new Degree(params).save()
    def degreeBlock = new DegreeBlock(params, degree:degree)
    degree.addToDegreeBlocks(degreeBlock)
    degreeBlock.save(flush:true)
    def courseBlock = new CourseBlock(params, degreeBlock:degreeBlock)
    degreeBlock.addToCourseBlocks(courseBlock)
    courseBlock.save(flush:true)
    def course = new Course(params, courseBlock:courseBlock)
    courseBlock.addToCourses(course)
    course.save(flush:true)

    return degree
}

我们在这里尝试了以下操作:
How do I save GORM objects with multiple many-to-one relationships?

但这给了我们错误:
| Error 2013-09-12 11:03:12,421 [http-bio-8080-exec-10] ERROR util.JDBCExceptionReporter  - ORA-02291: integrity constraint (FK1_DEGREE_ID) violated - parent key not found

| Error 2013-09-12 11:03:12,424 [http-bio-8080-exec-10] ERROR events.PatchedDefaultFlushEventListener  - Could not synchronize database state with session
Message: Could not execute JDBC batch update
Line | Method
->>   49 | saveDegree in degreebuilder.DegreebuilderService
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|     50 | save       in degreebuilder.DegreeController
|    195 | doFilter . in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter   in grails.plugin.cache.web.filter.AbstractFilter
|   1145 | runWorker  in java.util.concurrent.ThreadPoolExecutor
|    615 | run        in java.util.concurrent.ThreadPoolExecutor$Worker
^    724 | run . . .  in java.lang.Thread
Caused by BatchUpdateException: ORA-02291: integrity constraint (FK1_DEGREE_ID)  violated - parent key not found

->>  343 | throwBatchUpdateException in oracle.jdbc.driver.DatabaseError
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|   10698 | executeBatch in oracle.jdbc.driver.OraclePreparedStatement
|    297 | executeBatch in org.apache.commons.dbcp.DelegatingStatement
|     49 | saveDegree in degreebuilder.DegreebuilderService
|     50 | save . . . in degreebuilder.DegreeController
|    195 | doFilter   in grails.plugin.cache.web.filter.PageFragmentCachingFilter
|     63 | doFilter . in grails.plugin.cache.web.filter.AbstractFilter
|   1145 | runWorker  in java.util.concurrent.ThreadPoolExecutor
|    615 | run . . .  in java.util.concurrent.ThreadPoolExecutor$Worker
^    724 | run        in java.lang.Thread

使用调试器进行遍历,似乎直到方法底部的return语句才创建初始度,即使我认为(flush:true)应该强制持久化也是如此?

我只是想尽可能地以最简单,最正确的方式进行保存,并认为GORM可以通过这种方式进行处理,但也许不能。

最佳答案

您的情况是一对多,而不是多对一。

试试这个吧。必须先保留父级,最后要保留子级,您不必每次将子级与其父级关联时对它们进行flush编码,但最后可以刷新根父级以见证级联行为。

def saveDegree(params){
    def degree = new Degree(params)

    def degreeBlock = new DegreeBlock(params)
    degree.addToDegreeBlocks(degreeBlock)

    def courseBlock = new CourseBlock(params)
    degreeBlock.addToCourseBlocks(courseBlock)

    def course = new Course(params)
    courseBlock.addToCourses(course)

    degree.save(flush:true)

    return degree
}

关于hibernate - 使用GORM进行多次链式保存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18769938/

相关文章:

Grails Util 从 Bootstrap 读取文件

Spring Row 被另一个事务更新或删除(或未保存的值映射不正确)

java - 如何将组件中的列包含在自然 ID 中?

grails - Gorm一对一和一对多

sorting - DefaultGroovyMethod排序可导致版本更改和数据库更新

grails - 与Grails的零对多关系?

java - Hibernate 一对一映射的合并问题

java - 如何避免 IntelliJ 中可嵌入类的验证错误 "Cannot resolve column ' xy'"?

正则表达式导致无限挂起

java - 为什么我的 Android Studio 项目无法通过 Activity 打开?