I'm having problems with validating the domain classes. I have two domains associated by one-to-one relationship:
class AssemblyForm {
Measures measures
static hasOne = [measures: Measures]
}
class Measures {
AssemblyForm assemblyForm
}
Now I'm binding and creating them in controller and service:
// controller
class AssemblyFormController {
def save() {
AssemblyForm assemblyFormInstance = new AssemblyForm()
assemblyFormInstance.measures = measures
assemblyFormService.save(assemblyFormInstance)
}
}
// service
class AssemblyFormService {
public AssemblyForm save(AssemblyForm assemblyForm) {
try {
assemblyForm.save()
} catch (Throwable t) {
}
return assemblyForm
}
}
Now I would expect assemblyForm entity not to be save in database if its association has error. But the fact is, when Measures entity has some errors, the AssemblyForm is persisted to database while the Measures entity isn't. Am I doing something wrong or this is standard behaviour and I should check the associated entity before saving? Thank you.
Regards,
Lojza
Related
I see there is a strategy for a one to one mapping for domain objects across different databases. But I am trying to associate two Domain objects that are in different datasources and have a one to many relationship.
class DomainA {
// default data source
}
class DomainB {
static hasmany = [domainA: DomainA]
static mapping = {
datasource 'ds2'
}
}
Any suggestions on how to make this work? Or a workaround?
Found a solution to this and it works pretty well. Solution is to create a join table in the schema you own.
E.g.
class DomainA {
// default data source
}
class DomainB {
List<DomainA> domainAList
static transients = ['domainAList']
static hasmany = [domainAIds: Integer]
static mapping = {
datasource 'ds2'
domainAIds joinTable: [name: 'DOMAINB_DOMAINA', key: 'DOMAINB_ID', column: 'DOMAINA_ID']
}
List<DomainA> getDomainAList(){
domainAList = domainAIds.collect { DomainA.get(it) }
domainAList
}
}
I have an application where Owner objects can have many Account objects and Account objects can have many Owner objects. I thought of modelling this with a many to many relationship but then I realized that I may also need to create Account objects where the Owner cannot be immediately determined or may be created in the future AFTER the account has already been created. Therefore I do not believe I can use the Grails many to many relationship(I think). So, I was just going to have a property in the Owner class that was a list of Account ids(this would be the Owner's Accounts references) and a property in the Account class which is a list of Owner ids(this would be the Account's Owners references). Any better ideas? I feel this is too old fashioned and is akin to the C++ pointers way of doing it.
You can create a third domain to resolve the relation like this
class Owner{
...
Set<Object> getObjects() {
OwnerObject.findAllByOwner(this).collect { it.object } as Set // or replace with optimized criteria
}
...
}
class Object{
...
Set<Owner> getOwners() {
OwnerObject.findAllByObject(this).collect { it.owner } as Set // or replace with optimized criteria
}
...
}
class OwnerObject implements Serializable {
Owner owner
Object object
boolean equals(other) {
if (!(other instanceof OwnerObject)) {
return false
}
other.owner?.id == owner?.id && other.object?.id == object?.id
}
static OwnerObject get(long ownerId, long objectId) {
find 'from OwnerObject where owner.id=:ownerId and object.id=:objectId',
[ownerId: ownerId, objectId: objectId]
}
static OwnerObject create(Owner owner, Object object, boolean flush = false) {
new OwnerObject(owner: owner, object: object).save(flush: flush, insert: true)
}
static boolean remove(Owner owner, Object object, boolean flush = false) {
OwnerObject instance = OwnerObject.findByOwnerAndObject(owner, object)
if (!instance) {
return false
}
instance.delete(flush: flush)
true
}
static void removeAll(Owner owner) {
executeUpdate 'DELETE FROM OwnerObject WHERE owner=:owner', [owner: owner]
}
static void removeAll(Object Object) {
executeUpdate 'DELETE FROM OwnerObject WHERE object=:object', [object: object]
}
static mapping = {
id composite: ['object', 'owner']
version false
}
}
Frankly, I have used m2m relation only once in my 6+ years "Grails-career". Instead a combination of o2m and dynamic queries is easier to implement and maintain and usually more performant.
I read that a m:m relationship often means there is a third class that isn't yet required. So I have m:m on User and Project, and I created a third domain class, ProjectMembership
The three domains are as follows (minimized for illustration purposes):
User
class User {
String name
static hasMany = [projectMemberships : ProjectMembership]
}
Project Membership
class ProjectMembership {
static constraints = {
}
static belongsTo = [user:User, project:Project]
}
Project:
class Project {
String name
static hasMany = [projectMemberships : ProjectMembership]
static constraints = {
}
}
If I have the ID of the user, how can I get a list of Project objects that they are assigned to?
There are a handful of ways - here are a couple:
def user = User.get(userId)
ProjectMembership.findAllByUser(user).collect { it.project }
or to avoid the query for the User:
ProjectMembership.withCriteria {
user {
eq('id', userId)
}
}.collect { it.project }
Be wary of queries that'll return large result sets - you'll end up with a huge in-memory list of project objects.
I know there are several questions on this subject but none of them seem to work for me. I have a Grails app with the following Domain objects:
class Tag {
String name
}
class SystemTag extends Tag {
// Will have additional properties here...just placeholder for now
}
class Location {
String name
Set<Tag> tags = []
static hasMany = [tags: Tag]
}
I am trying to query for all Location objects that have been tagged by 1 or more tags:
class LocationQueryTests {
#Test
public void testTagsQuery() {
def tag = new SystemTag(name: "My Locations").save(failOnError: true)
def locationNames = ["L1","L2","L3","L4","L5"]
def locations = []
locationNames.each {
locations << new Location(name: it).save(failOnError: true)
}
(2..4).each {
locations[it].tags << tag
locations[it].save(failOnError: true)
}
def results = Location.withCriteria {
tags {
'in'('name', [tag.name])
}
}
assertEquals(3, results.size()) // Returning 0 results
}
}
I have validated that the data is being created/setup correctly...5 Location objects created and the last 3 of them are tagged.
I don't see what's wrong with the above query. I would really like to stay away from HQL and I believe that should be possible here.
Welcome to hibernate.
The save method informs the persistence context that an instance should be saved or updated. The object will not be persisted immediately unless the flush argument is used
if you do not use flush it does the saves in batches so when you setup your query right after the save it appears that the data is not there.
you need to add
locations[it].save(failOnError: true, flush:true)
You should use addTo* for adds a domain class relationship for one-to-many or many-to-many relationship.
(2..4).each {
locations[it].addToTags(tag)
}
I'm a newbie in grails. i'm having a problem right now in my domain classes. I have 3 domain classes, class Patient,class Nurse and class NursePatient, the class NursePatient is a composite key where you can see who is the attending Nurse in a Patient, so if you view its table you can only see the id's of nurses and patients. This is my code for Nurse class:
class Nurse {
String name
Nurse partner
boolean idle = true
static belongsTo = [hospital: Hospital]
static constraints = {
name(blank:false)
partner(nullable:true)
hospital(nullable:false)
}
String toString(){
"Nurse ${name}"
}
}
--> and this is my domain class for NursePatient:
class NursePatient implements Serializable{
Nurse nurse
Patient patient
static mapping = {
version false
id composite:['nurse', 'patient']
}
static constraints = {
patient(nullable:false, validator:{val, obj -> val.hospital == obj.nurse.hospital})
nurse(nullable:false)
}
String toString(){
"Nurse ${nurse.name} - ${patient.name}"
}
void saveIt(Nurse x, Patient y){
def np = new NursePatient(nurse: x, patient: y)
if(np.save()){
def n = nurse.get(nurse.id)
n.idle = false
}
}
}
--> I was asked to print a list of nurses who doesn't have a patient. I was thinking that the moment I save in table using the saveIt() method from class NursePatient, once the save() is successful it changes the value of the property idle of class Nurse from true to false so that querying is much more easier. My problem is I don't if my code in class NursePatient is correct or is it possible to change the value of a property from another class. Please Help me.. thank You!!
Changing properties of domain classes inside different classes is fine.
However, you don't really need a NursePatient class. If you declare the relationship between Nurses and Patients as many-to-many, like this:
class Nurse {
static hasMany = [patients: Patient]
...
}
class Patient {
static hasMany = [nurses: Nurse]
...
}
then Grails will create and update the needed join table automatically. You can then query for all the nurses without patients using Criteria API:
def nursesWithoutPatients = Nurse.withCriteria { isEmpty("patients") }