Once again way to go on verifying that your Contact objects are being persisted
into your database.
With simple console output, we were able to spy on the sequel that
Hibernate was generating and firing off to H2 for final processing.
This kind of monitoring of a Hibernate queries is useful in many scenarios.
Especially when fine-tuning the performance of Hibernate and
minimizing both the number of times your application has to hit the DB
as well as the amount of time each query is taking.
In our case though, it's only a stepping stone to using our data and
displaying it more naturally in the application.
What we'll look at now is how to use Hibernate to fetch a list of
all the objects of a certain entity class that have been persisted to the database.
Let's have a look at the most basic way of doing that with what is called Hibernate
Here in application.java, I'd like to do some refactoring first.
Since we currently have code saving a Contact object, and we're about to
write code to retrieve contact objects, let's split those into separate methods.
Let's create a method named save and have it persist as supplied contact.
I'll get the method signature in here now, private static void save.
And I want to save a Contact object, I'll name it contact.
And into here,
I'm gonna drop all that code that we previously put into the main method.
Great. Then, back up in main, we can simply call
the save method with the Contact object we created using the builder, just like this.
Next, let's create a method that will retrieve or
fetch all of our Contact objects from the database.
Let's call it fetchAllContacts.
So, private static will return a list, that's a java.util list,
of Contact objects and we'll call it fetchAllContacts.
Because we're interacting with a database using Hibernate this will involve
opening a session, doing some stuff, then closing the session.
So let's get that session open and close in there right away.
So we'll first open a session, we'll do some other things but
finally we'll close the session.
So again, to open the session, it's the same code as before,
session = sessionFactory.openSession.
And to close the session, we simply call the close method on that S~ession object.
Now between these two lines of code, while the session is open,
that's where our magical code will come into play.
To retrieve all contacts as a list of contact objects
we'll use what's called a Hibernate Criteria object.
In Hibernate, a Criteria object can be used to filter results according to one or
In its most basic form,
a criteria can be used to produce a list of persisted entity objects.
Here's how it looks, so first, we're going to create the Criteria object.
I'll declare a criteria variable that comes from org.Hibernate,
I'll call it criteria and into it I'll store a call to session.createCriteria.
And here is where we put a reference to the contact class,
Whereas we could add all sorts of restrictions to the Criteria object here
such as restricting results to contacts whose first name is Fiona or
whose email contains teentreehouse.com.
We can simply leave the Criteria object as is, and call its list method.
So let's create a list of Contact objects.
That will be a list of Contact objects, I'll call it contacts.
And store into it the results of calling that list method.
Let me add a comment here that says exactly what I'm doing.
Get a list of Contact objects
according to the Criteria object that we just created.
Now, after we close the session, we'll need to return that list of contacts,
Now, you might notice that you get some faint highlighting over critera.list.
What this is is a compiler warning telling us that we have an unchecked assignment.
The Criteria objects list method returns an unparamaterized list and
we're assigning it to a paramaterized list that is a list of Contact objects.
If you recall from our annotations course, we can suppress compiler warnings.
Because we don't have access to alter the hibernate source
code to resolve this assignment,
this is one of those few scenarios when it is acceptable to suppress the warning.
So let's do that with a SuppressWarnings annotation.
we will suppress the unchecked assignment warning using the string unchecked.
Excellent, the warning is now suppressed.
Now, to put this to work.
Let's go back up to the main method and
display a list of contacts using its two-string method.
So, here I'm going to display a list of contacts by using a for loop.
So I'm going to iterate over all contacts
that come back from the fetchAllContacts method.
And in here, I'm simply going to use a System.out.println of c.
Now, let's run the application again, to see our Contact objects displayed.
So I'll right click here and choose Run.
And you'll see a bunch of Hibernate output until finally we get
to our applications output.
And here are the results of our two-string method which show that we did
indeed successfully persist that Contact object using our method.
And successfully retrieved that list of contacts,
even though there is only one, using Hibernate, excellent.
Now you may wonder that after running this application a few times,
why is it that you always get just one contact in your database?
Each time I run it I still get just one contact in my database.
You might be asking, doesn't the data continue to exist after exiting and
re-running the application?
After I run it a second time shouldn't there be two contacts in there?
And a third time, shouldn't there be three contacts in there?
The answer to those questions is, well, no.
And that is because we told the HBM to DDL tool to create
our database schema on startup.
If we go back to that configuration file, we can remind ourselves that we set
the HBM to DDL.autoproperty to create.
That means that any previous data will be wiped out on application startup.
And we can change that property value to update so that only database schema
changes will be made instead of blowing away our whole schema and recreating.
Let me update the comment here.
Update the database schema on startup.
So now, when we rerun the application, if Hibernate detects that there have been
changes in the schema as indicated by our JPA annotations.
The table or tables will be altered by the HBM to DDL
tool without changing the data that exists in those tables.
So, after making that change, let me stop the application.
I will delete all the output in my terminal here and I will rerun.
Let's see what kind of data we get now.
There you have it, we have two contacts here.
Of course, because our application code only specifies information for
one contact, we'll continue getting the same info for each contact, but
with one exception, the id here.
In the second contact it's 2, in the first contact it's 1.
Remember the id field is automatically generated, so
that each contact has a unique id in the database.
As a fun side note, if we switch back to application.java,
we can use some of the new features offered by Java 8 to condense our code.
Specifically, this code right here.
This for each loop can be simplified by using what's called a stream, and
on that stream we can call a method named, for each.
Passing to it, a reference to the system.out classes static printlin method.
Let me show you how that looks.
We'll call the fetchAllContacts method and on that list we will create a Java stream.
And here is where we can call this method named forEach, passing a method reference,
which is new in Java 8, to the println.
The system that out-classes static println method.
And, after running this, you should see that we get the same output.
Let me stop our previous run of the application, trash our output, and
re-run it to see if we get the same output.
Excellent, we do get the same output.
And now we have three contacts, pretty sweet stuff.
Check out the Teacher's Notes for some more features introduced in Java 8.
Wow; I think I figured out the answer to my own question. I'm just not sure it's worth it! :)
The problem is the cast isn't checked. So, you have to check it yourself. You can't just check a parameterized type with instanceof, because the parameterized type information is unavailable at runtime, having been erased at compile time.
But, you can perform a check on each and every item in the hash, with instanceof, and in doing so, you can construct a new hash that is type-safe. And you won't provoke any warnings.
Thanks to mmyers and Esko Luontola, I've parameterized the code I originally wrote here, so it can be wrapped up in a utility class somewhere and used for any parameterized HashMap. If you want to understand it better and aren't very familiar with generics, I encourage viewing the edit history of this answer.
That's a lot of work, possibly for very little reward... I'm not sure if I'll use it or not. I'd appreciate any comments as to whether people think it's worth it or not. Also, I'd appreciate improvement suggestions: is there something better I can do besides throw AssertionErrors? Is there something better I could throw? Should I make it a checked Exception?