So I am surprised that doing a search on google and stackoverflow doesn't return more results.
In OO programming (I'm using java), how do you correctly implement a one-to-many relationship?
I have a class Customer and class Job. My application is for a fictious company that completes jobs for customers. My current implementation is so that the Job class doesn't have anything to do with the Customer class, there is no reference to it at all. The Customer class uses a collection and methods to hold, retrieve and modify information about the Jobs that have been assigned by and/or completed for a customer.
The question is, what if I'd want to find out for which customer a particular Job has been done? I've only found this article that's relevant: http://www.ibm.com/developerworks/webservices/library/ws-tip-objrel3/index.html.
According to the implementation of the author, I would let the Job constructor take a Customer parameter, and store it so I can retrieve it. However, I see no guarantee at all that this model can be consistent. There are no restirctions to set the related customer for a job as a customer that the job was not for, and add jobs to customers that were done for someone else. Any help on this would be appreciated.
There's no 100% surefire way to maintain the integrity.
The approach which is usually taken is to use one method to construct the relationship, and construct the other direction in that same method. But, as you say, this doesn't keep anyone from messing with it.
The next step would be to make some of the methods package-accessible, so that at least code which has nothing to do with yours can't break it:
class Parent {
private Collection<Child> children;
//note the default accessibility modifiers
void addChild(Child) {
children.add(child);
}
void removeChild(Child) {
children.remove(child);
}
}
class Child {
private Parent parent;
public void setParent(Parent parent){
if (this.parent != null)
this.parent.removeChild(this);
this.parent = parent;
this.parent.addChild(this);
}
}
In reality, you won't often model this relationship in your classes. Instead, you will look up all children for a parent in some kind of repository.
Maybe you didn't expect a complex (and zero-code) answer, but there is no solution to build your bombproof API the way you intend it. And it's not because the paradigm (OO) or the platform (Java), but only because you made a wrong analysis. In a transactional world (every system that models real life problems and their evolution over time is transactional) This code will ever break at some point:
// create
Job j1 = ...
Job j2 = ...
...
// modify
j1.doThis();
...
// access
j2.setSomeProperty(j1.someProperty);
because at the time j1.someProperty is accessed, j1 and j2 could not even exist :)
TL;DR
The long answer to this is immutability, and it also introduces the concepts of life cycle and transactions. All other answers tell you how to do it, instead I want to outline why. A one-to-many relationship has two sides
has many
belongs to
Your system is consistent as long as if Customer A has Job B, the Job B belongs to Customer A. You can implement this in a number of ways, but this must happen in a transaction, ie a complex action made of simple ones, and the system must be unavailble until the transaction has finished execution. Does this seem too abstract and unrelated to your question? No, it isn't :) A transactional system ensures that clients can access system's objects only if all these objects are in a valid state, hence only if the whole system is consistent. From other answers you see the amount of processing needed to solve some problems, so that guarantee comes at a cost: performance. This is the simple explanation why Java (and other general purpose OO languages) can't solve your problem out of the box.
Of course, an OO language can be used to both model a transactional world and accessing it, but special care must be taken, some constraints must be imposed and a special programming style be required to client developers. Usually a transactional system offers two commands: search (aka query) and lock. The result of the query is immutable: it's a photo (ie a copy) of the system at the very specific moment it was taken, and modifying the photo has obviously no effect on the real world. How can one modify the system? Usually
lock the system (or parts of it) if/when needed
locate an object: returns a copy (a photo) of the real object which can be read and written locally
modify the local copy
commit the modified object, ie let the system update its state based on provided input
discard any reference to (now useless) local objects: the system has changed changed, so the local copy isn't up to date.
(BTW, can you see how the concept of life cycle is applied to local and remote objects?)
You can go with Sets, final modifiers and so on, but until you introduce transactions and immutability, your design will have a flaw. Usually Java applications are backed by a database, which provides transactional functionalities, and often the DB is coupled with an ORM (such as Hibernate) to write object oriented code.
You can ensure that there are no duplicates by using a Set implementation like HashSet instead of using other data-structure.
And instead of adding Job to a customer, create an final inner class in Job class that has private constructor. That ensure that the wrapper inner class can only be created by a job object. Make you Job constructor take in jobID and customer as parameter. To maintain consistency -if customer is Null throw Exception as dummy jobs shouldn't be created .
In add method of Customer, check to see if the Job wrapped by JobUnit has the same customer ID as the its own id, if not throw Exception.
When replacing a customer in Job class remove the JobUnit using the method provided by Customer class and add itself to the new customer and change the customer reference to the newly passed customer.
That way you can reason with your code better.
Here's what your customer class might look like.
public class Customer {
Set<JobUnit> jobs=new HashSet<JobUnit>();
private Long id;
public Customer(Long id){
this.id = id;
}
public boolean add(JobUnit unit) throws Exception{
if(!unit.get().getCustomer().id.equals(id))
throw new Exception(" cannot assign job to this customer");
return jobs.add(unit);
}
public boolean remove(JobUnit unit){
return jobs.remove(unit);
}
public Long getId() {
return id;
}
}
And the Job Class:
public class Job {
Customer customer;
private Long id;
final JobUnit unit;
public Job(Long id,Customer customer) throws Exception{
if(customer==null)
throw new Exception("Customer cannot be null");
this.customer = customer;
unit= new JobUnit(this);
this.customer.add(unit);
}
public void replace(Customer c) throws Exception{
this.customer.remove(unit);
c.add(unit);
this.customer=c;
}
public Customer getCustomer(){
return customer;
}
/**
* #return the id
*/
public Long getId() {
return id;
}
public final class JobUnit{
private final Job j;
private JobUnit(Job j){
this.j = j;
}
public Job get(){
return j;
}
}
}
But one thing I'm curious about is why do you even need to add jobs to a customer object?
If all you want to check is to see which customer has been assigned to which job, simply inspecting a Job will give you that information. Generally I try not to create circular references unless unavoidable.
Also if replacing a customer from a job once its been created is not necessary, simply make the customer field Final in the Job class and remove method to set or replace it.
The restriction for assigning customer for a job should be maintained in database and the database entry should be used as a checking point.
As for adding jobs to customer that were done for someone else, you can either check for customer reference in a job to ensure that the customer to which a job is being added is the same one it holds or even better-simply remove any reference in customer for Job and it will simplify things for you.
If the Customer object owns the relationship then you can possibly do it this way:
Job job = new Job();
job.setStuff(...);
customer.addJob(Job job) {
this.jobs.add(job);
job.setCustomer(this); //set/overwrite the customer for this job
}
//in the job class
public void setCustomer(Customer c) {
if (this.customer==null) {
this.customer = c;
} // for the else{} you could throw a runtime exception
}
...if the ownership is the other way around, just substitute customer for job.
The idea is to have the owner of the relationship maintain consistency. Bi-directional relationships generally imply that the consistency management sits in both entities.
Make a proper setter-function that maintains consistency. For instance, whenever you create a job, you supply the customer in the constructor. The job constructor then adds itself to the customer's list of jobs.
Or whenever you add a job to a customer, the add function has to check that the job's customer is the customer it's being added to.
Or some combination of this and similar things to what suits your needs.
Just implement some sort of collection in the object that has the other objects
For example in customer you could say:
private List<Job> jobs;
then by using getters and setters you can add values jobs to this list.
This is basic OO stuff, I don't think you searched enough on the internet. there is a lot of info available on these subjects.
Btw, you can use all sort of collections (Sets, Lists, Maps)
I know this is late but I think another way to this would be to look at the problem a bit differently. Since customer holds a collection of all jobs assigned by or completed for a customer, you could consider the job class to be a sub class of customer with extra information of having all the jobs completed by the customer. Then you would only have to maintain customer id in the main class and it would be inherited. This design would ensure that each job can be linked to a customer. Also if for a customer you want to find out how many jobs are present that too also would be got.
I am sorry I know this is very late but I have come across a similar problem where I feel the best solution is to follow a inheritance model. Think of job as being jobs done/asisgned by a particular customer. So in that case the Customer would be a super class with the Job(Lets call is customer job) being a sub class since a Job cannot exists without a customer. A customer would also have a list of jobs primarily for ease of data fetching. Intutively this does not make sense since Job and Customer done seem to have any relation, however once you see that Job cannot exist without a customer, it just becomes an extension of customer.
Related
If we have a Class Book and we want to calculate the score of a Book following some rules like "if the number of pages is lower than X then we need to substract Y from the score" and using an Hexagonal Architecture. Should we place this method calculateScore() in a separate Service in case this logic changes in the future using different fields or this reponsibility should be in the Domain itself?
1st approach
package com.xxx.domain;
[...]
public class Book {
[...]
public Double score() {
[...]
}
[...]
}
2nd approach
package com.xxx.application;
[...]
public interface ScoreService {
[...]
void calculateScore(Book book);
[...]
}
Should we place this method calculateScore() in a separate Service in case this logic changes in the future using different fields or this reponsibility should be in the Domain itself?
First the clean architecture is very clear when it comes to the question "Where should business logic be placed?".
Application agnostic business logic in the entities layer.
Application specific business logic in the use case layer.
But I think your question is about something a bit different, it's about anemic or rich domain models. I can't tell you every of my thoughts here, but I have written down most of them in the blog I linked in the sentence before.
The condensed statement of mine is
rich domain models combine data and logic while anemic models separate them.
Let's think about the anemic way...
If you place the logic in a separate service it usually means that you have to expose all properties of the book. You will make them public or at least package scope if the service is in the same package.
Your question also focuses on change. You make the statement that logic changes can be better handled if the logic is put in a separate service. That's true, but it comes at a cost.
It's true that an anemic model let you add logic easier, but it is also true that each logic (each service) must have the same interpretation of the anemic model. I mean each service must know how to modify the data structure properly to keep it consistent and that will be hard to maintain when the number of services grows.
But implementing the service can also be a good intermediate step, because it will give you a hint about cohesion. The cohesion usually shows you where to place a method. E.g.
public class ScoreService {
public BookScore calculateScore(Book book, BookRentals rentals){
int pageCount = book.getPageCount();
Author author = book.getAuthor();
// calculate a new value based on pageCount and the author
// ...
OtherValue ov = book.getSomeOtherValue();
// do something with ov
int rentalCount = rentals.getCountSince(someDate);
// ... and so on
}
}
When you look at the calculateScore above you will recognize that there are a lot of get invocations on Book and less on BookRentals. This is a hint that most of the data that calculateScore needs is placed in the Book. Thus the calculateScore's cohesion is higher to Book and the method might be placed in the Bookclass. E.g.
public class Book {
public BookScore getScore(BookRentals rentals){
int pageCount = this.getPageCount();
Author author = this.getAuthor();
// calculate a new value based on pageCount and the author
// ...
OtherValue ov = this.getSomeOtherValue();
// do something with ov
int rentalCount = rentals.getCountSince(someDate);
// ... and so on
}
}
The difference is obvious:
the number of method parameters decreases. Maybe you apply DDD and Book is an aggregation root and also has access to BookRentals. Then your parameters might decrease to zero.
Since most of the properties that getScore needs are located in the Book class, you might want to lower their visibilily to private. So that uncontrolled access is not allowed.
One question that often arises when developers put the logic in the entities is: "How can an entity access data from a data store?"
My solution is to just pass a repository to the methods that need it. E.g.
public class Book {
public BookScore getScore(BookRentalRepository repo){
// ...
int rentalCount = repo.getRentalCountSince(this, someDate);
}
}
Whatever way you want to go, anemic or rich, keep the logic in a POJO. Also keep in mind that a POJO can be more than a simple data structure.
I hope my answer helps you to make a decision for your specific application.
If the calc of the score depends only on the book state, i would create a method in the book entity to calc it.
Otherwise, if it depends on other domain objects also, i would create a domain service for calculating it.
Regarding to persist the score. I would persist it just if the calc process is very complicated and takes a lot of time. Otherwise, I wouldn't persist it and calc it when need it.
In case you persist jt, you have to consider that you have to recalculate it and persist the new value every time the other values it depends on change too.
I can't find any documentation on the appropriate way to make a many-to-many relationship between objects using Objectify on Google App Engine.
Can anyone explain how to do this? Do I need to create a new "join" class for this? How efficient will it be?
What kinds of queries do you need to support?
The simplest solution is:
#Entity
public class StoredObject {
#Id
private Long id;
private List<Long> relatedIds;
}
then, given a StoredObject, you can call objectify.get(StoredObject.class, storedObject.getRelatedIds()) to fetch all the related ids.
To speed up some queries in my own app I did create a few join classes. The expense comes at write-time (you have to maintain the joins) but then read-time is a single index scan with consecutive results!
This is not the best approach to map many to many relationships in Objectify. The best way is to create an entity that maps the relationship. For example, suppose you have two objects A and B, and they are associated in a certain way. They you could create a class similar to:
Class Link{
Key<?> master;
key<?> slave;
public Link(){
}
public setLink(Entity master, Entity slave){
//initialize
}
}
Then you may create a Link entity to model a relationship. This automatically maps one to one or many to many relationships
I've solved using this approach with Objectify 4.0 :
#Entity
#Index
public class Module {
#Id
private Long id;
private String name;
#Load
private List<Ref<Template>> templates;
public List<Template> getTemplates() {
List<Template> templates = new ArrayList<Template>();
for (Ref<Template> temp : this.templates) {
templates.add(temp.get());
}
return templates;
}
public void setTemplates(List<Template> templatesParm) {
List<Ref<Template>> templates = new ArrayList<Ref<Template>>();
for (Template temp : templatesParm) {
templates.add(Ref.create(temp));
}
this.templates = templates;
}
Let's think about one-many for a moment; if you want an object A to "have many" object B-s, there are only two ways to do it:
The Relational Way: make each B point at the A. When you have the A0 and want all the B-s that relate to it, just query for the B-s which point to the given A0.
The NoSQL / ObjectStore way: make A have a field that holds a list of pointers (Keys) to the B-s. Note that this way also allows the B-s to be in a particular order (despite the GAE/Java docs to the contrary.)
Which one is best depends. The ObjectStore way is limited by the size of an object. The Relational way is subject to a subtle problem in that unless A and all the B-s are in the same Entity Group and you do an Ancestor Query in a Transaction (or maybe even if it isn't in a Transaction) you are guaranteed to get all of the B-s which point to that A. However if the A and B-s span Entity Groups, it is possible (though perhaps unlikely) that you will get a B that does not satisfy the query predicate, or miss a B that does: https://developers.google.com/appengine/articles/transaction_isolation
In the (now standard) High Replication Datastore, the transaction
typically is completely applied within a few hundred milliseconds
after the commit returns. However, even if it is not completely
applied, subsequent reads, writes, and ancestor queries will always
reflect the results of the commit, because these operations apply any
outstanding modifications before executing. However, queries that span
multiple entity groups cannot determine whether there are any
outstanding modifications before executing and may return stale or
partially applied results.
Now for many-many: I read a story once that described going to the toilet in space; there were four combinations: inside/outside a space ship and the two kinds of going to the toilet. For the last combination of being outside the ship (in a space suit) and eliminating solids, the only answer was "there ain't no graceful way" (also the title of the article): http://settlement.arc.nasa.gov/CoEvolutionBook/SPACE.HTML#There Ain't No Graceful Way
... and that is also the answer to many-many relationships in GAE. You can build them using a join class and each side of the join could be implemented with a query or a list of Keys.
I want to model the relationship between two entities, a group and an account with JPA/Hibernate. An account can have several groups, but not vice versa, so we have a OneToMany relationship between account and group.
My working colleague suggested to model the entities Account and Group like
public class Account {
private List<Group> groups = new ArrayList<Group>();
public Account() {}
public void setGroups(List<Group> usergroups) {
this.groups = groups;
}
#OneToMany(mappedBy = "account")
public List<Group> getGroups() {
return groups;
}
}
and
public class Group {
private String name;
private Account account;
public Group() {}
public Group(String name, Account account) {
this.name = name;
addToAccount(account);
}
public void addToAccount(Account account) {
setAccount(account);
List<Group> accountGroups = account.getGroups();
accountGroups.add(this);
}
#ManyToOne
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
}
}
My question is now about the usage of the helper method addToAccount in the constructor of Group. According to my working colleague this method is necessary because we need to update the bidirectional relationship between the two entities from both sides to ensure a consistent memory model of the two entities.
However I believe calling the method addToAccount in the constructor is not a good idea, because
The List of Groups is lazily
fetched, so calling the method
addToAccount needs an open
transaction. So the constructor of
Group can only be called inside an
open transaction. In my opinion this is a very annoying restriction.
The Account object given as argument
to the constructor of Group is
changed by the constructor. In my opinion, this is an
surprising side effect of the Group
constructor and should not happen.
My suggestion was to better use a simple constructor like
public Group(String name, Account account) {
this.name = name;
this.account = account;
}
and deal with the bidirectional relationship manually. But maybe I'm wrong. Is there a common way how one should handle bidirectional relationships when constructing hibernate entities?
In our projects we usually try to avoid bidirectional associations.
One reason is that you have a cycle in your model that may create problems if you want to somehow serialize it, for example let's say you want to serialize an Account and your serialization algorithm is not smart enough you end up with an infinite loop (because Group has a reference back to the Account).
Second reason is that I find it clearer having only one way to navigate the model. What I usually do is to remove the OneToMany association in the Account entity and use a repository call when I need to collect all the Groups for a specific Account (but this probably depends on your use case and personal taste).
Third, if you get rid of the addToAccount method and you use field access you can make your classes immutable that is a good thing.
In my experience you're doing it exactly as it is commonly done. My question would be more about the structure (I expect there is a lot more going on than the sample provided above) as to why you want to manipulate the Account directly from the Group.
I also question whether this is a OneToMany or a ManyToMany situation (usually multiple accounts can belong to a single group and multiple groups can belong to a single account but it is all in the semantics of your particular accounting scheme...) anyway: you're doing it right, and though I question (in this exact case) why you would want to directly manipulate the account (unless it is Lazily loaded) this is entirely fine.
[You may need to add some Cascade rules so that it persists properly depending on your configuration.]
You should note that by mapping to the Account you have effectively added it to the List of the Account. When the database next queries to create that list it will populate the list by finding the references from the Account entity.
In short->
public void Group.setAccounts(Account a)
{
this.account = a;
}
is effectively equivalent to what you are doing above. The database will query and populate the List with something akin to:
//Pseudo SQL
SELECT g.id FROM Group g WHERE g.account_id = :account_id
Thus, aside from the lazy load (something you may or may not want) adding to the groups is unnecessary as the List is defined by the query.
(Don't make it too hard, it look simple. I hope the long explanation gives you an idea of what's happening in the JPA)
I am writing an application that uses the observer pattern. The client class needs to know when an Employee object's state changes. It also needs to know the state of the employee at the current time (before any updates have been made). At the moment i am using a getEmployee() method and then registering an employee observer:
public class MyClass implements EmployeeObserver{
...
Employee employee= subjectClass.getEmployee();
subjectClass.registerEmployeeObserver(this);
...
}
Is there anything wrong with combining these methods so that an Employee object is returned in the same method call that the observer is registered in? :
Employee employee = subjectClass.getAndObserveEmployee(this);
I know this may seem a bit strange, but i only need the getEmployee method when the observer class is initialised and the subjectClass already has quite a large interface that i want to keep to a minimum. So, is this acceptable or is it bad practice to combine two actions into a single method call?
It's cleaner to separate the two.
On a separate note, why does the Employee itself not have an addObserver() method? There could be a perfectly valid reason but that would be my first guess of where to find it if I were searching for it. Either that or there would be some kind of service that manages employees and has the addObserver(int employeeIdToObserver) or something like that (implying that you already have a reference to the employee before you observer it.
Also, one way you could write the pattern is...
public interface EmployeeObserver {
public void stateChanged(State oldState, State newState);
}
...for observers that need to know what the state was before the change.
If sometimes you don't need the employee you have to do
subjectClass.getAndObserveEmployee(this);
which looks strange. or if sometimes you need emploee but not to register:
Employee employee = subjectClass.getAndObserveEmployee(null);
which again is not nice. If, let say you want to change the register part, (i.e. one more arg), you have to change the places where you use the function only for get() also.
I would not do that, except if necessary like in case of
oldVal = ConcurrentMap.replaceValue();
in this case two operations must be combined in one method because in concurrent system between two calls the state can change.
We're a couple of students trying to implement a design to search for customer-information in a database. When the GUI-class is asking for any customer with the surname "Jensen", would a customer-class then create many objects for each customer with that surname, give all those objects to the GUI-class, let the GUI-class e.g change something or add something, and then use some method in the customer-class to update it in the database?
Customer class:
Surname
Email
getSurname()
setSurname()
static List getCustomerFromDb(surname, email):
Customer customer = new Customer()
customer.setSurname(surname from db)
..
..
return listOfCustomers
updateThisCustomerInDb():
//updates all fields in db
Our implementation now is that we send a ResultSet to the GUI-class from a static method in the customer to search for customers.. And if the GUI-class want to change a field like email in the customer, it sends a HasMap with the keys and values to change.
Wouldn't it be bad to create like 300 customer objects and only need one of them?
The reason we ask for help, is that we've heard that it's a bad OO-design to not update, change, find (in the database) customers using objects, but using ResultSets and HasMaps.
Thanks =)
Assuming that a ORM-framework like Hibernate is either overkill or not allowed for your assignment this is what I suggest:
Implement the DAO Design pattern. In a nutshell this means that you declare an Interface with methods for retrieving and altering database data. Their signatures should look something like the example code you supplied and should return Domain objects, that is objects not specific to the implementation of the database access code. A typical Domain Object for customer could look like this:
public class Customer {
private String surname;
private String email;
private long id;
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
Then create an implementation of the interface where all the gritty DB-specific code is placed.
What you were told regarding poor design seems correct to me, you don't want to expose db-specific code in the upper layers of your design. You should use your own, domain specific objects or collections of them.
Good Luck
Your code doesn't have to hold onto every record in a database when it doesn't need it. What would happen if you had 50,000,000 customers in your database?
Utilize your database! If you know exactly what objects you want, write a query to return only those objects within a list. If you know exactly what rows you want to update without first viewing them, then write a query to update only the relevant rows directly in the database without returning the result set at all.
Sorry if this isn't relevant to your question.
You may want to alter the process a little, do your search and return search results that allow the user to select which customer to edit, as Kobi said the customer should have a unique identifier, once you have this you can obtain just the single customer object you are wanting to work with.
Hope that helps.
Chris
<speculation>
I'm a .net developer, but I'm pretty sure that if the ResultSet contains all data it also contains 300 objects (as rows?) - there's no way around this. 300 is considered a tiny number, by the way, but if you return rows you absolutely don't need you may have scaling problems, when you have a million times more records (give or take).
</speculation>
On the long run, returning your own classes and using them between the data-access layer and presentation layer is better practice - it will save you from duplicated code. In fact, the GUI should not contain this code, and it is better if that layers doesn't relay directly on the structure of your tables and columns' names (as this gets messy).
Creating your own classes and using them is common and advisable. It also improved the reliability and maintainability of your code - this may not be of interest in collage, but considered by some to be more important the speed or memory use.
I can see here two options:
There is 300 customers named Jensen and you want to present them to end user
There is 1 customer named Jensen and 299 other customers
In first case it is OK to create 300 objects of customers and modify only one - user searched for a guy named Jensen and there was 300 of them. In second you should create only one object and use it in GUI.
Plus it is also good idea to separate DB code (transforming ResultSets into objects) from GUI. The idea with DAO pattern is justified here.
Hope it helps
EDIT: too early enter pressed