Hibernate Case Study

batterycopperInternet και Εφαρμογές Web

12 Νοε 2013 (πριν από 3 χρόνια και 1 μήνα)

65 εμφανίσεις

Enterprise Applications Development

& Integration


Andrew Stratton

Hibernate Case Study

Hibernate
for Enterprise Java


Only a small part of a solution...


Often paired with Spring (framework) in Java


Example focuses on ASP based presentation, which could
alternately be:


Application (i.e. WinForms)


XML/SOAP (i.e. Web Service)


WAP/WML (Mobile service)


Tier overview:

JSP

Browser

or App

Presentation

Business

logic

Database

connection

Database

User

Java

Hibernate

Case Study : Kitchen Worktop
offcuts


A large DIY retailer wishes to sell
offcuts

of kitchen worktops.
Kitchen worktops typically come in three metre lengths. Most
stores offer an in house cutting service, which can leave
offcuts

that the customer does not need or want.


The justification for the system is:


To reduce wasted warehouse space


To (potentially) allow reductions in costs for customer needing ‘just a
couple more feet’ of worktop


For green credentials, i.e. to recycle/reduce waste


To increase income for the (charged for) cutting service


In order to accomplish this, an enterprise system is to be
developed for use in house and (later) available externally as a
web service


Methodologies and Technologies


An Agile like approach is to be used, with sprints and
incremental functionality


Test Driven Development is to be used, particularly for Web
Services


JUnit is to be used for unit testing


Hibernate is to be used for ORM mapping



Case Study : Phase 1 Detail


The first phase is to provide the following solution:


A JSP based web site for use in house, that display details of
all
offcuts

available


These details to include:


Name: This is the short identifier for the type of worktop, e.g.
‘Shiny Light Grey Marble’.


Description : this is a free form area that records any extra
details.


Length : in metric and imperial, typically up to 3m, down to
0.6m


Depth and Height : typically 60cm deep (default) and 2.5cm high


Contact details : free form, of the store and preferably person or
role to speak with


Case Study : Phase 1, Sprint 1


The focus of this sprint is the presentation layer, supported
by the minimum required business logic/data objects



Presentation tier


Following a ‘front end first’ approach


N.B. We are first concentrating on the presentation tier and
implementing whatever we need for the
JSP
to be complete


Create
jsp

and html pages to allow you to:

1.
enter a name for a worktop in a form

2.
submit the form contents to a
createWorktop.jsp
page

o
e.g. you could call the page with
http://
localhost:8080/Worktops/createWorktop.jsp?name=Shiny%20Ma
rble

o
An example page is:

o
<html>

o
<body>

o
Name entered is <%=
request.getParameter
("name")%>

o
</body>

o
</html>

3.
Next add fields for Description, Length, Height, Depth

4.
check the form submission and display of parameters

Business Logic 1


Next we add some business logic

1.
Add a WorktopManager class, e.g.


package com.worktops;


public

class

WorktopManager {



public

void

createWorktop(String name, String description,


String length, String height, String depth)


{

System.
out
.println(
"Request to create Worktop with"

+ "
\
nName="

+ name

+
"
\
ndescription="

+ description

+
"
\
nlength="

+ length +
"
mm
"

+
"
\
nheight="

+ height +
"
mm
"

+
"
\
ndepth="

+ depth +
"
mm
"
);


}

}

Business Logic 2


Integrate this with the createWorktop.jsp, e.g.

<jsp:useBean id="worktopManager" class="com.worktops.WorktopManager"
/>

<html>

<body>

Not much to say...

<% worktopManager.createWorktop(




request.getParameter("name"),




request.getParameter("description"),




request.getParameter("length"),




request.getParameter("height"),




request.getParameter("depth")



);



%>

</body>

</html>

Stop check


What have we gained?


+ Separation of presentation from (business) logic / rules


+ Business focused functionality (not yet implemented!)


-

spaghetti?


-

code dependencies


-

run time incompatibilities (i.e. loss of compile time checking)

Business Logic Implementation 1


We need to separate out the Worktop POJO (Plain Old Java Object) from
the manager
-

1.
Create Worktop class

package com.worktops;

import java.io.Serializable;


public class Worktop

{

private String
name
;

}

o
In the package explorer
-

right click name
-

Source
-
> Generate
getters and setters...OK

2.
Add the other properties:

o
description, length, height, depth

3.
Generate getters and setters (use Ctrl
-
right click to select multiple
properties)


Now we have a JavaBean...

Business Logic Implementation 2


Now we update the WorktopManager.createWorktop method, similar to:





And the jsp:







Run it again and check the output...

public

void

createWorktop(Worktop worktop)


{



System.
out
.println(
"Request to create Worktop with"

+





"
\
nName="

+ worktop.getName()

.....

<%@page import="com.worktops.Worktop"%>

...

<% Worktop worktop = new Worktop();


worktop.setName(request.getParameter("name"));

... also set the other properties


worktopManager.createWorktop(worktop);



%>

Stop Check


What have we gained?


+ Separation of data object from (business) logic / rules


+ Data focused class/objects


-

more spaghetti?


-

code dependencies


-

Java beans do not impose compile time constructor checking

Install
Hibernate


at last


Download


Hibernate
-
3_2min.zip from blackboard


hsqldb.jar from blackboard (simple database


or use access)


Unzip hibernate to directory


e.g.
F:
\
Hibernate3.2


Copy hsqldb.jar into directory


e.g. F:
\
hsqldb


Create a new project ‘Worktops’ in Eclipse


Import all the jars in
F:
\
Hibernate3.2
\
lib to WEB
-
INF/lib


import hsqldb.jar as well (or use access)


import
F:
\
Hibernate3.2
\
hibernate3.jar as well


under build path choose add jar and pick all the lib jars

Worktop class


Modify the Worktop class:

...

import java.io.Serializable;


public class Worktop
implements Serializable

{

private Long
id
; // and add getter/setter

...



Note: Serializable makes the class able to be sent through a stream, e.g.
file, http, ftp, etc., without using RMI. Hibernate uses it for storing
‘persistent’ copies of objects.

Hibernate configuration file


This tells hibernate where to look for mapping files
-

this is a one off
creation of file ‘hibernate.cfg.xml’ in the WEB
-
INF/src directory:


<?xml version='1.0' encoding='utf
-
8'?>


<!DOCTYPE hibernate
-
configuration PUBLIC



"
-
//Hibernate/Hibernate Configuration DTD 3.0//EN"



"http://hibernate.sourceforge.net/hibernate
-
configuration
-
3.0.dtd">


<hibernate
-
configuration>



<session
-
factory>



<property
name="hibernate.connection.driver_class">org.hsqldb.jdbcDriver</property>



<property name="hibernate.connection.url">jdbc:hsqldb:data/test</property>



<property name="hibernate.connection.username">sa</property>



<property name="hibernate.connection.password"></property>



<property name="dialect">org.hibernate.dialect.HSQLDialect</property>



<property name="show_sql">true</property>



<property name="transaction.factory_class">



org.hibernate.transaction.JDBCTransactionFactory



</property>



<property name="hibernate.cache.provider_class">



org.hibernate.cache.HashtableCacheProvider



</property>



<property name="hibernate.hbm2ddl.auto">update</property>



<mapping resource="/com/worktops/worktop.hbm.xml"/>



</session
-
factory>


</hibernate
-
configuration>

Adding a mapping file


Now we need a worktop.hbm.xml mapping file (in WEB
-
INF/src/com/worktops directory):


<?xml version="1.0"?>


<!DOCTYPE hibernate
-
mapping PUBLIC



"
-
//Hibernate/Hibernate Mapping DTD 3.0//EN"



"http://hibernate.sourceforge.net/hibernate
-
mapping
-
3.0.dtd">



<hibernate
-
mapping>

o
<class name="com.worktops.Worktop" table="worktops">

o
<id name="id" column="id" type="long">

o
<generator class="increment"/>

o
</id>

o
<property name="name" type="string"/>

o
<property name="description" type="string"/>

o
<property name="length" type="string"/>

o
<property name="height" type="string"/>

o
<property name="depth" type="string"/>

o
</class>


</hibernate
-
mapping>

Logger configuration


While we’re at it, create the logger configuration file in
log4j.properties in the WEB
-
INF/src directory:


log4j.rootCategory=
INFO,

A1


log4j.appender.A1=
org.apache.log4j.ConsoleAppender


log4j.appender.A1.layout=
org.apache.log4j.PatternLayout


log4j.appender.A1.layout.ConversionPattern=
%
-
5p

-



Now update the jsp...

Trying...<br>

<% boolean success = false;


try

{



Worktop worktop = new Worktop();



...



success = true;


} catch (Exception e)


{ e.printStackTrace(); }


if (success) {

%>

It worked!!!

<%

} else {%>

Some problems....

<% } %>


Updating Business Logic


The hibernate code needs to be added.


Amend the
WorktopManager
:











Now run it
-

and look in the console in eclipse for logging
information:


Hibernate: select max(id) from worktops


Hibernate: insert into worktops (name, description, length, height, depth, id)
values (?, ?, ?, ?, ?, ?)

...

import

org.hibernate.*;

import

org.hibernate.cfg.Configuration;

...


public

void

createWorktop(Worktop worktop)


{



SessionFactory sessionFactory


=
new

Configuration().configure().buildSessionFactory();



Session session = sessionFactory.openSession();




session.save(worktop);




session.flush();



session.close();






System.
out
.println(
"Created Worktop with"

+

...


Checking the database contents


Now amend createWorktop.jsp:








and WorktopManager:

It worked :
-

<br><br>

<%


java.util.List

worktops = worktopManager.listWorktops();


for (int i = 0; i<worktops.size(); i++) {



Worktop theWorktop = (Worktop) worktops.get(i);

%>

Worktop <%= theWorktop.getName() %>,

Description: <%= theWorktop.getDescription() %>

<br>

<%


}


} else {%>


private

List listWorktops()


{



List result =
null
;



SessionFactory sessionFactory


=
new

Configuration().configure().buildSessionFactory();



Session session = sessionFactory.openSession();




result = session.createQuery(
"from Worktop"
).list();




session.flush();



session.close();


return

result;


}

Tutorial exercises


During the tutorial, follow the above example first, then:

1.

Add (if you haven’t already) a form to enter new worktop details. N.B.
The database is emptied EVERY time tomcat restarts (change to access
if you wish to keep data).

2.

Add a separate page (e.g. listWorktops.jsp) to display a list of
worktops names only.

3.

Add the ability to read a worktop
-

so when a user clicks on an entry
in the list, the detail is shown.


Hint
-

use
(Worktop) session.get(Worktop.
class
, id);

4.

Add a form to update a worktop’s details by reading into a form, then
updating the details.


hint
-

use
session.merge(worktop)

5.

Add the ability to delete a worktop entry
-

preferably with
confirmation (use javascript); try
session.delete(worktop);

Where’s the benefit?


Consider:


How much Sql did you need to write?


Where do we need to change if (say) we only ‘mark’
worktops for deletion? (i.e. have a deleted flag)


What if we change the html?


What if we change the database contents?


What if we change database implementation (e.g. to
Access)?