Must I assign the relationship in each direction? Using the textbook domain classes for the hasOne relationship, this appears necessary from my testing so far to get the instances to recognize each other:
def face = new Face()
def nose = new Nose()
face.nose = nose
nose.face = face
I don't know why, though. And it's unconventionally awkward. I'm expecting there's a better way.
EDIT:
I need help with the relationship assignment. I do not need information on the mechanics of setting up a hasOne relationship in the domain classes, or a discussion about the wisdom of bi-directional references. I want to know why it takes more than a single statement to set the relationship between a nose instance and a face instance.
My two-statement solution is based on trouble I'm having in a complex application. I am going to try to reproduce my experience in a simple example.
Direct Answer
The need to set up the relationships, i.e. to assign nose to face and face to node, isn't really awkward. Hibernate is a RELATIONSHIP mapper, so you need to make the relationships explicit. That said, you can write less code by defining a
setNose(nose){
this.nose = nose
nose.face = this
}
on Face. Now when you do face.nose = nose, the setter gets invoked for you, and the relationship is setup the way you want.
General Useful Thoughts
In general, you do not need to assign the relationship in both directions. It is perfectly valid to have unidirectional or bidirectional relationships.
However, hasOne definition has very specific implications. The documentation very clearly states the purpose of hasOne is to tell hibernate to put the key that defines the relationship in the child, in this case Nose. If you think carefully about it, you will realize that the relationship should be bidirectional. Here are the thought points:
1) you define the hasOne on Face (i.e. the parent).
2) even though you have defined hasOne on the parent, the underlying table that is affected is the child's table (i.e. the face_id column on Nose)
3) Since the foreign key is on the child, the child must have a reference to its parent. If it didn't, you would have a property on the child that is a foreign key but is not related to an object.
4) Remember, you are using the ORM's machinery to define the relationship. While you could manually add a face_id field to Nose, and set up the values in code (i.e. manage the relationship yourself and not let the ORM tool do it), the fact that you are using ORM explicitly means the ORM tool will manage the relationship for you.
EDIT -- now reading my answer, I was unconvinced, so I wrote a test. I defined the Face and Nose classes as shown in the hasOne documentation, but I did not define the Face on the Nose. I tried to make it unidirectional. I wrote a test to see what what happen. Here is the test
class FaceTests extends GroovyTestCase {
public void testStuff(){
Face face = new Face()
Nose nose = new Nose()
face.nose = nose;
face.save(flush:true)
assertNotNull face.id
assertNotNull nose.id
}
}
and the result is an exception that contains
hasOne property [Face.nose] is not bidirectional. Specify the other side of the relationship!
So the framework even makes sure, for you, that when you use hasOne, you have a bidirectional relationship.
Related
I see that there are two different ways to make entity relationship on the example illustrated below (either by one to one or by many to many). Which one is better method? (What is the better method in terms of common practice or widely accepted convention. Possibly, which one is more efficient? If there is no better method what would be the trade-off of using one instead of another?)
One-to-one method
Many-to-many method
First of all, neither diagram is an entity-relationship diagram. Entity-relationship diagrams should be able to represent entity-relationship concepts, but the notation you used doesn't distinguish between entity relations and relationship relations, and shows columns, types and foreign key constraints, which belong in a physical model rather than a conceptual one. What you have is better described as table diagrams. For ERDs, I recommend Chen's original notation or something close to it.
The first diagram mixes a higher-level abstraction into an otherwise physical model, and for that reason, I recommend the second style as it's more consistent.
Note that in either diagram, CompanyType_ID in General appears at odds with the type of relationship you're trying to represent. It may not necessarily be wrong (entities described in General may each have a primary or distinguished CompanyType in addition to a set of secondary types) but even if it's modeled that way intentionally, it warrants a second look at least.
I'm new to Neo4J and I have a question about the most appropriate data model for a the problem domain described below.
Background
As I understand it, in Neo4J every relationship has a direction of sorts, outgoing, incoming or undirected. I read that a common mistake newbies make in "bi-directional" relationships is that they might model the relationship in both directions where in reality one undirected relationship would serve the purpose well. I also understand that irrespective of the direction it is possible at query time to ignore it and query based on either side of the relationship.
Problem Domain
This is a bit cliché, but stick with me, in a graph where "People" can connect with one another I felt tempted to model that as an undirected relationship. However, perhaps in my problem domain I want to store meta data on the relationship edge rather than at either of the People nodes. E.g. timestamp of when then connected or type of relationship (friend, family, employer etc...). Perhaps this is a "side effect" of using the spring-data-neo4j libraries but it seems that if I wish to data meta data on the edge rather than at the node I must create a class which is annotated as #RelationshipEntity rather than #NodeEntity. This necessitates a #StartNode and #EndNode which then seems to imply a direction to my otherwise undirected relationship...
Now, as it turns out this might not be a bad thing in my case because perhaps after all it turns out there is something useful about this additional directed context (e.g. perhaps I want to know who initiated the relationship so that the target node (person) must accept the invitation to be friends).
Now imagine that each person can place the "relationship" into a "group" like "friends, family, colleagues" etc I feel like I'd now need to actually have two distinct edges that point in either direction so that the meta data specific to the given direction has a natural place to reside. But this seems to have been described as a newbie anti-pattern.
Questions
I have two questions:
1) Should I use two separate distinct relationship edges that essentially point either way as a bi-directional relationship if I need to store meta data that is specific to the direction. e.g. Person A <--> Person B but person A placed Person B in the friends group whereas Person B placed A in the colleagues group.
2) Given the Java data model below, I am unclear what the direction attribute on the #Relationship annotation of Person should be. If I specify nothing it default to OUTGOING. But since it's a reflective relationship depending on which person instance you look at the relationship could be either outgoing or incoming, e.g. if person A adds person B, both are Person instances, but the direction is outgoing on the person A instance and incoming on the person B instance. Should the annotation be omitted altogether since I'm using a #RelationshipEntity?
Java Data Model
#NodeEntity
#EqualsAndHashCode(of = {"id"})
#NoArgsConstructor
public abstract class Person {
#GraphId
private Long id;
... other attributes
#Relationship(type = "CONNECTION_OF", direction = UNDIRECTED)
private Set<Connection> connections;
}
#Data
#RelationshipEntity(type = "CONNECTION_OF")
public class Connection {
#GraphId
private Long relationshipId;
... other meta-data
#StartNode
private Person from;
#EndNode
private Person to;
}
1) The rule of thumb that works well is to answer a question - if a relationship from A to B exists, can another relationship from B to A still be created, with different metadata? And can you delete one direction of the relationship independently of the other?
If the answer is yes they go for two directed relationships, otherwise stay with UNDIRECTED, and create initiatedBy=userId property or similar.
For your case where you put connections into groups - the thing is that you really categorize the people from another person's view, maybe it is a completely different fact independent of the CONNECTED_TO relationship?
You could e.g. create a group node and link that to owner and all people in the group, with following schema:
(:Person)-[:OWNS]-(:Group)-[:CATEGORIZED]-(:Person)
2) Keep the #Relationship(type = "CONNECTION_OF", direction = UNDIRECTED). For a given person X the connections Set is going to have elements that have from=X for outgoing edges mixed with elements that have to=X for incoming. All of these will be mixed in one collection.
What is the best practice for creating Unidirectional One to Many Relationships in Core Data?
For example...
Lets take two classic entity examples, "teacher" and "student".
Each student has one teacher, and each teacher has many students.
In CoreData right now you are forced to provide an inverse such that teacher is forced to have a reference to a 'student'. If you don't you get this nice warning that says something along the lines of...
file:///Users/josephastrahan/Documents/VisualStudioProjects/Swift3WorkOrders/WorkOrders/WorkOrders/WorkOrders.xcdatamodeld/WorkOrders.xcdatamodel/: warning: Misconfigured Property: Teacher.student should have an inverse
What if I don't want teacher to have a reference to student?
Some other posts have brought up that I should just allow the inverse anyways but I think this inverse may be causing an issue with one of my projects.
That said let me explain my exact issue.
Lets say that our teacher has a unique attribute int64 called 'id'. Lets say the students also have unique attribute int64 called 'id'.
The int64 is enforced to be unique by adding a constraint on the model for teacher on id. (refer to image below to see how that is done)
Every year there is new students but the teachers stay the same. So I decided that I want to delete all the students without deleting the reference to the teacher. So I set the delete rule to 'nullify' for the relationship for the teacher to student and 'nullify' for the student to teacher.
Now when I create a new student I want to assign one of the existing teachers to that student... (something like student.teacher = teacher object with id of 1 or the same id as before) however!! , because the teacher has the inverse relationship to a student that no longer exists (which in theory should be null) the program crashes!
I know this is the case as I've used print console logs to narrow it down the exact point that it occurs. Also I know this because if I add the delete rule of cascade for student the crash will go away but...then I lose my teacher! which I don't want...
Some things that I think might be the issue:
1.) When I do my testing I do it at the startup of the program which creates a new context everytime. Could it be that because I never deleted teacher it still thinks it refers to a student from a context that no longer exists? (if I'm even saying this right...)
I'm not sure the best solution to acheive what I'm trying to do with Coredata and any advice is much appreciated!
Note:
Forgot to mention I also have the Merge Policy of: NSMergeByPropertyObjectTrumpMergePolicy, which will overwrite the old data with the new. When I'm creating new students I'm creating new teachers also just using the same id which should follow this policy.
You are almost there.
The advice to keep the inverse relationship is a good one. Keep it.
Your issue is likely caused by different contexts. Instead of holding on to a teacher object in memory, you should fetch the teacher (based on the id) in the context in which you intend to use it.
Your nullified students should not have any impact. A to-many relationship is really a Set<Student>. Make sure the set is empty.
NB:
If you want to keep the student in the database (for historical purposes) - it seems from your description that this is the case - you might also consider another scheme: give your students another attribute (such as a year) and use that to filter the student list. You would not have to delete or nullify anything. You could also do some more interesting time-based queries on the data.
Unique Constraints are available with iOS9. Which have helped iOS Developers with adding and updating records in CoreData.
Unique Constraints make sure that records in an Entity are unique by the given fields. But unique constraints along with To-Many relationship leads to a lot of weird issues while resolving conflicts.
e.g. “Dangling reference to an invalid object.”
This post is basically focused to a small problem that may take days to fix.
http://muhammadzahidimran.com/2016/12/08/coredata-unique-constraints-and-to-many-relationship/
This question may seem a little bit naive, but do nodes have class names? I'm new to Neo4j and I've been looking at examples of how it is implemented in web frameworks, Rails especially. It seems like each node obviously holds the values of the class it belongs to, but, unless I'm misinformed, they don't seem to have class/table names like MySQL would have (eg table 'users'). If this isn't true, then why am I seeing so many examples of instantiated nodes with just the class fields and not the actual class name? If this is true, how would I refer to all nodes of a certain class (or create them)? Through their edges?
Check out Neo4J Labels. A label is a way of, well, labeling a node in neo4j according to a certain class it might belong to. So you might create a node with the label "Person". This isn't exactly what you mean by a "class" but a lot of people use it in roughly the same way.
By labeling nodes with class names that are relevant for your domain, you get the ability to query all of them, and only those nodes of a certain "class". Example:
MATCH (user:Person)-[:FRIEND]-(friend:Person) RETURN user, friend
This query specifies that "user" and "friend" must both be labeled "Person", which I think is pretty close to what you want.
Similar or perhaps related to this question.
Say I have an object class "Zoo". It has a to-many relationship to objects of (abstract) type "Animal". As such, an Animal belongs to a Zoo object, and has the property 'zoo' and the Zoo object has the property 'animals'.
However, I am generally more interested in concrete sub-entities, such as Giraffe, or Monkey.
I would like to have a relationship property called "giraffes" and "monkeys", but also the property "animals". I would like to create Giraffe objects and add them to the Zoo.
How would this work? I can't specify in the relationships giraffes and monkeys that its inverse is "zoo" because this would be invalid (in the Core Data Editor).
I am generally working with the subclasses, but I need to always be able to ask them what Zoo they belong to, so need a common interface.
Would appreciate some help and please let me know if there's anything I could clarify.
I think you choose a hard way to get what you want. Create your diagram like below and you can fetch everything you need. When you fetch a specific animal (let's say a monkey) you can always get their relations with other entities.
zoo -->> (to many) animal --> (to one) animalType
Based on your description, I'd consider removing the zoo <-> animal relationship as you don't use it often and it will be a burden to maintain. The relationship would also contain a potentially large number of items so you want finer grained control than the relationship alone allows. And, with other relationships you can specify the deletion semantics.
You like using specific methods so add explicit relationships between the Zoo and each of your animal sub-entities. Specify the deletion rules on each of these (so destroying the Zoo kills all the animals) if required. Each animal will have a link to the zoo and it will be appropriately named.
For the Zoo knowing all of the animals, use a fetch request. You don't use it often and, when you do, you should really be specifying the batch faulting approach.
Aside:
Generally you should use the relationship simply as the data source for a fetch request, specifically so that you can specify the batch faulting approach. Even if you have 50 giraffes, that's probably more than you will use at any one time for display on the UI. If you're doing a data operation then directly using the relationship could be good. But if you're listing the items on the UI you should use a fetch request where the predicate uses the relationship to filter the appropriate objects.
Thanks for all the suggestions. In the end, I have a zoo-animals relationship, and on the Zoo object I wrote a few helpers:
#property (nonatomic, readonly) NSArray *giraffes; // or monkeys
- (NSArray*)giraffes
{
NSArray *giraffes = [Giraffe MR_findByAttribute:#"zoo"
withValue:self
andOrderBy:#"name"
ascending:YES
inContext:self.managedObjectContext];
return giraffes;
}
The baseclass was more important than you think, and knowing the Core Data will cache quite a bit, if I call this fairly frequently the performance will not be a problem.
(I use MagicalRecord if that API call looks a little strange.)