Grails domain class does not add collection objects in one to many mapped classes Grails 5.1.7

38 Views Asked by At

I am working on a course creator website where a track can have multiple courses and they in turn, can have multiple assignments

The domain classes are defined as the following.

class Track {
String name
static hasMany = [courses: Course]
static constraints = {
    name minSize: 2
    courses nullable: true
}

@Override
String toString() {
    return name
}
}

and

class Course {
String name
static hasMany = [assignments: Assignment]
static belongsTo = Track
static constraints = {
    name nullable: false
    assignments nullable: true
}

@Override
String toString() {
    return name
}
}

and

class Assignment {
String name
String description
String url
static belongsTo = Course
static constraints = {
    name nullable: false
    description minSize: 20, widget: 'textarea'
    url nullable: true, url: true
}

@Override
String toString() {
    return name
}
}

While the final goal is to make a many to many relationship.

The bootstrap.groovy file has the following code.

        Assignment assignment1 = new Assignment(name: "Read Software Craftsman", description: "Software Craftsman " +
                "by Sandro Mancuso is one of the mandatory readings at Incubyte",
                url: "https://www.amazon.in/s?k=software+craftsmanship&sprefix=software+craftsman%2Caps%2C231&ref=nb_sb_ss_ts-doa-p_1_18")

        Assignment assignment2 = new Assignment(name: "Read Clean Coder", description: "Principles of clean coding is vital for the code readability. ",
                url: "https://www.amazon.in/Clean-Coder-Robert-C-Martin/dp/813178696X/ref=sr_1_1?crid=187IC46P73OZ7&keywords=clean+coder&qid=1654424906&sprefix=clean+coder%2Caps%2C451&sr=8-1")

        Course course = new Course(name: "Values and Practices of Software Development")
        Track track = new Track(name: "Practices").addToCourses(course)
        course.addToAssignments(assignment1).addToAssignments(assignment2)
        track.save()
        course.save()
        assignment1.save()
        assignment2.save()
        println track.getErrors()

While each one of the domain objects is being saved successfully, one to many relationship is not being persisted, and thus mapping tables TRACK_COURSE and COURSE_ASSIGNMENT have no data.

1

There are 1 best solutions below

1
Jeff Scott Brown On BEST ANSWER

While each one of the domain objects is being saved successfully, one to many relationship is not being persisted, and thus mapping tables TRACK_COURSE and COURSE_ASSIGNMENT have no data.

I cannot reproduce that but the project at https://github.com/jeffbrown/sapgormrelationships may help you.

I have pasted your code directly from the question into that project. At startup you will see the following written to stdout:

Hibernate: insert into track (id, version, name) values (default, ?, ?)
Hibernate: insert into course (id, version, name) values (default, ?, ?)
Hibernate: insert into assignment (id, version, url, name, description) values (default, ?, ?, ?, ?)
Hibernate: insert into assignment (id, version, url, name, description) values (default, ?, ?, ?, ?)
org.grails.datastore.mapping.validation.ValidationErrors: 0 errors
Hibernate: insert into track_course (track_courses_id, course_id) values (?, ?)
Hibernate: insert into course_assignment (course_assignments_id, assignment_id) values (?, ?)
Hibernate: insert into course_assignment (course_assignments_id, assignment_id) values (?, ?)

You can see inserts into both course_assignment and track_course. You can also validate that the data is there by interacting with the default scaffolding pages in the app.

grails-app/init/sapgormrelationships/BootStrap.groovy#L14-L30

@Transactional
void populateData() {
    Assignment assignment1 = new Assignment(name: "Read Software Craftsman", description: "Software Craftsman " +
            "by Sandro Mancuso is one of the mandatory readings at Incubyte",
            url: "https://www.amazon.in/s?k=software+craftsmanship&sprefix=software+craftsman%2Caps%2C231&ref=nb_sb_ss_ts-doa-p_1_18")

    Assignment assignment2 = new Assignment(name: "Read Clean Coder", description: "Principles of clean coding is vital for the code readability. ",
            url: "https://www.amazon.in/Clean-Coder-Robert-C-Martin/dp/813178696X/ref=sr_1_1?crid=187IC46P73OZ7&keywords=clean+coder&qid=1654424906&sprefix=clean+coder%2Caps%2C451&sr=8-1")

    Course course = new Course(name: "Values and Practices of Software Development")
    Track track = new Track(name: "Practices").addToCourses(course)
    course.addToAssignments(assignment1).addToAssignments(assignment2)
    track.save()
    course.save()
    assignment1.save()
    assignment2.save()
    println track.getErrors()
}

You have not provided enough information to know for sure, but I suspect that a transaction isn't being properly managed. If you remove @Transactional from my example, I expect you may see the same behavior you reported above.