1 00:00:00,890 --> 00:00:05,120 Once again way to go on verifying that your Contact objects are being persisted 2 00:00:05,120 --> 00:00:06,858 into your database. 3 00:00:06,858 --> 00:00:10,560 With simple console output, we were able to spy on the sequel that 4 00:00:10,560 --> 00:00:14,220 Hibernate was generating and firing off to H2 for final processing. 5 00:00:15,660 --> 00:00:19,568 This kind of monitoring of a Hibernate queries is useful in many scenarios. 6 00:00:19,568 --> 00:00:23,620 Especially when fine-tuning the performance of Hibernate and 7 00:00:23,620 --> 00:00:27,800 minimizing both the number of times your application has to hit the DB 8 00:00:27,800 --> 00:00:30,680 as well as the amount of time each query is taking. 9 00:00:31,680 --> 00:00:35,110 In our case though, it's only a stepping stone to using our data and 10 00:00:35,110 --> 00:00:37,430 displaying it more naturally in the application. 11 00:00:38,450 --> 00:00:41,660 What we'll look at now is how to use Hibernate to fetch a list of 12 00:00:41,660 --> 00:00:46,770 all the objects of a certain entity class that have been persisted to the database. 13 00:00:46,770 --> 00:00:50,850 Let's have a look at the most basic way of doing that with what is called Hibernate 14 00:00:50,850 --> 00:00:51,448 criteria. 15 00:00:51,448 --> 00:00:58,000 Here in application.java, I'd like to do some refactoring first. 16 00:00:58,000 --> 00:01:01,910 Since we currently have code saving a Contact object, and we're about to 17 00:01:01,910 --> 00:01:06,840 write code to retrieve contact objects, let's split those into separate methods. 18 00:01:06,840 --> 00:01:11,210 Let's create a method named save and have it persist as supplied contact. 19 00:01:11,210 --> 00:01:16,180 I'll get the method signature in here now, private static void save. 20 00:01:16,180 --> 00:01:20,350 And I want to save a Contact object, I'll name it contact. 21 00:01:20,350 --> 00:01:21,070 And into here, 22 00:01:21,070 --> 00:01:26,580 I'm gonna drop all that code that we previously put into the main method. 23 00:01:26,580 --> 00:01:29,792 Great. Then, back up in main, we can simply call 24 00:01:29,792 --> 00:01:35,620 the save method with the Contact object we created using the builder, just like this. 25 00:01:37,460 --> 00:01:38,720 Save contact. 26 00:01:39,910 --> 00:01:42,560 Next, let's create a method that will retrieve or 27 00:01:42,560 --> 00:01:45,490 fetch all of our Contact objects from the database. 28 00:01:45,490 --> 00:01:48,489 Let's call it fetchAllContacts. 29 00:01:48,489 --> 00:01:55,040 So, private static will return a list, that's a java.util list, 30 00:01:55,040 --> 00:02:00,050 of Contact objects and we'll call it fetchAllContacts. 31 00:02:01,720 --> 00:02:05,050 Because we're interacting with a database using Hibernate this will involve 32 00:02:05,050 --> 00:02:08,990 opening a session, doing some stuff, then closing the session. 33 00:02:08,990 --> 00:02:13,060 So let's get that session open and close in there right away. 34 00:02:13,060 --> 00:02:17,280 So we'll first open a session, we'll do some other things but 35 00:02:17,280 --> 00:02:19,380 finally we'll close the session. 36 00:02:21,940 --> 00:02:24,608 So again, to open the session, it's the same code as before, 37 00:02:24,608 --> 00:02:29,050 session = sessionFactory.openSession. 38 00:02:29,050 --> 00:02:33,710 And to close the session, we simply call the close method on that S~ession object. 39 00:02:34,835 --> 00:02:36,055 Cool. 40 00:02:36,055 --> 00:02:39,765 Now between these two lines of code, while the session is open, 41 00:02:39,765 --> 00:02:42,275 that's where our magical code will come into play. 42 00:02:42,275 --> 00:02:45,195 To retrieve all contacts as a list of contact objects 43 00:02:45,195 --> 00:02:48,705 we'll use what's called a Hibernate Criteria object. 44 00:02:48,705 --> 00:02:52,675 In Hibernate, a Criteria object can be used to filter results according to one or 45 00:02:52,675 --> 00:02:54,930 more restrictions. 46 00:02:54,930 --> 00:02:56,130 In its most basic form, 47 00:02:56,130 --> 00:03:00,920 a criteria can be used to produce a list of persisted entity objects. 48 00:03:00,920 --> 00:03:05,260 Here's how it looks, so first, we're going to create the Criteria object. 49 00:03:07,150 --> 00:03:10,580 I'll declare a criteria variable that comes from org.Hibernate, 50 00:03:10,580 --> 00:03:17,900 I'll call it criteria and into it I'll store a call to session.createCriteria. 51 00:03:17,900 --> 00:03:22,940 And here is where we put a reference to the contact class, 52 00:03:22,940 --> 00:03:26,120 that's Contact.class. 53 00:03:26,120 --> 00:03:29,820 Whereas we could add all sorts of restrictions to the Criteria object here 54 00:03:29,820 --> 00:03:34,150 such as restricting results to contacts whose first name is Fiona or 55 00:03:34,150 --> 00:03:37,370 whose email contains teentreehouse.com. 56 00:03:37,370 --> 00:03:42,610 We can simply leave the Criteria object as is, and call its list method. 57 00:03:42,610 --> 00:03:45,370 So let's create a list of Contact objects. 58 00:03:46,410 --> 00:03:50,340 That will be a list of Contact objects, I'll call it contacts. 59 00:03:51,540 --> 00:03:54,765 And store into it the results of calling that list method. 60 00:03:54,765 --> 00:03:57,804 Criteria.list. 61 00:03:59,200 --> 00:04:02,620 Let me add a comment here that says exactly what I'm doing. 62 00:04:02,620 --> 00:04:05,630 Get a list of Contact objects 63 00:04:07,110 --> 00:04:12,770 according to the Criteria object that we just created. 64 00:04:12,770 --> 00:04:16,110 Now, after we close the session, we'll need to return that list of contacts, 65 00:04:16,110 --> 00:04:18,520 return contacts. 66 00:04:18,520 --> 00:04:24,620 Now, you might notice that you get some faint highlighting over critera.list. 67 00:04:24,620 --> 00:04:30,290 What this is is a compiler warning telling us that we have an unchecked assignment. 68 00:04:30,290 --> 00:04:34,320 The Criteria objects list method returns an unparamaterized list and 69 00:04:34,320 --> 00:04:39,130 we're assigning it to a paramaterized list that is a list of Contact objects. 70 00:04:39,130 --> 00:04:43,960 If you recall from our annotations course, we can suppress compiler warnings. 71 00:04:43,960 --> 00:04:46,760 Because we don't have access to alter the hibernate source 72 00:04:46,760 --> 00:04:48,670 code to resolve this assignment, 73 00:04:48,670 --> 00:04:53,435 this is one of those few scenarios when it is acceptable to suppress the warning. 74 00:04:53,435 --> 00:04:56,355 So let's do that with a SuppressWarnings annotation. 75 00:04:58,550 --> 00:05:00,105 SuppressWarnings and 76 00:05:00,105 --> 00:05:05,960 we will suppress the unchecked assignment warning using the string unchecked. 77 00:05:06,995 --> 00:05:09,705 Excellent, the warning is now suppressed. 78 00:05:10,750 --> 00:05:12,440 Now, to put this to work. 79 00:05:12,440 --> 00:05:14,460 Let's go back up to the main method and 80 00:05:14,460 --> 00:05:18,310 display a list of contacts using its two-string method. 81 00:05:18,310 --> 00:05:26,750 So, here I'm going to display a list of contacts by using a for loop. 82 00:05:26,750 --> 00:05:29,330 So I'm going to iterate over all contacts 83 00:05:30,580 --> 00:05:33,980 that come back from the fetchAllContacts method. 84 00:05:33,980 --> 00:05:40,350 And in here, I'm simply going to use a System.out.println of c. 85 00:05:40,350 --> 00:05:44,780 Now, let's run the application again, to see our Contact objects displayed. 86 00:05:44,780 --> 00:05:46,940 So I'll right click here and choose Run. 87 00:05:48,220 --> 00:05:51,420 And you'll see a bunch of Hibernate output until finally we get 88 00:05:51,420 --> 00:05:54,050 to our applications output. 89 00:05:54,050 --> 00:05:58,835 And here are the results of our two-string method which show that we did 90 00:05:58,835 --> 00:06:04,570 indeed successfully persist that Contact object using our method. 91 00:06:04,570 --> 00:06:08,280 And successfully retrieved that list of contacts, 92 00:06:08,280 --> 00:06:12,730 even though there is only one, using Hibernate, excellent. 93 00:06:12,730 --> 00:06:17,300 Now you may wonder that after running this application a few times, 94 00:06:17,300 --> 00:06:22,780 why is it that you always get just one contact in your database? 95 00:06:22,780 --> 00:06:27,860 Each time I run it I still get just one contact in my database. 96 00:06:27,860 --> 00:06:31,898 You might be asking, doesn't the data continue to exist after exiting and 97 00:06:31,898 --> 00:06:33,910 re-running the application? 98 00:06:33,910 --> 00:06:37,800 After I run it a second time shouldn't there be two contacts in there? 99 00:06:37,800 --> 00:06:41,390 And a third time, shouldn't there be three contacts in there? 100 00:06:41,390 --> 00:06:44,460 The answer to those questions is, well, no. 101 00:06:44,460 --> 00:06:48,860 And that is because we told the HBM to DDL tool to create 102 00:06:48,860 --> 00:06:50,660 our database schema on startup. 103 00:06:50,660 --> 00:06:55,360 If we go back to that configuration file, we can remind ourselves that we set 104 00:06:55,360 --> 00:06:59,790 the HBM to DDL.autoproperty to create. 105 00:06:59,790 --> 00:07:04,780 That means that any previous data will be wiped out on application startup. 106 00:07:04,780 --> 00:07:11,090 And we can change that property value to update so that only database schema 107 00:07:11,090 --> 00:07:16,600 changes will be made instead of blowing away our whole schema and recreating. 108 00:07:16,600 --> 00:07:18,660 Let me update the comment here. 109 00:07:18,660 --> 00:07:20,740 Update the database schema on startup. 110 00:07:20,740 --> 00:07:25,710 So now, when we rerun the application, if Hibernate detects that there have been 111 00:07:25,710 --> 00:07:30,130 changes in the schema as indicated by our JPA annotations. 112 00:07:30,130 --> 00:07:35,800 The table or tables will be altered by the HBM to DDL 113 00:07:35,800 --> 00:07:41,420 tool without changing the data that exists in those tables. 114 00:07:41,420 --> 00:07:46,090 So, after making that change, let me stop the application. 115 00:07:46,090 --> 00:07:50,850 I will delete all the output in my terminal here and I will rerun. 116 00:07:50,850 --> 00:07:53,060 Let's see what kind of data we get now. 117 00:07:54,200 --> 00:07:57,400 There you have it, we have two contacts here. 118 00:07:57,400 --> 00:08:01,040 Of course, because our application code only specifies information for 119 00:08:01,040 --> 00:08:05,680 one contact, we'll continue getting the same info for each contact, but 120 00:08:05,680 --> 00:08:08,940 with one exception, the id here. 121 00:08:08,940 --> 00:08:13,360 In the second contact it's 2, in the first contact it's 1. 122 00:08:13,360 --> 00:08:17,050 Remember the id field is automatically generated, so 123 00:08:17,050 --> 00:08:21,810 that each contact has a unique id in the database. 124 00:08:21,810 --> 00:08:25,360 As a fun side note, if we switch back to application.java, 125 00:08:25,360 --> 00:08:29,420 we can use some of the new features offered by Java 8 to condense our code. 126 00:08:29,420 --> 00:08:32,200 Specifically, this code right here. 127 00:08:32,200 --> 00:08:36,330 This for each loop can be simplified by using what's called a stream, and 128 00:08:36,330 --> 00:08:39,430 on that stream we can call a method named, for each. 129 00:08:39,430 --> 00:08:43,820 Passing to it, a reference to the system.out classes static printlin method. 130 00:08:43,820 --> 00:08:45,490 Let me show you how that looks. 131 00:08:45,490 --> 00:08:52,110 We'll call the fetchAllContacts method and on that list we will create a Java stream. 132 00:08:52,110 --> 00:08:57,370 And here is where we can call this method named forEach, passing a method reference, 133 00:08:57,370 --> 00:09:00,930 which is new in Java 8, to the println. 134 00:09:00,930 --> 00:09:04,490 The system that out-classes static println method. 135 00:09:05,540 --> 00:09:09,490 And, after running this, you should see that we get the same output. 136 00:09:09,490 --> 00:09:14,105 Let me stop our previous run of the application, trash our output, and 137 00:09:14,105 --> 00:09:16,530 re-run it to see if we get the same output. 138 00:09:17,840 --> 00:09:19,650 Excellent, we do get the same output. 139 00:09:19,650 --> 00:09:23,200 And now we have three contacts, pretty sweet stuff. 140 00:09:23,200 --> 00:09:27,504 Check out the Teacher's Notes for some more features introduced in Java 8.