JSP Interface
A few simple conventions are used in the development of the JSP files used by this application. Identifiers are passed using the values authorID and postID. All of these files start with a header containing a bit of Java logic, and the rest of the page is concerned with the HTML formatting of the displayed results.
|
You may notice that the JSP as displayed in the screenshots looks quite a bit nicer than the raw JSP shown. This is accomplished using a template technology called SiteMesh (http://www.opensymphony.com/sitemesh/). For more information on how SiteMesh works, look for my articles on www.cascadetg.com. SiteMesh has no effect on how these pages work; in this application, it merely serves to provide for nicer formatting and headers. |
List Posts
Our first JSP lists the currently available posts. When the page is first visited, there are no posts. As shown in Figure 2.4, the only real user action at this point is to add a post (which, in turn, requires an author).

After a few authors and posts have been added, the page shows additional functionality for editing and deleting posts, as can be seen in Figure 2.5.

Reviewing the code for this JSP, as shown in Listing 2.9, provides an introduction to Hibernate object retrieval using the Criteria API. A session is retrieved from our AppSession factory, a transaction is started, and a query in the form of a Criteria object is executed. The post java.util.Iterator holds the returned Post objects. By setting the sole criteria to the Post.class, the application indicates that it wants all of the Post objects.
|
The Criteria API is one of the two mechanisms for querying objects using Hibernate. The other is Hibernate Query Language, or HQL. Both are described in more detail in Chapter 8. Briefly, the Criteria API allows you to obtain records from the database using Java objects as templates, whereas HQL is a more object-oriented version of SQL. As described in Chapter 8, both query systems have pros and cons.
A more robust application would limit the results returned to a set of perhaps 25 or 50 Post objects at a time, and would also add previous/next functionality. This could easily be done using the Criteria.setFirst Result() and Criteria.setMaxResults() methods, perhaps in conjunction with an offset parameter. |
For more information on the Criteria API, see Chapter 8.
Listing 2.9. Listing Posts Source
<%@ page contentType="text/html; charset=utf-8" language="java"
import="com.cascadetg.ch02.*,net.sf.hibernate.*" %><%
String error = "";
Session hibernateSession = null;
Transaction myTransaction = null;
java.util.Iterator posts = null;
try
{
hibernateSession = AppSession.getSession();
myTransaction = hibernateSession.beginTransaction();
Criteria query =
hibernateSession.createCriteria(Post.class);
posts = query.list().iterator();
myTransaction.commit();
hibernateSession.close();
} catch (Exception e) {
error = e.getMessage(); e.printStackTrace();
try{ myTransaction.rollback(); }
catch (Exception e2) {;}
}
finally
{
try{hibernateSession.close();}
catch (Exception e) {;}
}
%>
<HTML>
<HEAD>
<TITLE>List Posts</TITLE>
</HEAD>
<BODY>
<%= error %>
<% if(posts == null) { %>
<p>No posts available.</p>
<% } else { %>
<table width="100%" border="0">
<tr>
<td><strong>Author</strong></td>
<td><strong>Post</strong></td>
<td><strong>Date</strong></td>
<td><strong>Summary</strong></td>
<td> </td>
<td> </td>
</tr>
<% while(posts.hasNext()) {
Post myPost = (Post)posts.next();
%>
<tr>
<td><%
if(myPost.getAuthor() != null)
{
%><a href="edit_author.jsp?authorid=<%=
myPost.getAuthor().getId()%>"><%=
myPost.getAuthor().getFirstName()%> <%=
myPost.getAuthor().getLastName() %></a><%
}
%> </td>
<td><a href="view_post.jsp?postid=<%=
myPost.getId()%>"><%=myPost.getTitle()%></a> </td>
<td><%=myPost.getDate().toString()%></td>
<td><%=myPost.getSummary()%> </td>
<td>
<a href="edit_post.jsp?postid=<%=
myPost.getId()%>">Edit</a></td>
<td>
<a href="delete_post.jsp?postid=<%=
myPost.getId()%>">Delete</a></td>
</tr>
<% }
}
%>
</table>
<hr />
<p align="right"><a href="create_post.jsp">add Post </a> </p>
</BODY>
Create Author
Before the user can add a post, it is necessary to add an author. Figure 2.6 shows the simple form a user fills out to add an author.

As shown in Listing 2.10, the page simply displays the form unless a user clicks the Submit button. If the page detects the Submit button, the application uses a Hibernate Session to save the object. Note that the Author object is simply created with a new operation, the various properties are set from the request, and the object is passed to the Session.save() method. Very straightforward.
Listing 2.10. Creating Author Source
<%@ page contentType="text/html; charset=utf-8" language="java"
import="com.cascadetg.ch02.*,net.sf.hibernate.*" %><%
String error = "";
Session hibernateSession = null;
Transaction myTransaction = null;
java.util.Iterator authors = null;
if(request.getParameter("Submit") != null)
{
try
{
hibernateSession = AppSession.getSession();
myTransaction = hibernateSession.beginTransaction();
Author myAuthor = new Author();
myAuthor.setFirstName(request.getParameter("first"));
myAuthor.setLastName(request.getParameter("last"));
myAuthor.setEmail(request.getParameter("email"));
hibernateSession.save(myAuthor);
myTransaction.commit();
response.sendRedirect("list_author.jsp");
return;
} catch (Exception e) {
error = e.getMessage(); e.printStackTrace();
try{ myTransaction.rollback(); }
catch (Exception e2) {;}
}
finally
{
try{hibernateSession.close();}
catch (Exception e) {;}
}
}
%>
<HTML>
<HEAD>
<TITLE>Create Author</TITLE>
<meta name="no_print" content="true" />
</HEAD>
<BODY>
<form name="create_author"
method="post" action="create_author.jsp">
<p><%=error%></p>
<table width="50%" border="0">
<tr>
<td>First Name </td>
<td><input name="first" type="text" id="first"></td>
</tr>
<tr>
<td>Last Name </td>
<td><input name="last" type="text" id="last"></td>
</tr>
<tr>
<td>Email</td>
<td><input name="email" type="text" id="email"></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" name="Submit" value="Submit"></td>
</tr>
</table>
</form>
</BODY>
List Authors
After an author is created, the user is returned to a list of authors. Figure 2.7 shows the author list after a few authors have been created.

As can be seen from Listing 2.11, this application uses the Criteria API to retrieve results. The most notable difference is that the results are ordered by last name and first name.
Listing 2.11. Listing Authors Source
<%@ page contentType="text/html; charset=utf-8" language="java"
import="com.cascadetg.ch02.*,net.sf.hibernate.*" %><%
String error = "";
Session hibernateSession = null;
Transaction myTransaction = null;
java.util.Iterator authors = null;
try
{
hibernateSession = AppSession.getSession();
myTransaction = hibernateSession.beginTransaction();
Criteria query =
hibernateSession.createCriteria(Author.class);
query.addOrder(
net.sf.hibernate.expression.Order.asc("lastName"));
query.addOrder(
net.sf.hibernate.expression.Order.asc("firstName"));
authors = query.list().iterator();
myTransaction.commit();
hibernateSession.close();
}
catch (Exception e) {
error = e.getMessage(); e.printStackTrace();
try{ myTransaction.rollback(); }
catch (Exception e2) {;}
}
finally
{
try{hibernateSession.close();}
catch (Exception e2) {;}
}
%><HTML>
<HEAD>
<TITLE>List Authors</TITLE>
</HEAD>
<BODY><%=error%><% if(authors == null) { %>
No authors defined.
<% } else { %>
<table width="100%" border="0">
<tr>
<td><strong>Name</strong></td>
<td><strong>Email</strong></td>
<td> </td>
<td> </td>
</tr>
<% while (authors.hasNext()) {
Author myAuthor = (Author)authors.next(); %>
<tr>
<td><a href="edit_author.jsp?authorid=<%=
myAuthor.getId()%>"><%=
myAuthor.getLastName()%>, <%=
myAuthor.getFirstName()%></a></td>
<td><a href="mailto:<%=
myAuthor.getEmail()%>"><%=myAuthor.getEmail()%>
</a></td>
<td><a href="edit_author.jsp?authorid=<%=
myAuthor.getId()%>">Edit</a></td>
<td><a href="delete_author.jsp?authorid=<%=
myAuthor.getId()%>">Delete</a></td>
</tr>
<% } %>
</table>
<% } %>
<hr />
<p align="right"><a href="create_author.jsp">add Author </a></p>
</BODY>
Edit Author
Everybody makes mistakes, and so it's important to provide a mechanism for fixing mistakes. Figure 2.8 shows the form that enables a user to correct author information.

As can be seen from Listing 2.12, updating an Author object is similar to creating one. The biggest changes are the use of the Session.update() method instead of Session.save() and the use of the authorID to identify the record to update.
Listing 2.12. Updating an Author Source
<%@ page contentType="text/html; charset=utf-8" language="java"
import="com.cascadetg.ch02.*,net.sf.hibernate.*" %><%
String error = "";
Session hibernateSession = null;
Transaction myTransaction = null;
Author myAuthor = null;
if(request.getParameter("Submit") != null)
{
boolean done=false;
try
{
hibernateSession = AppSession.getSession();
myTransaction =
hibernateSession.beginTransaction();
myAuthor = new Author();
myAuthor.setId(request.getParameter("authorID"));
myAuthor.setFirstName(request.getParameter("first"));
myAuthor.setLastName(request.getParameter("last"));
myAuthor.setEmail(request.getParameter("email"));
hibernateSession.update(myAuthor);
myTransaction.commit();
hibernateSession.close();
done=true;
} catch (Exception e) {
error = e.getMessage(); e.printStackTrace();
try{ myTransaction.rollback(); }
catch (Exception e2) {;}
}
finally
{
try{hibernateSession.close();}
atch (Exception e) {;}
}
if(done)
{
response.sendRedirect("list_author.jsp");
return;
}
}
try
{
hibernateSession = AppSession.getSession();
myTransaction = hibernateSession.beginTransaction();
myAuthor = (Author)hibernateSession.load(
Author.class, request.getParameter("authorID"));
myTransaction.commit();
hibernateSession.close();
} catch (Exception e) { error = e.getMessage(); }
finally
{ try{ myTransaction.rollback(); }
catch (Exception e) {;}
finally { hibernateSession.close(); }
}
%>
<HTML>
<HEAD>
<TITLE>Edit Author</TITLE>
<meta name="no_print" content="true" />
</HEAD>
<BODY><%=error%>
<form name="edit_author" method="post" action="edit_author.jsp">
<table width="50%" border="0">
<tr>
<td>First Name</td>
<td><input type="text" name="first" value="<%=
myAuthor.getFirstName()%>"></td>
</tr>
<tr>
<td>Last Name </td>
<td><input type="text" name="last" value="<%=
myAuthor.getLastName()%>"></td>
</tr>
<tr>
<td>Email Address </td>
<td><input type="text" name="email" value="<%=
myAuthor.getEmail()%>"></td>
</tr>
<tr>
<td> </td>
<td><input name="authorID" type="hidden"
value="<%=request.getParameter("authorID")%>"><input
type="submit" name="Submit" value="Save Changes"></td>
</tr>
</table>
</form>
</BODY>
Create Post
Once a user has created an author, the author can make posts. Figure 2.9 shows a simple form for the user, with a pop-up to select the author of the post.

Listing 2.13 shows the code for creating a post with this form. Looking over the source, there are two main blocks of Java code at the start of the page. The first is only executed if the form has been submitted. As with the code shown for creating a new author, the most notable change is the use of an Author object to indicate the post's author. The second block uses the Criteria API to retrieve the list of authors.
Listing 2.13. Source for Creating a Post
<%@ page contentType="text/html; charset=utf-8" language="java"
import="com.cascadetg.ch02.*,net.sf.hibernate.*" %><%
String error = "";
Session hibernateSession = null;
Transaction myTransaction = null;
java.util.Iterator authors = null;
if(request.getParameter("authorID") != null)
if(request.getParameter("authorID").compareTo("null") != 0)
if(request.getParameter("Submit") != null)
{
boolean done = false;
String redirect_page = "view_post.jsp?postID=";
try
{
hibernateSession = AppSession.getSession();
myTransaction = hibernateSession.beginTransaction();
Post myPost = new Post();
myPost.setTitle(request.getParameter("title"));
myPost.setSummary(request.getParameter("summary"));
myPost.setContent(request.getParameter("content"));
myPost.setDate(new java.util.Date());
Author myAuthor = new Author();
myAuthor.setId(request.getParameter("authorID"));
myPost.setAuthor(myAuthor);
hibernateSession.save(myPost);
myTransaction.commit();
redirect_page = redirect_page + myPost.getId();
done=true;
} catch (Exception e) {
error = e.getMessage(); e.printStackTrace();
try{ myTransaction.rollback(); }
catch (Exception e2) {;}
}
finally
{
try{hibernateSession.close();}
catch (Exception e) {;}
}
if(done)
{
response.sendRedirect(redirect_page);
return;
}
}
try
{
hibernateSession = AppSession.getSession();
myTransaction = hibernateSession.beginTransaction();
Criteria query =
hibernateSession.createCriteria(Author.class);
query.addOrder(
net.sf.hibernate.expression.Order.asc("lastName"));
query.addOrder(
net.sf.hibernate.expression.Order.asc("firstName"));
authors = query.list().iterator();
myTransaction.commit();
hibernateSession.close();
} catch (Exception e) { error = e.getMessage(); }
finally
{ try{ myTransaction.rollback(); }
catch (Exception e) {;}
finally { hibernateSession.close(); }
}
%>
<HTML>
<HEAD>
<TITLE>Create Post</TITLE>
<meta name="no_print" content="true" />
</HEAD>
<BODY><%=error%>
<form name="create_post" method="post" action="create_post.jsp">
<table width="50%" border="0">
<tr>
<td>Author</td>
<td><select name="authorID">
<option default value="null">Please select an
author</option>
<% if(authors != null) { %>
<% while(authors.hasNext()) {
Author myAuthor = (Author)authors.next();%>
<option default value="<%=
myAuthor.getId()%>"><%=
myAuthor.getLastName()%>, <%=
myAuthor.getFirstName()%></option>
<% }
} %>
</select></td>
</tr>
<tr>
<td>Title</td>
<td><input name="title" type="text" id="title"></td>
</tr>
<tr>
<td>Summary</td>
<td><input name="summary" type="text" id="summary"></td>
</tr>
<tr>
<td>Content</td>
<td><textarea name="content"
id="content"></textarea></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" name="Submit"
value="Create Post"></td>
</tr>
</table>
</form>
</BODY>
</HTML>
View Post
After the post has been created, the user is given a chance to view it. This allows the user to read the post and optionally click the Edit link to make changes.

Listing 2.14 shows the code for viewing a post. The Session.get() method is used to retrieve an object by the supplied identifier.
Listing 2.14. Viewing a Post
<%@ page contentType="text/html; charset=utf-8" language="java"
import="com.cascadetg.ch02.*,net.sf.hibernate.*" %><%
String error = "";
Session hibernateSession = null;
Transaction myTransaction = null;
Post myPost = null;
try
{
hibernateSession = AppSession.getSession();
myTransaction = hibernateSession.beginTransaction();
myPost = (Post)hibernateSession.load(
Post.class, request.getParameter("postID"));
myTransaction.commit();
hibernateSession.close();
} catch (Exception e) {
error = e.getMessage(); e.printStackTrace();
try{ myTransaction.rollback(); }
catch (Exception e2) {;}
}
finally
{
try{hibernateSession.close();}
catch (Exception e) {;}
}
%><HTML>
<HEAD>
<TITLE>View Post</TITLE>
</HEAD>
<BODY><%=error%>
<table width="100%" border="0">
<tr>
<td width="20%"><strong>Title</strong></td>
<td><%=myPost.getTitle()%> </td>
</tr>
<tr>
<td width="20%"><strong>Version</strong></td>
<td><%=myPost.getRevision()%></td>
</tr>
<tr>
<td width="20%"><strong>Date</strong></td>
<td><%=myPost.getDate()%></td>
</tr>
<tr>
<td width="20%"><strong>Summary</strong></td>
<td><%=myPost.getSummary()%> </td>
</tr>
<tr>
<td width="20%"><strong>Content</strong></td>
<td><%=myPost.getContent()%> </td>
</tr>
</table>
<p align="right"><a href="edit_post.jsp?postid=<%=
request.getParameter("postID")%>">Edit Post</a> </p>
</BODY>
Edit Post
Figure 2.11 shows the standard interface presented when a user chooses to edit a post.

One of the more advanced features of this particular application is the use of Hibernate's built-in support for version management (as specified by the version tag in Listing 2.1). This allows Hibernate to verify that no intermediate changes have been made to an object before conducting the update. This powerful feature allows for an optimistic locking strategy (as described in more detail in Chapter 9).
In brief, imagine that two users are isaccessing this application at the same time. The first, Bob, goes to the edit page, and proceeds to spend several hours making lengthy changes. The second, Mary, opens the edit page and makes a minor spelling fix. When Bob attempts to save his revision, the application automatically detects that the version number of Bob's update is out of date (with a single UPDATE statement).
In our application, when this sort of conflict occurs, Bob is presented with both the revision currently in the database and the changes he has submitted. It's up to Bob to take these two revisions and submit a single merged post. Figure 2.12 shows the user interface presented to resolve this conflict. The conflict itself is detected with a net.sf.hibernate.StaleObjectStateException.

Listing 2.15 shows the code for editing a post. Pay close attention to the catch of the net.sf.hibernate.StaleObjectStateException. This is the mechanism whereby Hibernate informs the application that the attempt to UPDATE the post has failed because of a problem with the Post version.
Listing 2.15. Editing a Post
<%@ page contentType="text/html; charset=utf-8" language="java"
import="com.cascadetg.ch02.*,net.sf.hibernate.*" %><%
String error = "";
boolean conflict = false;
Session hibernateSession = null;
Transaction myTransaction = null;
Post myPost = null;
if(request.getParameter("Submit") != null)
{
boolean done = false;
String redirect_page = "view_post.jsp?postID=";
try
{
hibernateSession = AppSession.getSession();
myTransaction = hibernateSession.beginTransaction();
myPost = new Post();
myPost.setId(request.getParameter("postID"));
myPost.setRevision(
new Integer(
request.getParameter("revision"))
.intValue());
myPost.setTitle(request.getParameter("title"));
myPost.setDate(new java.util.Date());
myPost.setSummary(request.getParameter("summary"));
myPost.setContent(request.getParameter("content"));
Author myAuthor = new Author();
myAuthor.setId(request.getParameter("authorID"));
myPost.setAuthor(myAuthor);
hibernateSession.update(myPost);
myTransaction.commit();
hibernateSession.close();
redirect_page =
redirect_page + request.getParameter("postID");
done = true;
}
catch (net.sf.hibernate.StaleObjectStateException stale)
{
error =
"This post was updated by another transaction. " +
"You may either update the existing " +
"data, or resubmit your changes.";
conflict=true;
}
catch (Exception e) {
error = e.getMessage(); e.printStackTrace();
try{ myTransaction.rollback(); }
catch (Exception e2) {;}
}
finally
{
try{hibernateSession.close();}
catch (Exception e) {;}
}
if(done)
{
response.sendRedirect(redirect_page);
return;
}
}
try
{
hibernateSession = AppSession.getSession();
myTransaction = hibernateSession.beginTransaction();
Criteria query =
hibernateSession.createCriteria(Post.class);
myPost = (Post)com.cascadetg.ch02.finder.
PostFinder.findByID(hibernateSession,
request.getParameter("postID")).iterator().next();
myTransaction.commit();
hibernateSession.close();
} catch (Exception e)
{ error = e.getMessage(); e.printStackTrace(); }
finally
{ try{ myTransaction.rollback(); }
catch (Exception e) {;}
finally { hibernateSession.close(); }
}
%>
<HTML>
<HEAD>
<TITLE>Edit Post</TITLE>
<meta name="no_print" content="true" />
</HEAD>
<BODY><%=error %>
<% if(conflict) { %>
<p><strong>Current Saved Post</strong></p>
<% } %>
<form name="edit_post" method="post" action="edit_post.jsp">
<table width="100%" border="0">
<tr>
<td width="25%"><strong>Title</strong></td>
<td><input name="title" type="text" value="<%=
myPost.getTitle()%>"></td>
<td> </td>
</tr>
<tr>
<td width="25%"><strong>Summary</strong></td>
<td><input name="summary" type="text" id="summary"
value="<%=myPost.getSummary()%>"></td>
<td> </td>
</tr>
<tr>
<td width="25%"><strong>Content </strong></td>
<td><textarea name="content" id="content"><%=
myPost.getContent()%></textarea></td>
<td> </td>
</tr>
<tr>
<td width="25%"><strong>Date / Revision</strong></td>
<td><%=myPost.getDate()%> / <%=myPost.getRevision()%>
<input name="revision" type="hidden" id="revision"
value="<%=myPost.getRevision()%>"></td>
<td> </td>
</tr>
<tr>
<td width="25%"> </td>
<td><input name="authorID" type="hidden"
value="<%=myPost.getAuthor().getId()%>"><input
name="postID" type="hidden"
value="<%=request.getParameter("postID")%>">
<input type="submit" name="Submit"
value="Save Changes"></td>
<td> </td>
</tr>
</table>
</form>
<% if(conflict) { %>
<hr>
<p>Newly submitted post.</p>
<form name="edit_post" method="post" action="edit_post.jsp">
<table width="100%" border="0">
<tr>
<td width="25%"><strong>Submitted Title Change
</strong></td>
<td>
<input type="text" name="title" value="<%=
request.getParameter("title") %>"></td>
</tr>
<tr>
<td width="25%"><strong>Submitted Summary Change
</strong></td>
<td><input type="text" name="summary" value="<%=
request.getParameter("summary")%>"></td>
</tr>
<tr>
<td width="25%"><strong>Submitted Content Change
</strong></td>
<td><textarea name="content"><%=
request.getParameter("content")%></textarea>
<input name="revision" type="hidden"
id="revision" value="<%=myPost.getRevision()%>">
<input name="authorID" type="hidden"
value="<%=myPost.getAuthor().getId()%>">
<input name="postID" type="hidden"
value="<%=request.getParameter("postID")%>"></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" name="Submit"
value="Save Submitted Changes"></td>
</tr>
</table>
</form>
<% } %>
</BODY>
Delete Post
Sometimes a post is no longer of interest or covers a topic that the writer wishes had never been brought up. Figure 2.13 shows the simple HTML confirmation form presented when a user wishes to delete a post.

Listing 2.16 shows how the post is deleted. As can be seen, deleting a persistent object is a simple one-step method call to the Session.
|
This implementation first executes a load regardless of the delete operation. This is required to delete the post, as the version of the record is required to issue the delete. The application doesn't care about the version; it just wants to delete the post.
Alternatively, the application could retrieve the version number of the post when the form is first displayed and then pass the version along with a hidden field. This would have two advantagesit would allow the delete to occur without the first get, and would ensure that the deleted post is of the proper revision. |
Listing 2.16. Deleting a Post
<%@ page contentType="text/html; charset=utf-8" language="java"
import="com.cascadetg.ch02.*,net.sf.hibernate.*" %><%
String error = "";
Session hibernateSession = null;
Transaction myTransaction = null;
Post myPost = null;
boolean done = false;
try
{
hibernateSession = AppSession.getSession();
myTransaction = hibernateSession.beginTransaction();
myPost = (Post)hibernateSession.load(Post.class,
request.getParameter("postID"));
if(request.getParameter("Submit") != null)
{
hibernateSession.delete(myPost);
done=true;
} else
{
}
myTransaction.commit();
} catch (Exception e) {
error = e.getMessage(); e.printStackTrace();
try{ myTransaction.rollback(); }
catch (Exception e2) {;}
}
finally
{
try{hibernateSession.close();}
catch (Exception e) {;}
}
if(done)
{
response.sendRedirect("list_posts.jsp");
return;
}
%>
<HTML>
<HEAD>
<TITLE>Delete Post</TITLE>
<meta name="no_print" content="true" />
</HEAD>
<BODY><%=error%>
<p>Are you sure you want to delete the post "<b><%=
myPost.getTitle()%></b>"?</p>
<form name="delete_post" method="post" action="delete_post.jsp">
<input name="postID" type="hidden" value="<%=
request.getParameter("postID")%>">
<input type="submit" name="Submit" value="Delete Post">
</form>
</BODY>
Delete Author
Finally, a user may wish to delete an author, as shown in Figure 2.14. Note the warning that all of the author's posts will be deleted as well.

Every post must be assigned to an author. Deleting the author means that any posts pointing to that author are left in an inconsistent statethe foreign key on the authorID column would be violated. Hibernate takes care of this automatically. The mapping file in Listing 2.2 declares that the posts are to be deleted when the owning author is deleted (the cascade="delete" attribute). Therefore, the code in Listing 2.17 merely issues a single delete and Hibernate automatically deletes both the Author and all associated Post records.
WARNING
As you can imagine, cascading deletes are both powerful and very dangerous. Make sure that you fully understand (and test) your cascading operations to ensure that the action you get is the action you expect.
Listing 2.17. Deleting an Author
<%@ page contentType="text/html; charset=utf-8" language="java"
import="com.cascadetg.ch02.*,net.sf.hibernate.*" %><%
String error = "";
Session hibernateSession = null;
Transaction myTransaction = null;
Author myAuthor = null;
try
{
hibernateSession = AppSession.getSession();
myTransaction = hibernateSession.beginTransaction();
if(request.getParameter("Submit") != null)
{
myAuthor = new Author();
myAuthor.setId(request.getParameter("authorID"));
System.out.println(myAuthor.getId());
hibernateSession.refresh(myAuthor);
hibernateSession.delete(myAuthor);
myTransaction.commit();
response.sendRedirect("list_author.jsp");
return;
} else
{
myAuthor = (Author)hibernateSession.load(Author.class,
request.getParameter("authorID"));
myTransaction.commit();
}
} catch (Exception e) {
error = e.getMessage(); e.printStackTrace();
try{ myTransaction.rollback(); }
catch (Exception e2) {;}
}
finally
{
try{hibernateSession.close();}
catch (Exception e) {;}
}
%>
<HTML>
<HEAD>
<TITLE>Delete Author</TITLE>
<meta name="no_print" content="true" />
</HEAD>
<BODY><%=error%>
<p>Are you sure you want to delete the author and
all posts written by the author
<b><%=myAuthor.getFirstName()%>
<%=myAuthor.getLastName()%></b>?</p>
<form name="delete_author" method="post" action="delete_author.jsp">
<input type="hidden" name="authorID"
value="<%= request.getParameter("authorID") %>">
<input type="submit" name="Submit" value="Delete Author">
</form>
</BODY>
</HTML>
Next Steps
Now that you've gotten a taste for Hibernate, your next steps depend on your needs and situation. In this chapter the application was built "from the middle out"a mapping file generated both the persistent Java objects and the database definition. In Chapter 3, an application is built starting from Java, and in Chapter 4, an existing database definition is used. Even if you don't intend to use either of these approaches yourself, the examples shown in Chapters 3 and 4 are used throughout this book as examples. Note that the remaining examples in the book are provided as simple command-line operations and not as full-blown Web applications. This serves to keep the focus on Hibernate as a tool rather than on the idiosyncrasies of Web application development.
|