Grails deletes referenced records by other domain object? - grails

I am a bit puzzled on the following..
A domain model consists of a Person who has Addresses, these Address
can also be referenced by other Persons..
So Person A has addresses 1, 2, 3 and Person B has adresses 1, 4 ,5
No when i delete Person A, Person B also loses his address 1!! I was
under the impression that the cascade: 'all-delete-orphan' was meant
for these kind off situations. But probably i am making a mistake!
How can i tackle this?
class Person {
Address address
Address addressPostal
Address addressInvoice
static mapping = {
address cascade:'all-delete-orphan'
addressPostal cascade:'all-delete-orphan'
addressInvoice cascade:'all-delete-orphan'
}
}
class Address {
String street
String streetNo
String streetSuffix
}

I think all-delete-orphan works the other way. When you remove the many object from the collection on the one side, the object gets auto-deleted. Otherwise, it would just get "orphaned" with null as the foreign key.
You could use it the other way. For example, Address had a static hasMany = [persons: Person] and you removed the person from it, all-delete-orphan would remove the Person.

Related

OneToMany association in grails domain classes

I want one to many association between the Person and Address domain class which will be more like :
create table person (id bigint),
version bigint not null,
primary key (id))
create table address (id bigint),
person_id bigint not null,
primary key (id))
I tried to establish oneToMany Relation between these two tables so that one person can have n number of addresses.
class Person{
static hasMany = [
addresses: Address
]
}
class Address{
Address address
}
This is how I think it should work, i tried serveral other option, but none worked as wanted. Either I get an crosstable or an error when starting the application.
Thanks for help
You need to do establish one-to-many relationship between the Domain class Person & Address as given below-
Person Domain class
class Person{
static hasMany = [addresses: Address]
}
Address Domain class
class Address{
static belongsTo = [person : Person]
}
Please go through the grails documentation for gorm to understand the
domain class relationships in depth.

Unidirectional Many To One mapping with cascade

Is it possible to map the following with GORM?
I want to get rid off all associated events when I delete a person.
Person object should not have a link to events.( I want to avoid using hasMany on Person domain)
class Person {
String username
}
class Event {
String description
static belongsTo = [person:Person]
}
I'm getting now a 'Referential integrity constraint violation' when doing person.delete() because events are not removed before deleting person.
I don't think that is possible without using hasMany (speaking of which, why do you want to avoid that anyway?)
This SO Question states:
Hibernate only cascades along the defined associations. If A knows
nothing about Bs, nothing you do with A will affect Bs.
Use static hasMany and bam, problem fixed.
Edit:
The only way I think you could achieve this is using beforeDelete on the Person class to delete all the associated Events, i.e.
class Person {
def beforeDelete() {
def events = Event.findAllByPerson(this)
for (e in events) {
e.delete()
}
}
}
See the documentation on Events and Auto Timestamping for more info on that.
The above will not work
Why not define a no reference mapping:
class Person {
String username
static hasMany=[Events]
}
This way there is no actual bindings of events to person but a person can have many events

Grails understanding belongsTo Association [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Grails/GORM: The meaning of belongsTo in 1:N relationships
I have 2 domain class with belongsTo association
class Teacher {
String name
String department
}
class Address {
String line1
String line2
// Teacher teacher //this line is commented.
static belongsTo = [teacher: Teacher]
static constraints = {
}
}
What is the advantage i get when i make Address belongsTo Teacher
do i need to declare teacher object reference in Address class (see the commented line in Teacher class)
The goal to have the belongsTo clause is to have bi-directional access from one class to the other. See Documentation of belongsTo.
You can omit the second declaring of teacher (you commented out).
So it should look like this:
class Teacher {
String name
String department
Set<Address> adresses = new HashSet<Address>() // here you could set a specific list/set data holder
static hasMany = [adresses:Address]
}
class Address {
String line1
String line2
static belongsTo = [teacher: Teacher]
static constraints = {
}
}
Here you have a one-to-many associaton, where both classes have access to each other. If you remove the belongsTo clause you can not access the teacher object from the adress object. This is also reflected in the database.
Goal of belongsTo isn't making the relations bidirectional - The goal is to specify which side of the association takes the ownership and to define the behavior of cascading save and delete operations
Read this documentation it explains every thing you need to know about belongsTo.

Saving a reference through belongsTo

I'm making a script using some already created (not by me) domain classes from grails.
class Person extends OAP {
static hasMany = [addresses: Address]
(...)
}
class Address {
static belongsTo = [oap: OAP]
(...)
}
class OAP has no reference to Address.
So I was trying to do:
p.save()
a.oap = p
println a.oap
a.save()
with p being Person and a being Address, but although it prints the correct person on the console, the reference is not saved on the address table (oap_id stays null)
P.S.: It may not be the best relationship set-up in grails, but that's what I have to work with
Try p.addToAddresses(a) and then p.save(). It should save both p and a.
See http://grails.org/doc/latest/guide/5.%20Object%20Relational%20Mapping%20%28GORM%29.html#5.2.4%20Sets,%20Lists%20and%20Maps
I have no idea how GORM will behave in this situation because you have essentially entered into this weird zone where you have a unidirectional hasMany on Person which results in a SAVE-UPDATE cascade behavior from Person and a NONE on Address. Then you also have a unidirectional one-to-one between Person and OAP which results in an ALL cascade behavior on the OAP side, and a NONE on the Address side. So I'm not sure what to even expect here. You need to fix the relationship to either:
Make it so OAP and not Person hasMany = [address:Address]
Make it so Address belongsTo = [person:Person]
Or, give some additional explanation as to what you're trying to do in your relationship and we can go from there.
Please try with this, it resolved my problem
p.addToAddresses(a);
p.save(flush:true)

Grails select will not return correct data

This a continuation of this question.
I have an Address class which contains basic street address information. I also have a User class which has the attributes physicalAddress, mailingAddress, cargoDestinations, and cargoSources. The User class looks something like this:
class User {
String username
String password
String firstName
String lastName
String businessName
String phoneNumber
Address physicalAddress
Address mailingAddress
static hasMany = [accounts:Account, cargoSources:Address, cargoDestinations:Address, cargoes:Cargo, loadsLogged:Load, loadsDelivered:Load]
Set accounts, cargoSources, cargoDestinations, cargoes
static mappedBy = [loadsLogged:"loggedBy", loadsDelivered:"deliveredBy"]
//some other stuff after this
And the Address class looks something like this:
class Address {
static belongsTo = [user:User]
String streetAddress
String city
String state
String zip
BigDecimal taxRate
//some other stuff after this
I followed the tutorial here for the most part. In step 5 my template looks like this:
<g:select
from="${account.user.cargoDestinations}"
name="cargoDestinations" value="">
</g:select>
The problem is that instead of returning only cargoDestinations, the template returns ALL addresses associated with that user. If I change from="${account.user.cargoDestinations}" to from="${account.user.physicalAddress}" or from="${account.user.mailingAddress}" I get the expected result, so I know my problem has something to do with how the cargoDestinations variable is mapped. How can I go about fixing this without changing my class files too much?
The way you have your addresses mapped, they all link back to the user on the user_id column. You'll need to add some fields to Address to distinguish how they're related to User, similar to how you've mapped Loads. For example:
class Address {
static belongsTo = [cargoSourceFor: User, cargoDestinationFor: User]
...
}
class User {
...
static hasMany = [cargoSources:Address, cargoDestinations:Address]
static mappedBy = [cargoSources: "cargoSourceFor", cargoDestinations: "cargoDestinationFor"]
...
}
If you're familiar with SQL, doing a grails schema-export and looking at target/ddl.sql can be helpful when setting up mappings.
I ended up adding several boolean fields to my address class, which made the design simpler and much easier to work with. This way I only need one class instead of several nearly identical classes. The boolean fields in the Address class now indicate if an address is a physical address, mailing address, cargo source, etc., or all of the above. As #ataylor pointed out, this system makes it so an address object can only be associated with one user from my User class, but it does not seem like that will ever be an issue. The worst case is that a multiple users would have the same address in real life, and my program would require the creation of a separate address object for each of those users, even though the addresses in question would be identical.

Resources