views:

364

answers:

5

Hello

I wonder if anyone can advise me here; I have an application which has classes like this:

Code:

public class Order implements Serializable { 
    private int orderNo; 
    private int customerNo;    
    private date orderDate; 

    public int getOrderNo () { 
        return orderNo; 
    } 

    public int getCustomerNo () { 
        return customerNo; 
    } 

    public date getOrderDate () { 
        return orderDate; 
    } 

    // And so on with set methods. 

} 

public class OrderLine implements Serializable { 
    private int orderNo; 
    private int lineNo;    
    private int qty; 
    private int prodID; 

    // Get and set methods for each of the above. 
    public int getOrderNo () { 
        return orderNo; 
    } 

    public int getLineNo () { 
        return lineNo; 
    } 

    public int getQty () { 
        return qty; 
    } 

    public int prodID () { 
        return prodID; 
    } 
    // And so on with set methods. 
}

This translates directly into relational table:

Order: orderno, customerNo, orderDate OrderLine: orderno, lineNo, qty, prodID

So each class directly translates into a database table with get and set pairs for each attribute.

Now what I want to know is, if in an Java web application, should the classes be as they are above or more like this where the gets return objects:

Code:

public class Order implements Serializable { 
    private int orderNo; 
    private Customer;    
    private date orderDate; 
    private ArrayList<OrderLine>lineItems; 

    public int getOrderNo () { 
        return orderNo; 
    } 

    public Customer getCustomer () { 
        return Customer; 
    } 

    public date getOrderDate () { 
        return orderDate; 
    } 

    public ArrayList<OrderLine> getOrderLines () { 
        return lineItems; 
    } 

    public OrderLine[] getOrderLines () { 
        return lineItems; 
    } 
    // And so on with set methods.     
} 

public class OrderLine implements Serializable { 
    private int orderNo; 
    private int lineNo;    
    private int qty; 
    private Product; 

    // Get and set methods for each of the above. 

    public int getOrderNo () { 
        return orderNo; 
    } 

    public int getLineNo () { 
        return lineNo; 
    } 

    public int getQty () { 
        return qty; 
    } 

    public int getProduct () { 
        return Product; 
    } 
}

Which is the better approach? Or does it really matter which approach is taken as long as the classes processing the data do so correctly and the system operates efficiently?

Thanks

Mr Morgan

+2  A: 

There is absolutely no reason to use the first form - it will be much harder to work with in the Java code, and there will be a lot of bugs resulting from that.

All decent O/R mappers (Hibernate being the most popular one) will translate from the DB schema into proper OO object graphs with no problems.

However, the downside is that having all this done for you can result in very bad performance when you leave everything to the OR mapper and it fetches too much or too little data from the DB, so you have to pay some attention to caching and whether your collections are lazy or eager loading.

Michael Borgwardt
But what if the first form has been used and is currently working correctly without known bugs? Is it better to leave it or to re-engineer it? The current system has a set of database access classes where, e.g. to get order lines, a method is called with the order number as a parameter.
If the current system is large, works well and you're not planning to make huge changes, then it would probably be better to leave it as it is. If it's small and you know you'll have to extend it substantially, I'd take the time to switch to using an OR matter.
Michael Borgwardt
About 25 core tables with a number of dynamically created tables which with varying column types so these wouldn't count. But thr 25 tables, maybe.
I'd classify that as "medium size", so it mainly depends on how much further development is still going to be done.
Michael Borgwardt
As an on-going project it's difficult to say. The current data access layer works well enough and is easily extended without having to alter the class definitions but I'm open minded here, hence the original question.
You could try a hybrid approach: use Hibernate for only for new tables at first to see how you like it. Actually, you could use it for your existing model classes as well and only replace the DB access code with calls to Hibernate, then gradually change the classes into a proper object model.
Michael Borgwardt
+1  A: 

If your business objects are as clean as this, I'd suggest maybe looking at an ORM mapper such as Hibernate or ActiveObjects.

If you'd rather build your own data access layer, I'd suggest making these classes as light-weight as possible. For instance in Order, I would have a CustomerID integer field which would represent the foreign key, instead of having a getCustomer() returning a Customer object in the Order business class.

Fetch methods such as getCustomer() would probably be better placed in a different class such as CustomerDAO etc which contains your data access functionality.

It won't really matter from an efficiency point of view which approach you go with, but it's always good practice to have loosely-coupled objects.

Andrew Corkery
I suppose I have built my own data access layer which works fine. I just wonder about conventions and best practices.
Is this use of lightweight classes an example of loose-coupling or not though?
No, that does not qualify as "loose coupling". It's more like "obfuscated coupling" because the relations are still there, just hidden through int keys. The best practice of loose coupling doesn't really apply to data models at all, though.
Michael Borgwardt
'Fetch methods such as getCustomer() would probably be better placed in a different class such as CustomerDAO etc which contains your data access functionality.' Could the same be said of a method in Order to get the order lines? Or should such a method be placed in the DAO for Order or OrderLines?
I think the getOrderLines() method should also be in a data access class, I just like to have my objects knowing very little about other business objects and closely resembling the Tables that they model. I think it should be up to the data access classes to manage the relationships between those models and the persistance layer. Indeed I'm incorrect using 'loose coupling' to describe this.
Andrew Corkery
This seems to be the appraoch with the current system which lacks a persistence manager because the back end id a relational MySQL database. So the business classes translate more into rows in the database tables. But how could 'the data access classes' 'manage the relationships between those models and the persistance layer' if the data access classes are written as a series of methods for accessing the database?
Are you speaking in terms of exceptions being raised if, for example, a mismatched foreign key is inserted?
No, I just mean that your data access classes would be where you would fetch and populate objects. For example CustomerDAO might have static methods: getCustomerById(int id), getAllCustomers(), saveCustomer(Customer c) and OrderDAO might have: getOrdersByCustomerId(int customerId), getProductsInOrder(int orderId) etc. Regarding exceptions, you could handle these within each method normally (I usually log exceptions like the one above in the the catch block).
Andrew Corkery
That's currently the arrangement and despite some refactoring of classes and code to make it more truly object-oriented, that's most likely how things will remain. Despite incorporating appropriate tags in the business classes and new methods like the order class one to return a collection of order lines, there will still be many fetch methods in the order DAO as well using connection pooling to access the DB; but the gets and sets will remain in the order business class.
+1  A: 

You should look at some Object Relational Mapping (ORM) mapping tool, like Hibernate or TopLink, or perhaps a simpler query mapping tool like iBatis.

I think you'd end up with something more like your second suggestion if you go down the ORM route.

A_M
+1  A: 

The common way to do it is by using an Object-Relational Mapping library (ORM). The common ones are:

All these are open source libraries and implement the JPA (Java Persistence Architecture) standard.

David Rabinowitz
+1  A: 

I would also encourage you to look at an Object-Relational Mapping tool like Hibernate, or a simpler SQL mapping tool like iBatis. (I've had very good experience with iBatis.)

On the question of modelling the master-detail relationship between an Order and its OrderLines, at the Java object level they certainly are part of the same conceptual hierarchy, so I would choose to model them as an Order object that contains a List. That way I could pass complete Orders around my code and never worry about losing parts of them.

If you're using an SQL mapper like iBatis, you'd set up an Order table and an OrderLine table in your database, and give iBatis an XML map that tells it how to assemble your compound Java Order/OrderLine object hierarchy by joining the two SQL tables together. ORMs operate in reverse, generating the SQL tables based on your Java data model.

Jim Ferrans