• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

Is it a good design model (struts + hibernate)?

 
Ranch Hand
Posts: 99
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
After reading some books i developed my web application (tomcat) using the following design:

I have mapped my table with hibernate then create DAO classes for accessing to them. When i run an action it calls DAO class that use Hibernate.
Do not look at Exception Handling that is a question i find very hard and i' have not understood well..
That i need to understand is my application is on the right way or if i made big mistake in design.

Tnk you very much for assistance
Marco

This is a bare-bone classes of my project (only model & action class):

ACTION CLASS
public class AddAttributeAction extends Action {


public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response) {

AddAttributeForm addAttributeForm = (AddAttributeForm) form;
AttributeDAO attributeDAO = new AttributeDAO();
if(attributeDAO.addAttribute(addAttributeForm))
return (mapping.findForward("success"));
else
return (mapping.findForward("failure"));
}

}

DAO CLASS
public class AttributeDAO {

public AttributeDAO() {

}

public Session getSession( ) throws PersistenceException {
Session session = null;
try {
session = Persistence.getSession( );
} catch (HibernateException e) {
//log.error("Exception accessing persistence session");
throw new PersistenceException(
"Exception accessing persistence session", e);
}
return session;
}
public boolean addAttribute(AddAttributeForm addAttributeForm) {

boolean save = false;

//setto l' oggetto attributo
Attribute theAttribute = new Attribute();
theAttribute.setName(addAttributeForm.getName());
theAttribute.setType(Short.valueOf(addAttributeForm.getType()));
theAttribute.setColumn(addAttributeForm.getColumn());
theAttribute.setObjectName(addAttributeForm.getMetaobject());

Transaction tx = null;

try {

tx =getSession().beginTransaction();
Query q = getSession().createQuery("from MetaObject m where m.name = :name");
q.setString("name", addAttributeForm.getMetaobject());
List result = q.list();
MetaObject theMetaObject = null;
for (int i = 0; i < result.size(); i++) {
theMetaObject = (MetaObject) result.get(i);
}

//se esiste metaobject aggiungo l' attributo al suo set.
if (theMetaObject != null){
theAttribute.setMetaObject(theMetaObject);
theMetaObject.getAttributes().add(theAttribute);
getSession().save(theMetaObject);
save = true;
}
tx.commit();

}
catch (HibernateException e) {
save = false;
System.out.println("Errore di database: forse hai inserito un nome gia' esistente");
//e.printStackTrace();
if (tx != null) Persistence.rollback(tx);
}
return save;

}
public List getAttributes() {
List result = null;
Transaction tx = null;

try {

tx =getSession().beginTransaction();
Query q = getSession().createQuery("from Attribute");
result = q.list();
tx.commit();
}
catch (HibernateException e) {
System.out.println("Error!!!");
e.printStackTrace();
if (tx != null) Persistence.rollback(tx);
}
return result;
}
}

POJO CLASSES

public class Attribute implements Serializable {

/** identifier field */
private Long id;

/** persistent field */
private String name;

/** persistent field */
private String objectName;

/** persistent field */
private short type;

/** persistent field */
private String column;

/** persistent field */
private MetaObject metaObject;

private Fuzzyattribute fuzzyattribute;

+ getter setter methods

public class MetaObject implements Serializable {

private Long id;

/** identifier field */
private String name;

/** persistent field */
private String from;

/** nullable persistent field */
private String where;

/** persistent field */
private Set attributes = new HashSet();

+ getter setter methods

HIBERNATE MAPPINGS

<hibernate-mapping>

<class name="com.full.hibernate.model.Attribute"
table="ATTRIBUTES">

<!-- Common id property. -->
<id name="id"
type="long"
column="ATTRIBUTE_ID"
unsaved-value="null">
<generator class="native" />
</id>

<property
name="name"
type="java.lang.String"
length="50"
not-null="true" >
<column name="NAME" unique-key="uk_object_name"/>
</property>

<property
name="objectName"
type="java.lang.String"
length="50"
not-null="true" >
<column name="OBJECT" unique-key="uk_object_name"/>
</property>

<property
name="type"
type="short"
column="TYPE"
not-null="true"
length="6" />

<property
name="column"
type="java.lang.String"
column="COLUMN_"
not-null="true"
length="50" />

<!-- Associations -->
<!-- derived association(s) for compound key -->
<!-- bi-directional many-to-one association to Object -->

<many-to-one name="metaObject"
class="com.full.hibernate.model.MetaObject">
<!--update="false"-->
<!--insert="false">-->
<column name="OBJECT_REF" />
</many-to-one>

<!--associazione uno a uno presa da manuale Hibernate in Action, con creazione di colonna apposita-->
<many-to-one name="fuzzyattribute"
class="com.full.hibernate.model.Fuzzyattribute"
column="FUZZYATTRIBUTE_REF"
cascade="all"
unique ="true"/>
</class>

<class
name="com.full.hibernate.model.MetaObject"
table="OBJECTS"
>

<!-- Common id property. -->
<id name="id"
type="long"
column="METAOBJECT_ID"
unsaved-value="null"
>
<generator class="native"/>
</id>

<property
name="name"
type="java.lang.String"
column="NAME"
not-null="true"
unique="true"
/>

<property
name="from"
type="java.lang.String"
column="FROMCLAUSOLE"
not-null="true"
length="50"

/>

<property
name="where"
type="java.lang.String"
column="WHERECLAUSOLE"
length="50"

/>

<!-- Associations -->

<!-- bi-directional one-to-many association to Attribute -->
<set
name="attributes"
lazy="true"
inverse="true"
cascade="all"
>
<key>
<column name="OBJECT_REF" />
</key>
<one-to-many
class="com.full.hibernate.model.Attribute"
/>
</set>

</class>
 
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You shouldn't pass the ActionForm to the Model, you should only pass primitives, 'Standard' classes or a Value Object which contains all data accessed via getters and setters. Personally I add another layer of abstraction and create service classes which usually contain static methods that access the DAO.

So in summary

Struts Action -> passes VO -> Service -> passes VO -> DAO

I use the service in case I need to map across tables. I don't like DAO classes talking to other DAO so I use a service which talks to whatever DAO it wants to.

Hope that helps.
 
Sheriff
Posts: 6450
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Piggybacking on what Kerry said, which is very good advice... In general you will not want your Actions to interact directly with the DAOs. This is a pretty good sign that you are coding business logic into your Actions, which you certainly want to avoid. As Kerry mentioned, you should be using Service classes. As a rule of thumb, you can plan on one service method for each use case, with those methods divided amongst a set of service classes that makes sense for your application.

So if you have use cases for "add an attribute", "remove an attribute", "sort attributes", "register a new user", "logoff user", and "edit user information" then you might break things up as follows:

AttributeServices
-----------------
+addAttribute
+removeAttribute
+sortAttributes

AttributeDAO
------------
+createAttribute
+deleteAttribute

UserServices
------------
+editUserInfo
+logoffUser
+registerNewUser

UserDAO
-------
+createUser
+updateUser

The DAOs in this case are strictly handling CRUD and find functions for persistent business objects and not business logic themselves, some of which is required at least to some extent with any use case (for example, "you can't add an attribute if the same one already exists" requires business logic). You'll also notice that not all service methods deal with persisten business objects, such as "sort attributes" which only sorts a collection for display.

When you're doing your design, if you start thinking about each use case as a service method and DAOs as relatively dumb objects use only for handling persistence functions on specific objects, things should fall into place pretty easy.
 
Marco Vanoli
Ranch Hand
Posts: 99
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yes it helps, thanks,
but why necerrary value objects, the form bean isn' t similar to it? (Phereps the problem is that all its properties are Strings?)
--
However instead on create a value object or another class (too much layer for me, i try keep simple thing ) Cannot i istantiate the POJO class (hibernate mapped to a table DB) in the action and pass it to DAO?
Or if this anti-pattern maybe the best chooice is to pass only parameters needed for my operations, isn't it ?

thnks again,
bye
 
Kerry Wilson
Ranch Hand
Posts: 254
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
If a Value Object contains several field 5+ I will usually assign it to the form. Then, I access in the JSP with ${vo.id} that way I can retrieve in Action with form.getValueObject().
 
Marco Vanoli
Ranch Hand
Posts: 99
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Kerry Wilson:
Personally I add another layer of abstraction and create service classes which usually contain static methods that access the DAO.



About this topic where can i fond more info about creating this services classes? Can sombody explain to me why use static method to access dao and not normal ones?
tnk
 
Ranch Hand
Posts: 354
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hibernate is not an apache project and it has no support for stored procedure. i highly recommend using iBatis (http://ibatis.apache.org/) instead.
 
Marco Vanoli
Ranch Hand
Posts: 99
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
My project is in deep develop so i cannot change hibernate.
I' d like to know only the Kelly Wilson phrase that say to use static service for accessing to dao.
I understand this:
I will have an action class that call class (static or normal?) wich implements methods (static or normal) that are the service that i need.
At the end service classe use fine grain DAO to simple acces to database.

Is it al right? .. An my bigges dubt is about servlet' s threads.
I have to synchronize service methods or not?

tnk
 
alan do
Ranch Hand
Posts: 354
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
for the struts part, there's no need to synchronize the ActionServlet.service(). eventhough the Action classes are static, the objects passed into the .excute() methods are not. the key then is to NOT place any values that can be changed (localized variables/objects) OUTSIDE of the .execute() method.

for the rest of the app, if you are using static methods, the same rules follow. don't use static methods to modify global values. your users will end up overwrite and grabbing each other's values.
 
reply
    Bookmark Topic Watch Topic
  • New Topic