merge two domain objects and reassign children to one of them in Grails - grails

I have two entries in a domain entity that I want to merge. Let's call the parent House and the children Room. I have a situation where I want to merge two House domains that are actually the same. I have the logic to do this top level merge.
However, I want to know if there is a way in Grails to easily say, 'go through the domain objects and wherever there is a fk pointer to House, update that fk to a new value'.
The code would be something like this
houseInst1.magicMerge(houseInst2)
This would run the House merge as well as check for every domain object that has a pointer (fk) to House and update where it points to houseInst2 originally to point to houseInst1.
Update: One key feature is that I'd like this to work if someone adds another domain object with a link to the master object. eg. if someone added Mortgages later, I don't want to update all my merge logic, it should go and find that Mortgages is a child of House, and update accordingly.

Grails domain objects expose the hibernate merge() method, but this does something completely different: it merges a (possibly detached) object back into the persistence context.
I'm not aware of any built in functionality to merge two objects like you describe. I think you need to manually update the foreign keys as in Gregg's answer. A more efficient way to do the update would be through HQL like so:
Room.executeUpdate('update Room set house = :newHouse where house = :oldHouse',
[newHouse: newHouse, oldHouse: oldHouse])
Edit: to automatically update all the associations, you can interrogate the Artefact:
def artefact = grailsApplication.getArtefact("Domain", "House")
artefact.associationMap.values().each { associationClass ->
associationClass.executeUpdate("update ${associationClass.simpleName} set house = :newHouse where house = :oldHouse",
[newHouse: newHouse, oldHouse: oldHouse])
}

How about something like this? You'll want to do this before you get rid of the old house.
Room.findAllByHouse(oldHouse).each { room ->
room.house = newHouse
room.save()
}
I haven't tried this and I'm assuming a pretty standard OneToMany relationship between House and Room.

Related

OGM Custom Query using Custom Label

I have a Neo4j/OGM Entity Person which I mapped to the Label User using
#NodeEntity(label="User).
I now want to write a custom Query MATCH (p:Person) where....
As far as I see, there is no way to use my Application-Side Type Person instead of the Graph-Side Label User like in Hibernate, right?
If there is a way, please explain how to do this, or tell my a key-word to google for.
Same question goes for entity properties.
Thank you.
Update:
Lets say I have a User class like so:
#NodeEntity(label="Person")
class User {
#Property(name="username")
private String name;
...
}
I've used the Mapping to obtain loose coupling so I can eg. rename the Person and won't affect the Neo4j.
And in the Neo4j there are for example Houses with Relationships to Users.
Now I want to load all Houses, referencing a User with the name "Sven", so the Statement would be MATCH (h:House)-[:HOLDS]->(p:Person {username:'Sven'}).
Given, that I might have a huge poject with all the entities in some submodule somewhere else, I might not know, that User is mapped to Person and the user.name is mapped to username, so in a Hibernate environment, I would query as MATCH (h:House)-[:HOLDS]->(u:User {name:'Sven'}). However in OGM this doesn't seem to work.
There might be a way to solve this architectually but in some projects you don't have this choise.
So the question in the End is: Is there some way to get this to work, or do I really need to know the mapping of every entity i use?
You can do this in several ways :
Make your User extend a Person class
if you need more dynamic labels, the class can contain an #Labelsannotated list of labels to apply. See the documentation for more details
About properties, I don't see how this would be useful. Interested to hear about the use case.

Core data with unique constraints and relationships-IOS

I have a core data design with multiple tables using relationships. My database is SQLite. For updates I import data from JSON and use this method:
[NSEntityDescription insertNewObjectForEntityForName:entityName inManagedObjectContext:context].
I have added unique constraints in core data.
If I update an entity that is a relationship of another object it loses the connection.
Ex: Entity "person" that contains the one to one relationship to "pet_id". If I update "pet" it changes his id and "person" still points to the old id, so they are not related any more.
Is there a way to avoid this problem?
I don't think this is documented anywhere yet. Here's what it sounds like is happening:
You create a new instance. Your constraints mean that this instance matches an existing instance. But...
Your new instance has a nil value for this relationship. So...
The existing instance's value for the relationship is replaced by this new nil value.
To maintain the relationship, your new instance needs to already have the correct value for that relationship. You're essentially asking that the constraint matching system ignore the fact that the relationship value is different in your new instance, but to accept new values for other attributes.
I think what you're expecting is completely reasonable but I'm also not surprised that the current implementation doesn't support it. I recommend filing a bug with Apple about this, and investigating non-constraint based approaches to keeping your data unique.

Custom Join table in grails

I have a following domains
User (in database called usermanagement) and
Account (in another database xyz)
Its an old system so i cannot really change the architecture of the system. I have been assigned task to implement a system that a certain users can only access certain accounts. This is a classic case of many-to-many relationship but the problem lies in the fact that these two domains are in two different databases. I googled if that was possible but i realized that it was not possible. So I now am thinking of creating a custom join table to store info on which user are allowed access to which accounts. The table can have two columns 'accountId' and 'userId'. So for this, do i have to create a new domain in grails or is there any cleaver way of doing this ?
Thanks in advance.
If you create joinTable in which DB you are going to create it and how you are going handle updates in main (Account,User) tables and ceep your join table up2date ?
I think (for this case) you don't need join table, you need handle business logic in application level.
You cane have 2 Domain classes each one pointed to different dataSource(DataBase).
http://grails.org/doc/latest/guide/conf.html#multipleDatasources
As I searched for solution of this, I did not find any sustainable solutions. I eventually narrowed down the probable solutions to two:
1. Create a domain table (only) using sql, some sort of patch and use hard-coded queries in grails to write and access data to and from the table.
2. Create a domain class like AccountUser having properties clientId and userId
I choose the 2nd option, I wrote some additional methods and created a service to return user and client instance and I am done ! Anyways, thanks guys.
If the databases are "visible" to each other (on the same server or there is a db link between them), you should be able to map the domain classes using the fully qualified table names ('schema.tablename') in the mapping closure.
psuedocode:
class User {
static mapping = {
table "usermanagement.user"
}
static hasMany = [Account:accounts]
}
class Account {
static mapping = {
table "xyz.account"
}
}
http://grails.org/doc/latest/guide/GORM.html#tableAndColumnNames

Reassigning one-to-one relationship nulls previous object / CoreData iOS

I have 2 entities. ObjectA stores all ObjectB's objects through a many-to-many relationship. ObjectA also stores one specific object as a default object using a one-to-one relationship. The idea is to be able to assign many different child objects for EntityA while also keeping a specific reference to one specific child object. This idea works perfectly fine all throughout my project exempt in one circumstance(identical code and identical entity relationship setups.
The problem I am having is when I reassign the existing defaultObject to a new different object by simply ObjectA.defaultObject = someObject23; this assigns the new object correctly but in the process my original To-Many relationship reference to that existing defaultObject goes null.
The to-many relationship 'AllObjects' from EntityA has a Cascade delete rule for EntityB.
The One-To-One relationship 'DefaultObject' has a NULL delete rule for EntityB.
Both have inverses set.
Here is a real quick overview.
ObjectA.allObjects = 10 objects; // 1 of these is someObject1
ObjectA.defaultSomeObject = someObject1; // This works fine.
ObjectA.defaultSomeObject = someObject2; // This assigns the new defaultSomeObject=someObject2,
// but in the process it removes the someObject1 from my ObjectA.allObjects array (Goes NULL)
I'm stumped because like I say I have used this technique multiple times and the only workaround to this I have succeeded with is to "rig" it and actually save a reference to the previous object, delete it from the ObjectA array, set the new defaultObject, then write that object back to the array. There must be a simple explanation I am overlooking. More coffee? lol. Any help is greatly appreciated. I have tried all the different delete rules for each relationship as well just for kicks.
Problem solved. Definitely needed more coffee. What was happening was the one-to-one relationship was using the to-many relationship inverse causing it to do exactly what it was supposed to do, go null...

add user define properties to a domain class

i have a requirement to allow the user to define some custom field in one of the system entities. do you have any suggestion/pattern/plugin that will help me add this feature to my application.
thanks,
Meni
You can add a Map property to your domain class and store arbitrary data there. It's rather limited though. It will generate a table with varchar(255) keys and values, so you need to manage any type conversions yourself, e.g.
class Thing {
String name
Map extraProperties = [:]
}
int age = 123
def thing = new Thing(name: 'whatever')
thing.extraProperties.age = age.toString()
thing.save()
...
def thing = Thing.get(thingId)
int age = thing.extraProperties.age.toInteger()
See section "5.2.4 Sets, Lists and Maps" at http://grails.org/doc/latest/ for the brief online docs.
Sounds like you want your application to be an infinitely adjustable wrench that users can modify at will. Is that fair?
I don't think it's possible or desirable. Think about what happens when you add an attribute to an existing domain object in Grails. The attribute is added to the ORM mapping, which means the tables have to be modified. The UI has another text box added for data entry; the list page has another column added to its table.
There's a lot going on when you add an attribute. How will you manage multiple users modifying the app all at the same time? What happens when one user is modifying a table while another is accessing the old version?
You ask too much. I don't think it's a reasonable requirement. Grails' sweet spot is rapid development of web-based CRUD applications. I don't think that includes modification by users at runtime.

Resources