Making the most of code

J

jstorta

I have a web site that uses JSP and some back end classes to manage
data in a MySQL database. It does okay and has run well for about 3
years. It has, however, grown to the point where I need to redesign
some of it to be more dynamic. I've recently started incorporating
Hibernate and JavaServer Faces to ease the development now and make it
easier for me to make changes later on. Or at least that was my plan.

Each database table maps to a Java class. I will easily have 25-30
tables before I am done. I am okay with 25-30 classes to represent
the data, but my concern is when it comes to the associated classes
needed to manage the data connections and such. I find that I am
cutting and pasting way too much similar code into these separate
classes.

For example.
I have a HibernateDAO class that manages the Hibernate session.

Each class then has its own DAO class that extends the HibernateDAO
class and the code within the extended DAO classes is virtually
identical.

Here is one method from my clientDAO class.
public Client add( Client client) {
try {
begin();
getSession().save(client);
commit();
return get(client.getClientId()); //not every class
will have a clientId member
} catch (HibernateException e) {
rollback();
System.out.println( "Could not add client: " +
client.getClientId() + " : " + e); //message hard coded for client
class
return new Client();
}
}


And then in my ContactDAO class I have this.
public Contact add(Contact contact) {
try {
begin();
getSession().save(contact);
commit();
return get(contact.getId()); //not every class will have
an Id member
} catch (HibernateException e) {
rollback();
System.out.println( "Could not add contact: " +
contact.getId() + " : " + e); //Message hard-coded for contact class
return new Contact();
}
}


Note that the code is virtually identical.

The begin(), getSession(), rollback(), and commit() methods are all
from the HibernateDAO superclass.

I tried using Generics to make the return type and parameter <T>, but
this only gets me so far. I cannot declare a new instance of <T>, or
at least I don't know how to. And the method uses values that are
specific to the class in question. I.E. not every data class will
have a getId() method.

I am not sure if any of that made sense, but the crux of the issue is
I am trying to avoid cutting and pasting code and then having to
remember to update it in 25 different places when I make a change. I
feel like there is a way to do what I want, but I just don't have the
experience to see it.

If anyone can point me toward some documentation that might help set
me straight, I would appreciate it.

Thanks.
 
R

Roedy Green

Note that the code is virtually identical.

The begin(), getSession(), rollback(), and commit() methods are all
from the HibernateDAO superclass.

A technique you might consider is the Stomper.

You write a Java method that takes N parameters and stomps out Java
source code. It can be considerably cleverer than a traditional macro.
Your code can do checks, computation, variable expansions etc.

You might find Quoter helpful to turn the basic code skeletion into a
giant set of Java strings.

You can also write stompers than do regex searches or indexOf searches
to do fancy search-replace-insert-delete on finished code. You embed
magic comments to make it simpler. I use one like this to change the
picture and text in http://mindprod.com/jgloss/index.html
and http://mindprod.com/jgloss/artcom.html
each day.


You periodically rerun your stompers when you find a better way to
expand the code.

http://mindprod.com/applet/quoter.html

use the "to Java String literal" option.
 
M

Mark Space

jstorta said:
Here is one method from my clientDAO class.
public Client add( Client client) {
try {
begin();
getSession().save(client);
commit();
return get(client.getClientId()); //not every class

I'm not using your packages (Hibernate, etc.) so I really can't talk
about best practice, but the first thing that occurs to me is to push
the work of saving onto the object being saved.

So if Client and Contact both have some interface "SessionSavable" with
a save() method which takes a session as a parameter,

public Object add( SessionSavable s ) {
try {
begin();
s.save( getSession() );
commit();
//....

Then in Client

@Override
public void save( Session x ) {
x.save( this );
}

and the same in Contact. You'd have to do the return method the same
way. Have both Client and Contact implement a method which returns
Object, but really returns the specific class/ID that is needed for that
type of object.

This could muck up your Client and Contact classes a little, but maybe
the decrease in boilerplate would be worth it.


Alternately, if session is just a Map or something, you could just save
all your objects as some base class, e.g., Object or something else you
create. You'd still need return method to over ride, so I think Object
may not be the best choice here.
 
A

Abhijat Vatsyayan

jstorta said:
I have a web site that uses JSP and some back end classes to manage
data in a MySQL database. It does okay and has run well for about 3
years. It has, however, grown to the point where I need to redesign
some of it to be more dynamic. I've recently started incorporating
Hibernate and JavaServer Faces to ease the development now and make it
easier for me to make changes later on. Or at least that was my plan.

Each database table maps to a Java class. I will easily have 25-30
tables before I am done. I am okay with 25-30 classes to represent
the data, but my concern is when it comes to the associated classes
needed to manage the data connections and such. I find that I am
cutting and pasting way too much similar code into these separate
classes.

For example.
I have a HibernateDAO class that manages the Hibernate session.

Each class then has its own DAO class that extends the HibernateDAO
class and the code within the extended DAO classes is virtually
identical.

Here is one method from my clientDAO class.
public Client add( Client client) {
try {
begin();
getSession().save(client);
commit();
return get(client.getClientId()); //not every class
will have a clientId member
} catch (HibernateException e) {
rollback();
System.out.println( "Could not add client: " +
client.getClientId() + " : " + e); //message hard coded for client
class
return new Client();
}
}


And then in my ContactDAO class I have this.
public Contact add(Contact contact) {
try {
begin();
getSession().save(contact);
commit();
return get(contact.getId()); //not every class will have
an Id member
} catch (HibernateException e) {
rollback();
System.out.println( "Could not add contact: " +
contact.getId() + " : " + e); //Message hard-coded for contact class
return new Contact();
}
}


Note that the code is virtually identical.

The begin(), getSession(), rollback(), and commit() methods are all
from the HibernateDAO superclass.

I tried using Generics to make the return type and parameter <T>, but
this only gets me so far. I cannot declare a new instance of <T>, or
at least I don't know how to. And the method uses values that are
specific to the class in question. I.E. not every data class will
have a getId() method.

I am not sure if any of that made sense, but the crux of the issue is
I am trying to avoid cutting and pasting code and then having to
remember to update it in 25 different places when I make a change. I
feel like there is a way to do what I want, but I just don't have the
experience to see it.

If anyone can point me toward some documentation that might help set
me straight, I would appreciate it.

Thanks.
You should think along separating your domain representation from
details of persistence technology. Sure, every class that corresponds to
a table needs to be saved but if you have a one-to-one correspondence
between database tables and classes, your (mapped) classes are pure data
with no behaviour (except the ability to persist).

As far are you code is concerned, it should be pretty easy to provide a
common implementation for the two methods you have provided as example.
Let us, for the time, concentrate on the add method and the two classes
Client and Contact (and stick to pre 1.5 syntax) . Both of these classes
should implement an interface "Identifiable" which should be
serializable and contain at least one method - "Long getID()". Move your
add method out of each class and into a class say "IdentifiableDAO"
where you should provide a common implementation of add which will look
something like this (not showing all the details here).

Identifiable add(Identifiable obj2save)
{
.....
Long objID = session.save(obj2save) ;
return get(objID);
}

Looking at your code, I would say using spring's HibernateDAO might also
be a good idea for you.

Note: The idea of moving the hibernate code out of the domain objects is
not really central to your problem but it will help (if implementation
details of persistence are separate from your domain representation) if
you want to later change your persistence mechanism or change the way
you manage transactions etc.

Hope this helps.

Abhijat
 
J

jstorta

Looking at your code, I would say using spring's HibernateDAO might also
be a good idea for you.


I had heard of Spring, but never really looked into it. I did some
reading this morning and I think it is exactly what I am looking for.

Hibernate to wrap around the complexity of database access.
Spring to wrap around the complexity of Hibernate.

One more framework to learn. :)

Thanks.
 
A

Are Nybakk

jstorta said:
I have a web site that uses JSP and some back end classes to manage *snip*
Each database table maps to a Java class. I will easily have 25-30
tables before I am done. I am okay with 25-30 classes to represent
the data, but my concern is when it comes to the associated classes
needed to manage the data connections and such. I find that I am
cutting and pasting way too much similar code into these separate
classes.
*snip*

On a side note; did you consider using Java Persistence API (JPA)?

*snip*
I tried using Generics to make the return type and parameter <T>, but
this only gets me so far. I cannot declare a new instance of <T>, or
at least I don't know how to. And the method uses values that are
specific to the class in question. I.E. not every data class will
have a getId() method.

I don't know Hibernate, but how about this?


public interface DAO<T> {

public T add(T obj);

}

public class DAOTasks {

public static <T> T add1(T obj) {
//...
}

public static <T> T add2(T obj) {
//...
}

}

public class ContactDAO implements DAO<Contact> {

public Contact add(Contact obj) {
DAOTasks.add1(obj);
//Or DAOTasks.add2(obj);
}

}

*snip*

Are
 
R

RedGrittyBrick

Lew said:
JPA frameworks, and the other object-relational mapping (ORM) frameworks
I've seen for Java, use pure value objects to represent entities. This
may seem strange to O-O programmers accustomed to objects that manage
their own behaviors, but it's valid. Persistence actions use entity
objects, but their concerns are not those of an entity. An entity just
is, in its own mind, and it takes its values as gifts. Any behaviors it
does have will not relate to persistence, but to its own concerns,
trusting persistence matters to the layer that handles them.

"Rabbit's clever," said Pooh thoughtfully.
"Yes,"said Piglet, "Rabbit's clever."
"And he has Brain."
"Yes," said Piglet, "Rabbit has Brain."
There was a long silence.
"I suppose," said Pooh, "that that's why he never understands anything."

;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top