Grails: master domain field by detail domain field [hasMany] - grails

There are domains:
class Order {
static hasMany = [execDepartments: Department]
String orderNo
//boolean signature
...
}
class Department {
String name
...
}
I want to add boolean signature field for Order but by Department, so I need field signature by execDepartments for Order. Is it possible? Please help.

Is this an m:m relationship?
why not create another domain like
class Order {
static hasMany = [execDepartments: DepartmentOrder]
String orderNo
//boolean signature
...
}
class DepartmentOrder{
boolean signature
Order order
Department department
}
class Department {
String name
static hasMany = [execOrders: DepartmentOrder]
}
Then you can write the belongTo

What you need is a list of signatures in the Order domain.
Possibly an OrderSignature domain that maps signatures to orders.

Related

How to create 3 domain relationships in Grails 3?

I have 3 domain class and I need to define their relationships but I find no luck in defining them correctly. Can somebody rectify my code? I have always get the error unknown column pointing to an id. Please help. Below are my codes. Thank you.
Todo.groovy class
package todoScaff
import userScaff.User
import categoryScaff.Category
class Todo {
String name
String note
Date createDate
Date dueDate
Date completedDate
String priority
String status
User owner
Category category
static belongsTo = [User, Category]
static constraints = {
name(blank:false)
createDate()
priority()
status()
note(maxsize:1000, nullable:true)
completedDate(nullable:true)
dueDate(nullable:true)
}
String toString() {
name
}
}
Category.groovy class
package categoryScaff
import todoScaff.Todo
import userScaff.User
class Category {
String name
String description
User user
static belongsTo = User
static hasMany = [todos: Todo]
static constraints = {
name(blank:false)
}
String toString(){
name
}
}
User.groovy class
package userScaff
import todoScaff.Todo
import categoryScaff.Category
class User {
String userName
String fname
String lname
static hasMany = [todos: Todo, categories: Category]
static constraints = {
userName(blank:false, unique:true)
fname(blank:false)
lname(blank:false)
}
String toString(){
"$lname, $fname"
}
}
Errors
I'm fairly certain your SQL tables are incorrect.
I created a small project with your 3 domain classes and used the grails command schema-export; after removing everything that doesn't relate to the domain relationship, the structure should look like this:
create table category (
id bigint,
user_id bigint,
);
create table todo (
id bigint,
category_id bigint,
owner_id bigint,
);
create table user (
id bigint
);
If your table structure doesn't resemble this, you should either change it to match or use the static mapping = {} closure in the domain class to indicate the proper column names.
Static Mapping
In Todo:
static mapping = {
owner column: 'owner_id' // change owner_id to match your owner column within todo
category column: 'category_id' // change category_id to match your category column within todo
}
In Category:
static mapping = {
owner user: 'user_id' // change user_id to match your user column within category
}

Command Object and hasmany

I'm trying to use the commandObject to validade my data when I submit my form. Can I validate a hasMany relation in commandObject. My cenario is something like this.
Tow simple classes whith hasMany relationship:
class Book{
String nameBook
}
class Author{
String nameAuthor
static hasMany = [books:Book]
}
Simple commandObject with hasMany that i want to validate when submit form.
#grails.validation.Validateable
class MyValidateCommand{
String nameAuthor
static hasMany = [books:Book]
static constraints = {
nameAuthor nullable:false
books nullable:false
}
}
Ps: I know that this commandObject is wrong, it don't compile. But can I do something like this ???
hasMany in GORM is used for association in Domain objects. In case of command objects it will be a lucid approach to have different command objects for each domain (for example: AuthorCommand and BookCommand) and the command object would look like:
import org.apache.commons.collections.list.LazyList
import org.apache.commons.collections.functors.InstantiateFactory
//Dont need this annotation if command object
//is in the same location as the controller
//By default its validateable
#grails.validation.Validateable
class AuthorCommand{
String nameAuthor
//static hasMany = [books:Book]
//Lazily initialized list for BookCommand
//which will be efficient based on the form submission.
List<BookCommand> books =
LazyList.decorate(new ArrayList(),
new InstantiateFactory(BookCommand.class))
static constraints = {
nameAuthor nullable:false
books nullable:false
//Let BookCommand do its validation,
//although you can have a custom validator to do some
//validation here.
}
}
Not sure why don't you can try like(normal hibernate hasMany declaration)
class MyValidateCommand{
String nameAuthor
Set<Book> books= new HashSet<Book>();
static constraints = {
nameAuthor nullable:false
books nullable:false
}
}

Grails object references an unsaved transient instance

i have this issue when i want to save my object
My Customer
String firstName
String lastName
LocalDate dateOfBirth
CountryCode nationality
My CountryCode
#Audited
class CountryCode implements Serializable {
String code
String symbolA2
String symbolA3
String countryName
static constraints = {
code size:3..3, unique: true, matches: '[0-9]+'
symbolA2 size:2..2, nullable: false, unique: true, matches: '[A-Z]+'
symbolA3 size:3..3, nullable: false, unique: true, matches: '[A-Z]+'
countryName size:1..50
}
static mapping = {
id generator: 'assigned', name: 'code'
}
def beforeValidate() {
symbolA2 = symbolA2?.toUpperCase()
symbolA3 = symbolA3?.toUpperCase()
}
#Override
String toString() {
return countryName
}
}
when i try to save my object i recieve this error
Class
org.hibernate.TransientObjectException
Message
object references an unsaved transient instance - save the transient instance before flushing: lookup.iso.CountryCode
Do you have ideas how to fix this?
Thankx
Use Grails relation convention
static hasOne = [nationality:CountryCode]
at Customer class and
static belongsTo = [customer:Customer]
at CountryCode class
Check grails docs about that, especially paragraph stating about cascade saves.
If this doesn't fit your case than you need to call save() on CountryCode instance before assigning it to a Customer instance.
You can also use static embedded if apply to your case.
Another thing if you consider CountryCode as a dictionary entity, then load desired ContryCode instance from repository before assigning it to the Customer instance.
The specific reason for your error is because you haven't saved CountryCode before assigning it to the Customer, so Hibernate (the underlying ORM for Grails) considers it transient. Basically you do not have any GORM relationships (e.g, has*, belongsTo) defined. By defining a GORM relationship, you gain the ability to have cascade save/delete depending on how the relationships are defined.
Before simply adding hasOne or belongsTo to Customer and CountryCode respectively, you may want to consider how you are using CountryCode. Is CountryCode used as:
one-to-many lookup/reference/dictionary entity where many Customers may be mapped to a particular CountryCode
one-to-one unique entity where there's a unique CountryCode per Customer
To implement #1, you should define just a uni-directional relationship using belongsTo in CountryCode WITHOUT a hasOne in Customer like so:
class CountryCode {
static belongsTo = [customer: Customer]
...
}
This will create a foreign key on the Customer table referencing a particular CountryCode - basically a one-to-many.
To implement #2, you should define a bi-directional relationship using belongsTo in CountryCode WITH a hasOne in Customer like so:
class Customer {
static hasOne = [country: CountryCode]
..
}
class CountryCode {
static belongsTo = [customer: Customer]
..
}
This will create a foreign key on the CountryCode table back to a particular Customer - basically a one-to-one mapping.

Grails hasMany error creating beans

I'm creating a (theoretically) simple hasMany relationship within a domain class. I have two tables with a foreign key relationship between the two. Table 1's domain object is as follows:
Functionality{
String id
static hasMany = [functionalityControllers:FunctionalityController]
static mapping =
{
table 'schema.functionality'
id column:'FUNCTIONALITY_NAME', type:'string', generator:'assigned'
version false
}
}
and domain object 2
FunctionalityController
{
String id
String functionalityName
String controllerName
static mapping =
{
table 'schema.functionality_controller'
id column:'id', type:'string', generator:'assigned'
version:false
}
}
The issue I am having is that when I have the hasMany line inside of the Functionality domain object, the app won't start (both the app and the integration tests). The error is org.springframework.beans.factory.BeanCreationException leading to Invocation of init method failed; nested exception is java.lang.NullPointerException.
Any help would be appreciated.
UPDATE:
*Working Domains*:
class Functionality {
String id
static hasMany = [functionalityConts:FunctionalityCont]
static mapping =
{
table 'schema.functionality'
id column:'FUNCTIONALITY_NAME', type: 'string', generator: 'assigned'
functionalityConts( column:'functionality_name')
version false;
}
}
and
class FunctionalityCont {
String id
String functionalityName
String controllerName
static belongsTo = [functionality: Functionality]
static contraints = {
}
static mapping =
{
table 'schema.functionality_controller'
id column:'id', type: 'string', generator: 'assigned'
functionality(column:'FUNCTIONALITY_NAME')
version false;
}
}
Well 2 things...
1.I'm not sure but I guess that your domain class with the prefix 'Controller' maybe is the responsible, this is because grails is convention over configuration and by convention the controller class ends with Controller prefix and are in the controller folder, in this case is a lil' confusing
2.In GORM and in this case the relationship between objects can be unidirectional or bidirectional, is your decision to choose one, but in both cases there are different implementations, the class Functionality(btw is missing the 'class' word) has the right relationship to FunctionalityController through hasMany, but FunctionalityController doesn't knows about the relationship, so you can implement:
// For unidirectional
static belongsTo = Functionality
// For bidirectional
static belongsTo = [functionality:Functionality]
// Or put an instance of Functionality in your domain class,
// not common, and you manage the relationship
Functionality functionality
So check it out and tell us pls...
Regards
Try adding
static belongsTo = [functionality: Functionality]
to your FunctionalityController class. I suspect there is more to your error than what you've shown, but generally a hasMany needs an owning side to it. Since that is where the foreign key actually lives.

How to indicate a field in domain class not to be created in the database

I have a domain class like:
class Product {
String name
String number
}
and I only want name field be created in the database as a column, I will generate the number field in the code, I don't want it to be a column of the Product table in the database.
What's the best way to do that?
class Author {
String name
String getUpperCaseName() { name.toUpperCase() }
static transients = ['upperCaseName']
}
See http://www.grails.org/doc/latest/ref/Domain%20Classes/transients.html

Resources