Cannot get the value of ID when using ignoreNotFound - grails

Given the following domain classes, it is possible to get the value of author's ID from a Book object without fetching the related Author object like this: Book.get(1).authorId (see this SO question).
class Author {
hasMany = [books: Book]
}
class Book {
belongsTo = [author: Author]
}
However, adding books ignoreNotFound:true to Book static mapping (to get around some legacy issues) causes Book.get(1).authorId to be null.
Is there a way to get the value of AUTHOR_ID column in the BOOK table when the related record is missing in the AUTHOR table?

Related

Grails 3: find domains that were added to another one in many-to-many relationship (No value specified for parameter 1

I'm a Grails newbie and I found the following obstacle:
I have 2 domains: Course and Student, they have a many-to-many relationship (a Course can have several students, a student can enroll in several courses) and the student belongs to the course.
So, when I add a student to a course, I want to be able to find what Courses have added a specific student.
I tried to use:
def s = Student.get(id)
def c = Course.findAllByStudents(s)
But grails keeps telling me "No value specified for parameter 1".
Can you guys throw some light into this?
Course.findAllByStudents expects as parameter Set of Students but you are supplying it with single instance of Student, that's why you are getting "No value specified for parameter 1".
To find in what Courses is Student. If you created domain classes like this:
class Course {
//some Course attributes
static hasMany = [students: Student]
}
class Student {
//some Student attributes
static hasMany = [courses: Course]
static belongsTo = Course
}
then you can simply use s.courses.
If you are not two-way mapping that relationship. You can create criteria like this:
Course.withCriteria {
createAlias 'students', 's'
eq 's.elements', s
}

Grails(GORM) - Multiple many-to-many and cascade delete

Let's say i have 3 domain classes:
class Book {
static belongsTo = [Author,User]
static hasMany = [authors:Author,usersWhomReadThisBook:User]
String title
}
class Author {
static hasMany = [books:Book]
String name
}
class User {
static hasMany = [booksRead:Book]
String name
}
belongsTo defines a cascading relationship so deleting a parent will delete all objects that belong to it.
Question is: when I delete a User does it cascade up and delete the Books the user have read? Even if it still belongs to an existing Author? Or does it only delete from the join table?
The documentation is not clear on this use case.
Your question is:
When I delete a User does it cascade up and delete the Books the user have read? Even if it still belongs to an existing Author? Or does it only delete from the join table?
The answer is:No deletes are not cascaded for many to many,here if we delete the user only it will be deleted because the books is associated with other class Author.

Creating one-to-many & many-to-many for same domain class in grails

I want to create a domain class as like , One user can post many orders [Bidirectional] and one order can be liked by many users [unidirectional].
I have written a domain class as shown below ,
Class User {
String userName;
List orders
static hasMany = [Order]
}
Class Order {
String orderId
String orderName
//Indicates this order belongs to only one user
static belongsTo =[owner : User ] // Bidirectional
//Indicates order can be liked by many users
static hasMany = [likedUser : User] //Unidirectional
}
But I am getting am error saying invalid schema . Any body please help...
This post looks similar to my question but I am not getting , Please help.
First, order is a reserved word in SQL. Since GORM by default creates a table with the same name as your class, you'll need to either rename your class or provide a different name to use when mapping to SQL tables.
For example:
class Order {
static mapping = {
table 'user_order'
}
// ...
}
Another problem is that Order contains two associations to User. You need to tell GORM which one of these that is the bi-directional association from User to Order. That can be achieved using mappedBy, like this:
class User {
String userName
static hasMany = [orders: Order]
static mappedBy = [orders: 'owner']
}
Hope this helps.

Grails (GORM) Many-To-One Cascade Delete Behaviour

I've been struggling to produce the right configurations to produce cascade-delete behaviour in a relatively simple Grails project.
Say I have the following simple domain classes:
class Author {
String name
static constraints = {
}
}
and
class Book {
String title
Author author
static constraints = {
}
}
If I create an author, and then create a book written by that author, I am not able to delete the Author without first manually deleting the book. I get an "Integrity constraint violation". This isn't suprising as MySQL (my underlying database) is created by Grails with a "foreign key constraint" on the "author" column of the "book" table as "Restrict" (and this behaviour is consistent with expectations from the Grails documentation as I understand it).
Now, if I were to manually change the underlying database constraint on the "author" column of the book table from "Restrict" to "Cascade", I get the behaviour I want. Namely, that if you delete the Author, all their books are also deleted.
So, what I'd like to do is change my Grails "Book" class in a way that creates the "book" table with "on delete cascade" on the author column. I've been reading plenty of information about doing this sort of thing and GORM defaults using "belongsTo" and explicit "mappings".
One way to do this, based on the documentation for "belongsTo", seemed to be to change the line in the Book class from:
Author author
to
static belongsTo = [author: Author]
Thereby making it explicit that the Author is the "owning side" of the relationship. The documentation seems to suggest that this should generate the cascade-delete behaviour I'm after. However, it doesn't work unless I add an explicit "hasMany = [books:Book]" into the Author class. I don't wish to do this. (This wish makes more sense in my actual business domain, but even just as an exercise in understanding, I don't yet get why I have to have the Author domain class know about books explicitly).
I'd just like a grails setting to change the Book class to produce the "cascade delete" setting in the database, without having to change the Author class. I tried using an explicit mapping like:
static mapping = {
author cascade: 'all'
}
and combinations of this with other explicit mapping or "belongsTo" options. This didn't work.
Noting that a simple change to the "constraints" in the underlying SQL database provides the behaviour I want, is there a way to get this through Grails? If not, have I misunderstood something fundamental here or am I trying to do something stupid?
I think you are missing the required field of type Book in Author.
Here's the sample code, which is as per the documentation (tested and works)
class Author {
String name
Book book //you are probably missing this field
static constraints = {
}
}
class Book {
String name
static belongsTo = [author: Author]
static constraints = {
}
}
Test case:
#TestFor(Author)
#Mock([Book])
class AuthorTests {
#Test
void testAuthorBookCascades() {
Author a = new Author(name: "Douglas Adams")
Book b = new Book(name: "So Long, and Thanks for all the Fish")
a.book = b
a.save()
assert Author.count() == 1
assert Book.count() == 1
a.delete()
assert Author.count() == 0
assert Book.count() == 0
}
}
As you can see, you need the Book argument in Author. No need for the hasMany or hasOne clause.

Grails domain class relationship to itself

I need a way to be able to have a domain class to have many of itself. In other words, there is a parent and child relationship. The table I'm working on has data and then a column called "parent_id". If any item has the parent_id set, it is a child of that element.
Is there any way in Grails to tell hasMany which field to look at for a reference?
This is an example of what you are looking for (it's a snippet code I am running and it generates column parent_id). I don't think you need SortedSet:
class NavMenu implements Comparable {
String category
int rank = 0
String title
Boolean active = false
//NavMenu parent
SortedSet subItems
static hasMany = [subItems: NavMenu]
static belongsTo = [parent: NavMenu]
}
Furthermore, you can give name to the hasMany clause using the Mapping DSL, which is explained at http://grails.org/GORM+-+Mapping+DSL

Resources