I am trying to understand the relationship between classes in Object oriented world, and came across various terms like:
Association , Aggregation, Composition, Dependency, Generalization, Realization, Using (and may be there are more to the list, which I would encounter soon).
I came across the following UML diagram:
Here, we have two different Classes (and so objects), Car and Road, and the connector symbol connecting them (and I believe it is directed association symbol, as per MS Visio).
So this means that Car and Road classes are having some relationship (association). I have some doubts on this to understand this relation:
1) How would this relationship be translated to Java classes? I am having difficulty in understanding how Car and Road would have "some code" connecting them?
2) what does * and 0..1 mean in this diagram? Usually I have seen these in an Entity-Relationship diagrams (in DB).
Any pointer to understand this would be of great help.
A Car object would have a reference to a Road object (in other words, an instance variable of type Road). A Road object would also have a list (or List) of Car objects. The first sentence represents the 0..1 relationship between the classes; note that the reference could be null (car is on 0 roads) or not (car is on one road). The list in the Road object represents the * relationship -- 0 or more cars are on the road.
1) is too broad to answer. UML and Java are both formal languages with well-defined structures, but there is no standardized way of expressing any particular UML concept in Java or vice versa. Thus, any answer would be opinion-based.
Furthermore, an association is a loosely-defined relationship. UML has many others more strictly defined (you've listed a few), and those are easier to translate to source code.
Because there are more strictly defined relationships, the correct reading of an association relationship is along the lines "these two things are related somehow, but not so tightly that the one contains the other, or that the one uses the other, or is dependent on the other." Those concepts all have their own connectors, and the modeller has made a conscious decision not to use them.
2) * means "any number" and 0..1 means "zero or one", which is usually read as "an optional". So the drivesOn relationship associates any number of Cars with an optional Road.
Presumably this should be taken to mean that a car may drive on a road, but never on more than one, and a road may have any number of cars driving on it.
In terms of understanding UML, this is a very poor example so don't try to read too much from it.
Your questions do have simple answers:
Your uni-directional many-to-one association drivesOn is expressed in (or translated to) Java in the form of a single-valued reference property in the following way:
class Car {
int passengers;
Road drivesOn;
}
The symbols * and 0..1 represent multiplicities: * means many (or unbounded) and 0..1 means at most one, so your model makes two multiplicity statements: (1) a Car movesOn at most one Road, and (2) a Road has many Cars moving on it.
A pointer for reading more about the meaning of associations and multiplicities and how they are expressed in Java is my book chapter Reference Properties and Unidirectional Associations.
It is like many cars can be associated to no road or at max one road. In other words many cars can be driven on 1 road or not at all driven on any road
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last month.
Improve this question
In Java apps, I prefer to use unique fields in equals and hashCode methods instead of adding only id field or all the fields. However, I am confused about the following points:
By considering object states in Hibernate, I think it is good practice not using id field in equals and hashCode methods, right?
When there is a unique field in a class, is it enough to use only one of the unique fields in equals and hashCode methods (except from id field)?
Should I add all the fields except from id field when there is not any unique field except from id field in a class? Or should I only add some numeric field instead of adding text fields?
JPA and Hibernate don't specify or rely on any particular semantics for entities' equals() and hashCode() methods, so you can do what you want.
Good alternatives
With that said, there is a handful of alternatives for equality that make much more sense to me than any others:
Equality corresponds to object identity. This is of course the default provided by Object.equals(), and it can serve perfectly well for entities. OR
Equality corresponds to persistent identity. That is, entities are equal if and only if they have the same entity type and primary key. OR
Equality corresponds to (only) value equality. That is, equality of all corresponding persistent fields except the ID. There are additional variations around how that applies to mapped relationships. OR
Equality corresponds to persistent identity AND value equality. Again, there are variations around how the value equality part applies to mapped relationships.
General advice
In general, you would do well to follow a fule rules of thumb:
As with most other classes, especially mutable ones, default to just inheriting Object.equals() and Object.hashCode(). Have a specific purpose and plan before you do otherwise, and remember that you get only one choice for this. And that it is impactful.
If you do override equals() (and therefore hashCode() as well) then do it in a consistent way across all your entities.
Think carefully before you go with an option involving value equality. This is usually a poor choice for mutable classes in general, and entities are no exception.
Specific Questions
1. By considering object states in Hibernate, I think it is good practice not using id field in equals and hashCode methods, right?
I think using the ID is fine. It's simply a question of what you want equality to represent for your entities. You absolutely can have distinct entity objects with the same type and ID, and you might want to be able to detect that with equals(). The other persistent fields might or might not factor into that.
In particular, an equals() method based solely on entity ID might make sense for entities that appear on the "many" side of a one-to-many relationship when that is mapped to a Set.
2. When there is a unique field in a class, is it enough to use only one of the unique fields in equals and hashCode methods (except
from id field)?
I see no good reason to consider only a proper subset of unique fields, except that subset consisting only of the entity ID. Or if all the fields are unique then the one consisting of all the fields except the ID. The logic that suggests that you might be able to consider other proper subsets revolves around the persistent identity of the entity, which is completely and best represented by its ID.
3. Should I add all the fields except from id field when there is not any unique field except from id field in a class? Or should I only
add some numeric field instead of adding text fields?
If your sense of equality is to be based on entity value then I don't see how it makes much sense to omit any persistent fields except, possibly, the ID. Do not arbitrarily omit the ID -- it may very well be something you want to include. Again, it depends on what equals() is intended to mean for your entities.
That's a tricky question that hibernate itself doesn't have a clear answer on.
John Bollinger's answer covers your specific question, but there is some additional context about how to think about equality and hibernate that should help figure out what to do. After all, given that hibernate doesn't require you to do anything particular, you can do whatever you want, which leads to the obvious question: ... okay, so what should I do, then?
That question boils down to (using Person as an arbitrary example of a model class + associated table; furthermore, lets say the person table has a single unique ID that is generated (A random UUID or auto-sequenced integer value).
What does an instance of Person represent?
There are in broad strokes 2 answers:
It represents a person. A row in the person table also represents a person; these 2 things aren't related.
It represents a row in the person table.
It represents a state in my application, nothing more.
Even though these things sound quite similar, they result in opposite meanings as to equality.
Which choice is correct? That's up to you.
When reading on, remember:
Any Person instance which isn't "saved" yet, would have a null value for id, because upon insertion, hibernate will ask the DB to generate a value for it or generates one itself and only then fills it in.
An instance represents a row
Equality under the second model (an instance of Person represents a row in the table) should look only at the id column, because that defines row uniqueness; any 2 representations of a row in the person table are guaranteed to be referring to the same row (hence, equal) if and only if the id is equal. That is a necessary and sufficient condition: If they are equal the 2 objects are necessarily referring to the same row, and if they aren't equal, then they are necessarily referring to different rows.
Notably, if id is still null, then they cannot be equal, not even to themselves: More generally the question: "Is this object-representing-a-row equal to this other object-representing-a-row" is a meaningless question if these objects are representing rows-to-be (unsaved rows). If you invoke save() on each object, you end up with 2 rows. Optimally such an object should be considered in a state such that attempting to invoke equals on it is a failure, but the spec of equals states that they can't throw, therefore, false is the best answer. This would mean you want:
class Person {
// fields
#Override public boolean equals(Object other) {
if (other == this) return true;
if (other == null || other.getClass() != Person.class) return false;
UUID otherId = ((Person) other).id;
return id == null ? false : id.equals(otherId);
}
}
This defines your equals method as 'ends up representing the same row'. This holds even if you change meaningful state:
Change the name and save the object? It's... still the same row, and this equality implementation reflects this.
Call save() on each in the comparison when they were unsaved? Then you get 2 rows - and this equality implementation reflects this before and after attempting to save it.
If invoking on self (a.equals(a)) this returns true as the equality spec demands; it also works out in the 'modelling a row' view: If you invoke save() on the same object twice, it's still just one row.
An instance represents a person
The nature of what a person is is entirely unrelated to the autosequence/autogen ID it gets; the fact that we're using hibernate is an implementation detail that should play no part at all in considering equality; after all, this object represents the notion of a person, and that notion exists entirely independent of the database. The database is one thing that is modelling persons; instances of this class are another.
In this model you should do the exact opposite: Find something that uniquely identifies a person itself, and compare against that. After all, if you have 2 rows in a database that both contain the same social security number, then you have only 1 person.. and you just happen to have 2 rows that are both referring to the same person. Given that we chose our instance to imply that it represents a person, then an instance loaded from row A, and an instance loaded from row B, ought to be considered as equal - after all, they are representing the same individual.
In this case, you write an equals method that considers all relevant fields except the autoseq/autogen ID field! If there is a separate unique id such as social security number, use that. If there isn't, essentially it boils down to an equals method that compares all fields, except ID. Because that's the one field that definitely has zero bearing on what defines a person.
An instance defines a state in your application
This is almost a cop-out, and in general means equality is irrelevant / not applicable. It's like asking how to implement an equals method to an InputStream implementation - mostly, you.. don't.
Here, the default behaviour (Object's own impls) are what you want, and therefore, you don't implement either hashCode or equals. Any instance of Person is equal to itself (as in, a.equals(a), same reference), and not equal to any other, even if the other has identical values for each and every field, even the id field isn't null (represents the same row).
Such an object cannot meaningfully be used as a value object. For example, it would be pointless to stuff such things in a hashmap (at best, you can stuff them in an IdentityHashMap, as those semantics would apply. Only way to do any lookups is to have a ref that was .put() into it before and call .get() with that).
Which one is right? Up to you. But document it clearly, because in my experience, lots of hibernate users are absolutely convinced either the first or second model is the one, and only, right answer, and consider the other answer utterly bonkers. This is problematic - they'd be writing their code assuming all hibernate model classes work precisely as they want, and would therefore not even be thinking of checking docs/impl to know how it actually works.
For what its worth, objects are objects and database rows do not neatly map to the notion of an object. SQL's and java's notion of null are utterly incompatible, and the notion of 'a query' does not neatly map to tables (between selecting expressions, selecting on views, and JOINs, that should be obvious) - hibernate is tilting at windmills. It is a leaky abstraction and this is one of its many, many leaks. Leaky abstractions can be useful, just, be aware that at the 'edges' the principle hibernate tries to peddle you (that objects can represent query results and rows) has limits you will run into. A lot.
Excerpt from Java EE 7 tutorial:
SELECT DISTINCT p FROM Player p, IN (p.teams) AS t WHERE t.city = :city
Expressions cannot navigate beyond (or further qualify) relationship
fields that are collections. In the syntax of an expression, a
collection-valued field is a terminal symbol. Because the teams field
is a collection, the WHERE clause cannot specify p.teams.city (an
illegal expression).
Why expressions cannot navigate beyond relationship fields that are collections?
I didn't design the language, and I could of course miss more important reasons, but IMHO, it wouldn't make much sense: p.teams.city reads as "the city property of the teams property of p". But teams is a collection. And collections don't have any city property.
That's at least a good way to remember that this is not vald JPQL.
Following question also refers to discussion in following questions as well
https://stackoverflow.com/search?page=2&tab=Relevance&q=one%20to%20many%20unidirectional%20java
Best practise for adding a bidirectional relation in OO model
I tried to implementing 8 association combinations formed by [Unidirectional/Bidirectional] X [(One/Many) to (One/Many)] in Java. I found two cases can not be implemented namely Unidirectional One to One and Unidirectional One to Many (e.g. Person->*Vehicle). Other 6 combinations and Composition are possible programatically.
I Feel its not only the case with Java, these 2 cases do not exist. e.g. Use case - allocate one Aadhar/SSN number to only one person is possible if we know that number is not allocated to anybody else (reverse navigation is must). Does this mean we need to take care while making our design model not to arrive at these specific associations (though they might be present in analysis model)? I am confused on this.
Basic (No Aggregation)
If you are looking at basic unidirectional association, then that's the simplest of them all.
Unidirectional One to One
class Person {
String name;
}
Unidirectional One to Many
class Person {
List vehicles;
}
Composite Aggregation
If I assume that you are asking about composite relationshions (where one SSN can be assigned to at most one person), then you can still implement it.
How exactly you decide to implement it is however subject to your specific domain or e.g. how you store your data, because
reverse navigation is must
is not actually true, because you can just check all Person instances; or you can store all the SSNs in a smart data structure that allows you to quickly check if a new one is unique, and then you would assign it to the Person without additional checks, because you already know that it is unique).
Or you can implement also the opposite lookup, which is not prohibited even if the association is "uni-directional"
To quote the UML Specs (11.5.3.1 Associations) [emphasis mine]:
Navigability means that instances participating in links at runtime (instances of an Association) can be
accessed efficiently from instances at the other ends of the Association. The precise mechanism by which such efficient
access is achieved is implementation specific. If an end is not navigable, access from the other ends may or may not be
possible, and if it is, it might not be efficient.
Update from comments
Noone claims that upholding the relationship constraints has to be done in the accessors. In fact pretty much always you will have temporarily invalid relationships, imagine:
person = new Person();
// right now person is invalid state because it doesn't have an SSN
ssn = ssnGenerator.createNew();
// now ssn is also in invalid state because it has no person
person.setSSN(ssn);
// only now is person and ssn valid
(creating a constructor wouldn't help, because constructor is called after the object has already been created (so another part of the constructor could need the ssn already set).
So it is the responsibility of the programmer to ensure that the system upholds all constraints in whatever way it makes most sense. Using constructors/accessors is the easiest way in some circumstances, but you could e.g. wrap the code above in an atomic transaction. After all, if you kept your validation in the setSSN(), then what would happen if the programmer were to forget to call the method at all?
(person 1->* vehicle)
p1.add(v1) and p2.add(v1) are possible violations
You asked about "person ->* vehicle", now you've changed it to "person 1 -> * vehicle" so obviously the answer differs. But the same principle as above applies -- it is the responsibility of the system to uphold all constraints, and wherever that's done in accessors, validation methods, or the way the system constructed is an implementational detail -- there's no single best way, and there will be always trade-offs.
I'm currently taking a course in Software Engineering (I have to).
We have a whole bunch of tasks which require us to use design patterns in Java. Normally I'm just a PHP developer, so I don't have many skills in Java, which may be a problem.
The specific problem is: We have to use the composite pattern for following problem: Create a mathematic framework to solve terms. The term could be Number (double) or "/", "-" which connect two terms, or "sin" which uses one Term.
I have to create a UML Class Diagram to.
Which is this
I'm not sure if this is right. The two main questions I got about my class diagram are:
Is it correct to use value, and first/second for the Composites, because they only have either 1 or 2 Terms, or should I make a list with addmethod and make sure there are exactly 1/2 items in the list?
Should I create another Interface for the Composite Structures (Sin, Divide, Subtract)
Am I doing it right, or did I follow a bad/wrong approach?
Thank you
Bernd
The composite pattern really doesn't place any restrictions on how you represent the children of a composite node. In your case you could either have classes representing unary and binary operations or have separate classes for each operation.
The second option would look something like:
interface Term {
double getValue();
}
class Constant implements Term {
private double value;
public double getValue() {
return value;
}
}
class Divide implements Term {
private Term numerator;
private Term denominator;
public double getValue() {
return numerator.getValue() / denominator.getValue();
}
}
This is probably the closest representation of your UML. In this case there's no advantage in modelling the child terms as a List.
The other option I mentioned (which I would not recommend) is to have UnaryOperation and BinaryOperation classes and then define and enum for the operations. In this case the operation enumeration would contain the actual calculation logic. I think that's unnecessarily complex for your needs unless you have a large number of operations.
I'm sorry, but this isn't a correct implementation of the composite pattern. If you look at it, you'll see that you have no Composite (the object with add, remove, and getChild methods) class, and that you're aggregating the Leaf objects which you should not do.
If you're to apply the composite pattern to this problem, you need to come up with a class that contains the different operations to perform.
So, first create an abstract class called something like FrameworkItem. This corresponds to Component on the Composite pattern diagram. From this, derive another class called Term. This is your Composite, and is an aggregate of FrameworkItem. (Make sure it includes your add, remove, and getChild methods.) Finally, derive your Leaf classes individually (Number, Sin, Subtract, Divide etc.) from FrameworkItem as well, using simple association rather than aggregate.
Keep in mind that your Composite's solve() method needs to take a Leaf object as parameter, which tells it which one of its children's solve() methods it needs to call.
Consider this situation: I've got an aquarium simulator where I have 5 different types of fishes. Different types means different attributes (speed, colour, hunger, etc). What if I want the user of my simulator to be able to create a new type of fish and give it its values for its attributes?
How is that implemented by the programmer? Do I need some kind of "event handling" that will add a specific bunch of lines of code in my "Fish" class? Is that even a valid thought?
(In case it's essential, the language is Java. And to avoid any misunderstandings and prevent comments like "is this uni work?", yes it is. But I am not looking for THE answer, I am curious about the concept.)
EDIT: Yeah, my bad that I didn't mention the interaction way: a GUI.
So, imagine a tab called "Add New Species" that has a field for every attribute of the fishes (type, speed, colour, etc). So, the user fills in the fields with the appropriate values and when he clicks on "add" the constructor is called. At least that's how I imagine it. :)
I would just use a map:
class Fish
{
Map<String,String> attributes = new HashMap<String,String>();
setBusterFish()
{
attributes.put("speed", "5");
attributes.put("colour", "red");
attributes.put("hunger", "10");
attributes.put("name", "buster");
}
}
Java is an OO language, and it deals in classes and objects. The tempting, naive solution would be to have your program deal with "classes" of fish like it deals with classes of anything, i.e. to create some Java code and let the compiler and loader introduce it into the runtime.
This approach can be made to work, with some awkwardness. Essentially your "dynamic Java classes" coding would probably end up much bigger and complicated than your assignment actually intends.
You only really need to do this if you are actually going to have different attributes (not just different values of those attributes) for your different fish; and even then there are simpler solutions.
For what's being asked, I think you really only need one Fish class. When the user defines a new one, what he's really defining are the attribute values.
If you really want new and dynamic attributes, then you could go a long way using e.g. a HashMap to store name/value pairs. You could let the user add "legs" / "4" and then print out that new attribute as-is; but you couldn't make the fish walk on those legs because you'd be missing coding to work with the new attribute.
Have a look at the type object pattern. Also google for it I just gave one of the first references I found...
You may also look the Reflection pattern...
Let the user define attribute values of an instance of, say, a FishSpecies class, and give the FishSpecies a method createFish that creates a fish of that species (i.e. having those attribute values). Keeping track of all FishSpecies objects in a list grants you the opportunity to manage FishSpecies objects, and create Fish objects of given species.
If I understand your question correctly, then I believe that complicating things more than this is a mistake.