I seem to find all documentation regarding OOP too basic or too advanced. I'm trying to solve a specific problem and I can't get a nice solution without having to use Singletons or global instances or the such.
I'm trying to create a DB based application: I have a DB with Boxes that are stored in some Location. So I created to tables: Boxes and Locations
BOXES
| id | Name | Location |
------------------------
| 1 | AA | 1 |
| 2 | AB | 2 |
LOCATIONS
| id | Name |
---------------------
| 1 | Garage |
| 2 | Living Room |
When trying to bring this to an Java application, I want to have a Box class that I can instantiate for every box and locations that I have in DB and put them in a list. My question is: how do I design Box and Location Classes?
The immediate approach would be:
class Box {
int id;
String name;
Location location;
}
Class Location {
int id;
String name;
}
But then, how can I operate Locations properly? I still want to manage them from my application and have a tool that would return Location objects given an id. Something like:
Location loc = new Locations.getById(1);
And it would query an something (like n enum) that would return the appropriate, filled, object.
Can anyone point me to resources that would explain this kind of services and solutions?
Even though your question title indicates OO design, from reading your question I get a sense that you're more interested in the general way to go about handling persistent objects in your application.
ReplyDeleteJust to be clear...this isn't an OO design answer, even though OO concepts will be a part of your solution.
Here are some of the ways you can accomplish your goals:
(This is an ANTI-EXAMPLE...would not recommend this for any other reason than trying to really understand why you should NOT be doing it...) Write some kind of god object that builds SQL strings and runs them using JDBC. Yuck...
Use JDO or JPA. These are frameworks where you basically don't write SQL at all. Instead you declare objects which represent data you want to store. There are then classes/services available which perform CRUD (Create, Retrieve, Update, Delete) operations on your objects and also provide mechanisms for performing transactions.
Use an ORM (Object Relational Mapping) framework which requires you to map your SQL tables to your Java Objects. Then, you can write paramaterized SQL queries in a localized place. For example, this allows you to make objects like BoxService.get().getObjectByName(name).location; The most popular option for this seems to be hibernate but a good alternative is mybatis. Using ORMs is personally the route I would chose, but for me, it is just a preference. I wouldn't be able to give a detailed argument for why an ORM would be better than JDO or JPA.
That should be enough info to get you started. If you're looking to take a real do-it-yourself approach then see one of the other answers. My answer is specifically an overview of what developers commonly do.
It depends on how you interact with your persistence layer, etc.
ReplyDeleteLike one of the comments hinted, one possibility is to have a List on the Location class, so you can easily "query" what boxes are in a specific location.
As to the instantiation part of the problem, perhaps you could take a look at:
http://en.wikipedia.org/wiki/Builder_pattern and http://en.wikipedia.org/wiki/Factory_method_pattern
I think you don't want to have a call like:
new Location().getById(1);
but rather something like:
Location.getById(1);
and this factory method can instantiate a new Location from the database data and return it. It doesn't have to maintain state, so you won't end up in Singleton Hell.
Hope it helps.
P.S.: If you aren't coding the interaction with the data layer by hand, meaning, by using JDBC directly, then your ORM (Object Relational Mapping) of choice might take care of this problem for you.
You could use Maps to "map" the ids to objects:
ReplyDeletepublic static void main( String[] args )
{
Map< Integer, Box > boxes = new HashMap< Integer, Box >();
boxes.put( 1, new Box( "AA", 1 ) );
boxes.put( 2, new Box( "AB", 2 ) );
Map< Integer, Location > locations = new HashMap< Integer, Location >();
locations.put( 1, new Location( "Garage" ) );
locations.put( 2, new Location( "Living Room" ) );
// example
String s = locations.get( boxes.get( 2 ).location ).name;
System.out.println(s);
}
class Box
{
String name;
int location;
public Box( String name, int location )
{
this.name = name;
this.location = location;
}
}
class Location
{
String name;
public Location( String name )
{
this.name = name;
}
}