Working with the Database
The application now has both *.hbm.xml files and corresponding Java source files. Given these files, it's a simple matter to use Hibernate to perform database operations. The sample code shown in the remainder of this chapter will use the generated files to populate the database with some data and then produce a report based on that data.
From the perspective of the classes manipulating the database via Hibernate, these are just additional examples of manipulating data with Hibernate, independent of the build system that generated the Java and mapping files.
Two classes, as shown in Figure 4.4, are used to manipulate the data. The first, GenerateData, populates the database with some test data. The second, GenerateReports, generates a tab-delimited text file, suitable for use with a spreadsheet.

Listing 4.13 demonstrates the insertion of data. Note the use of java.util.HashSet as a concrete implementation of java.util.Set. The latter is only an interface, whereas the former is a concrete implementation. For more information on sets and relationships, see Chapter 7.
Listing 4.13. Generating Data
package com.cascadetg.ch04;
import java.util.HashSet;
/** Various Hibernate-related imports */
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
public class GenerateData
{
/** We use this session factory to create our sessions */
public static SessionFactory sessionFactory;
static String[] students =
{
"Smith",
"Bob",
"123-45-6789",
"Stevens",
"John",
"456-78-9012",
"Almara",
"Betty",
"098-76-5432" };
static Student[] createdStudents = new Student[3];
static Exam midterm;
static Exam coursefinal;
/** Loads the Hibernate configuration information,
* sets up the database and the Hibernate session factory.
*/
public static void initialization()
{
//System.setErr(System.out);
System.out.println("initialization");
try
{
Configuration myConfiguration = new
Configuration();
myConfiguration.addClass(Course.class);
myConfiguration.addClass(Exam.class);
myConfiguration.addClass(Examresult.class);
myConfiguration.addClass(Student.class);
// Sets up the session factory (used in the rest
// of the application).
sessionFactory =
myConfiguration.buildSessionFactory();
} catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
initialization();
createClass();
createExamResults();
}
static void createClass()
{
System.out.println();
System.out.println("createClass");
Session hibernateSession = null;
Transaction myTransaction = null;
try
{
hibernateSession = sessionFactory.openSession();
myTransaction =
hibernateSession.beginTransaction();
Course myCourse = new Course();
myCourse.setQuarter("Q12005");
myCourse.setTitle("Introduction To Hibernate");
hibernateSession.save(myCourse);
midterm = new Exam();
midterm.setComment("First midterm");
midterm.setCourse(myCourse);
hibernateSession.save(midterm);
coursefinal = new Exam();
coursefinal.setComment("Course final");
coursefinal.setCourse(myCourse);
hibernateSession.save(coursefinal);
HashSet myExams = new HashSet();
myExams.add(midterm);
myExams.add(coursefinal);
myCourse.setExams(myExams);
hibernateSession.save(myCourse);
for (int i = 0; i < students.length; i = i + 3)
{
Student newStudent = new Student();
newStudent.setLastName(students[i]);
newStudent.setFirstName(students[i + 1]);
newStudent.setIdString(students[i + 2]);
hibernateSession.save(newStudent);
createdStudents[i / 3] = newStudent;
}
hibernateSession.flush();
myTransaction.commit();
} catch (Exception e)
{
e.printStackTrace();
try
{
myTransaction.rollback();
} catch (Exception e2)
{
// Silent failure of transaction rollback
}
} finally
{
try
{
hibernateSession.close();
} catch (Exception e2)
{
// Silent failure of session close
}
}
}
static void createExamResults()
{
System.out.println();
System.out.println("createExamResults");
Session hibernateSession = null;
Transaction myTransaction = null;
try
{
hibernateSession = sessionFactory.openSession();
myTransaction =
hibernateSession.beginTransaction();
for (int i = 0; i < createdStudents.length; i++)
{
Student myStudent = createdStudents[i];
Examresult myExamResult = new Examresult();
myExamResult.setScore(85 + i * 4);
myExamResult.setStudent(myStudent);
myExamResult.setExam(midterm);
hibernateSession.save(myExamResult);
}
for (int i = 0; i < createdStudents.length; i++)
{
Student myStudent = createdStudents[i];
Examresult myExamResult = new Examresult();
myExamResult.setScore(75 + i * 8);
myExamResult.setStudent(myStudent);
myExamResult.setExam(coursefinal);
hibernateSession.save(myExamResult);
}
hibernateSession.flush();
myTransaction.commit();
} catch (Exception e)
{
e.printStackTrace();
try
{
myTransaction.rollback();
} catch (Exception e2)
{
// Silent failure of transaction rollback
}
} finally
{
try
{
hibernateSession.close();
} catch (Exception e2)
{
// Silent failure of session close
}
}
}
}
Once data is loaded into the database, generating a report is only a matter of retrieving data from the database. Listing 4.14 shows how the report is generated, including the use of HQL to obtain statistical information. For more information on HQL, see Chapter 8.
|
You may have noticed that the uses of Hibernate in the examples in this book all explicitly commit the transactions (for example, mytransaction .commit()). This explicit call to commit a transaction isn't strictly necessary, but it's best to get into the habit of using it. On the other hand, you may eventually get tired of doing the bookkeeping associated with opening a session, committing a transaction, handling exceptions, and closing sessions. For a discussion of one strategy to deal with this, check out inversion-of- control as described in Chapter 12. |
Listing 4.14. Generating the Report
package com.cascadetg.ch04;
/** Various Hibernate-related imports */
import java.io.FileOutputStream;
import java.util.Iterator;
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;
import net.sf.hibernate.expression.*;
public class GenerateReports
{
/** This is used to store the resulting report */
static StringBuffer report = new StringBuffer();
// System constants for the new line and directory tokens
static String newLine =
System.getProperty("line.separator");
static String fileSep =
System.getProperty("file.separator");
/** We use this session factory to create our sessions */
static SessionFactory sessionFactory;
static public String highScore(Exam inExam)
{
String hql =
"select max(result.score) from Examresult "
+ "as result where result.exam=?";
return getExamStats(hql, inExam);
}
static public String lowScore(Exam inExam)
{
String hql =
"select min(result.score) from Examresult "
+ "as result where result.exam=?";
return getExamStats(hql, inExam);
}
static public String averageScore(Exam inExam)
{
String hql =
"select avg(result.score) from Examresult "
+ "as result where result.exam=?";
return getExamStats(hql, inExam);
}
static public String getExamStats(String hql, Exam inExam)
{
Session hibernateSession = null;
Transaction myTransaction = null;
String returnVal = "0";
try
{
hibernateSession = sessionFactory.openSession();
myTransaction =
hibernateSession.beginTransaction();
Query myQuery = hibernateSession.createQuery(hql);
myQuery.setLong(0, inExam.getId().longValue());
returnVal = myQuery.iterate().next().toString();
myTransaction.commit();
} catch (Exception e)
{
e.printStackTrace();
try
{
myTransaction.rollback();
} catch (Exception e2)
{
// Silent failure of transaction rollback
}
} finally
{
try
{
if (hibernateSession != null)
hibernateSession.close();
} catch (Exception e)
{
// Silent failure of session close
}
}
return returnVal;
}
static public String getExamReport(Exam inExam)
{
Session hibernateSession = null;
Transaction myTransaction = null;
java.util.Iterator result = null;
String returnVal = "0";
try
{
hibernateSession = sessionFactory.openSession();
myTransaction =
hibernateSession.beginTransaction();
// In this example, we use the Criteria API. We
// could also have used the HQL, but the
// Criteria API allows us to express this query
// more easily.
Criteria query =
hibernateSession.createCriteria(Examresult.class);
query.add(Expression.like("exam", inExam));
// Now, specify sorting by the score
query.addOrder(Order.desc("score"));
// Indicate that we want to grab all of the
// associated student IDs as well. This
// lets us pull all of the data in a single
// SQL statement!
query.setFetchMode("student.idString",
FetchMode.EAGER);
// This actually performs the database request,
// based on the query we've built.
result = query.list().iterator();
while (result.hasNext())
{
Examresult myExamResult =
(Examresult)result.next();
report.append(myExamResult.
getStudent().getIdString());
report.append("\t");
report.append(myExamResult.getScore());
report.append(newLine);
}
myTransaction.commit();
} catch (Exception e)
{
e.printStackTrace();
try
{
myTransaction.rollback();
} catch (Exception e2)
{
// Silent failure of transaction rollback
}
} finally
{
try
{
if (hibernateSession != null)
hibernateSession.close();
} catch (Exception e)
{
// Silent failure of session close
}
}
return returnVal;
}
static public void generateReport()
{
Session hibernateSession = null;
Transaction myTransaction = null;
java.util.Iterator result = null;
try
{
hibernateSession = sessionFactory.openSession();
myTransaction =
hibernateSession.beginTransaction();
// In this example, we use the Criteria API. We
// could also have used the HQL, but the
// Criteria API allows us to express this query
// more easily.
Criteria myQuery =
hibernateSession.createCriteria(Course.class);
result = myQuery.list().iterator();
while (result.hasNext())
{
Course myCourse = (Course)result.next();
Iterator exams =
myCourse.getExams().iterator();
report.append(myCourse.getTitle());
report.append(newLine);
report.append(myCourse.getQuarter());
report.append(newLine);
report.append(newLine);
while (exams.hasNext())
{
Exam myExam = (Exam)exams.next();
report.append(myExam.getComment());
report.append(newLine);
report.append("High Score: \t");
report.append(highScore(myExam));
report.append(newLine);
report.append("Low Score: \t");
report.append(lowScore(myExam));
report.append(newLine);
report.append("Average Score: \t");
report.append(averageScore(myExam));
report.append(newLine);
report.append(newLine);
getExamReport(myExam);
report.append(newLine);
}
}
myTransaction.commit();
} catch (Exception e)
{
e.printStackTrace();
try
{
myTransaction.rollback();
} catch (Exception e2)
{
// Silent failure of transaction rollback
}
} finally
{
try
{
if (hibernateSession != null)
hibernateSession.close();
} catch (Exception e)
{
// Silent failure of session close
}
}
}
static public void initialization()
{
try
{
Configuration myConfiguration = new
Configuration();
myConfiguration.addClass(Course.class);
myConfiguration.addClass(Exam.class);
myConfiguration.addClass(Examresult.class);
myConfiguration.addClass(Student.class);
// Sets up the session factory (used in the rest
// of the application).
sessionFactory =
myConfiguration.buildSessionFactory();
} catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
// Places the generated report in the same directory
// as this Java source file.
java.io.File reportFile =
new java.io.File(
"com"
+ fileSep
+ "cascadetg"
+ fileSep
+ "ch04"
+ fileSep
+ "report.txt");
// If the report file doesn't exist, generate the
// default data set.
if (!reportFile.exists())
{
GenerateData.main(null);
}
// Set up our session factory
initialization();
// Do all of the report generation
generateReport();
// Echo the results to the console
System.out.println(report.toString());
// Try to write the results to the report file
try
{
FileOutputStream myOutputStream =
new FileOutputStream(reportFile);
myOutputStream.write(report.toString().getBytes());
} catch (Exception e)
{
e.printStackTrace();
}
}
}
When this application runs, it will generate the report file. Before looking at the report, Listing 4.15 shows the SQL generated by Hibernate during the course of the run. While the SQL shown may seem complex, it's a lot easier to look at this generated SQL than to write the SQL by hand. Several statements are much more complex than what one might easily writein particular, the single lengthy statement which fetches both the Examresults and the associated Student records with a single query. Compare that SQL statement with the generating code, as shown in the GenerateReports.getExamReport().
Listing 4.15. SQL Generated by Hibernate
Hibernate: select this.ID as ID0_, this.title as title0_, this.quarter as quarter0_ from
course this where 1=1
Hibernate: select exams0_.ID as ID__, exams0_.courseID as courseID__, exams0_.ID as ID0_,
exams0_.date as date0_, exams0_.comment as comment0_, exams0_.courseID as courseID0_ from
exam exams0_ where exams0_.courseID=?
Hibernate: select max(examresult0_.score) as x0_0_ from examresult examresult0_ where
(examresult0_.examID=? )
Hibernate: select min(examresult0_.score) as x0_0_ from examresult examresult0_ where
(examresult0_.examID=? )
Hibernate: select avg(examresult0_.score) as x0_0_ from examresult examresult0_ where
(examresult0_.examID=? )
Hibernate: select this.ID as ID3_, this.score as score3_, this.studentID as studentID3_,
this.examID as examID3_, student1_.ID as ID0_, student1_.firstName as firstName0_,
student1_.lastName as lastName0_, student1_.idString as idString0_, exam2_.ID as ID1_,
exam2_.date as date1_, exam2_.comment as comment1_, exam2_.courseID as courseID1_,
course3_.ID as ID2_, course3_.title as title2_, course3_.quarter as quarter2_ from
examresult this left outer
outer join exam exam2_ on this.examID=exam2_.ID left outer join join student student1_ on
this.studentID=student1_.ID left
course course3_ on exam2_.courseID=course3_.ID where this.examID like ? order by this
.score desc
Hibernate: select max(examresult0_.score) as x0_0_ from examresult examresult0_ where
(examresult0_.examID=? )
Hibernate: select min(examresult0_.score) as x0_0_ from examresult examresult0_ where
(examresult0_.examID=? )
Hibernate: select avg(examresult0_.score) as x0_0_ from examresult examresult0_ where
(examresult0_.examID=? )
Hibernate: select this.ID as ID3_, this.score as score3_, this.studentID as studentID3_,
this.examID as examID3_, student1_.ID as ID0_, student1_.firstName as firstName0_,
student1_.lastName as lastName0_, student1_.idString as idString0_, exam2_.ID as ID1_,
exam2_.date as date1_, exam2_.comment as comment1_, exam2_.courseID as courseID1_,
course3_.ID as ID2_, course3_.title as title2_, course3_.quarter as quarter2_ from
examresult this left outer join student student1_ on this.studentID=student1_.ID left
outer join exam exam2_ on this.examID=exam2_.ID left outer join course course3_ on exam2_
.courseID=course3_.ID where this.examID like ? order by this.score desc
Finally, the generated report, a tab-delimited text file, can easily be opened in any popular spreadsheet software and formatted and edited as needed, as shown in Figure 4.5.

 |