OCP 8 Book Bonus: Creating a Derby Database in Java 8

While it is certainly possible to get all the JDBC questions on the exam without running any code or understanding any SQL, it is nice to be able to follow along. This blog post is meant to help anyone who has purchased our book, OCP: Oracle Certified Professional Java SE 8 Programmer II Study Guide: Exam 1Z0-809, download and run through the examples in the text. It also includes the database setup code so you can simply copy/paste it. The actual book covers what you need to know for the exam.


This blog post assumes you are reading chapter 10 of our OCP 8 book and have gotten up to the part that references this blog post.


Creating your initial database

Apache Derby is an open source database. It is really easy to use and comes with JDK 8. This means you don’t have to install anything special. You can even create and setup the database completely in Java. To start out, copy this code into a file named SetupDerbyDatabase.java.

import java.sql.*;

public class SetupDerbyDatabase {

   public static void main(String[] args) throws Exception {
      String url = "jdbc:derby:zoo;create=true";
      try (Connection conn = DriverManager.getConnection(url); 
           Statement stmt = conn.createStatement()) {
			
	   // stmt.executeUpdate("DROP TABLE animal");
	   // stmt.executeUpdate("DROP TABLE species");
			
	   stmt.executeUpdate("CREATE TABLE species ("
	        + "id INTEGER PRIMARY KEY, "
	 	+ "name VARCHAR(255), "
		+ "num_acres DECIMAL(4,1))");
		
	   stmt.executeUpdate("CREATE TABLE animal ("
		+ "id INTEGER PRIMARY KEY, "
		+ "species_id integer REFERENCES species (id), "
		+ "name VARCHAR(255), "
		+ "date_born TIMESTAMP)");

	   stmt.executeUpdate("INSERT INTO species VALUES (1, 'African Elephant', 7.5)");
   	   stmt.executeUpdate("INSERT INTO species VALUES (2, 'Zebra', 1.2)");

 	   stmt.executeUpdate("INSERT INTO animal VALUES (1, 1, 'Elsa', '2001-05-06 02:15:00')");
	   stmt.executeUpdate("INSERT INTO animal VALUES (2, 2, 'Zelda', '2002-08-15 09:12:00')");
	   stmt.executeUpdate("INSERT INTO animal VALUES (3, 1, 'Ester', '2002-09-09 10:36:00')");
	   stmt.executeUpdate("INSERT INTO animal VALUES (4, 1, 'Eddie', '2010-06-08 01:24:00')");
	   stmt.executeUpdate("INSERT INTO animal VALUES (5, 2, 'Zoe', '2005-11-12 03:44:00')");
			
	   ResultSet rs = stmt.executeQuery("select count(*) from animal");
	   rs.next();
	   System.out.println(rs.getInt(1));
      }
   }
}

Then compile as usual:

javac SetupDerbyDatabase.java

Running it is a bit different as you need to include the Derby jar file in your classpath. If you don’t know how to find it or encounter problems see the next sections of this blog post. Notice the classpath contains the following three things:

  1. The relative or absolute path of the Derby jar file
  2. A separator (semicolon on Windows, colon on Mac/Linux)
  3. A dot (which means the current directory)

For example, on my Mac either of these works:

java -cp "$JAVA_HOME/db/lib/derby.jar:." SetupDerbyDatabase
java -cp "/Library/Java/JavaVirtualMachines/jdk1.8.0_45.jdk/Contents/Home/db/lib/derby.jar:." SetupDerbyDatabase

If all goes well, the program will output the number 5.

Alternatively, you could have added Derby to your CLASSPATH environment variable and just run the program as

java SetupDerbyDatabase

How do I set up the classpath to run the Java program?

If you know where the JDK ($JAVA_HOME) is on your computer, you can start there and then look in the db/lib directory to find the derby.jar file. The most likely location for the JDK install is:

Operating System Most likely location
Windows c:\program files or c:\program files (x86)
Mac /Library/Java/JavaVirtualMachinges
Linux /usr

Or you can search for derby.jar to get the exact path. On Mac and Linux, the search command is:

find / -name derby.jar -print 2> /dev/null

What does this program actually do?

The main method starts out by obtaining a connection to the Derby database. It then creates a statement object so it can run updates. it would have been more efficient to use a PreparedStatement, but those aren’t on the exam. We aren’t taking user input here so there is no security risk with SQL Injection.

Then the code runs two SQL statements to create tables in the zoo database. The commands each include:

  • the table name – species and animal
  • the fields in each table along with their type. Integer is like a Java int. Decimal is like a Java double. Timestamp is like a Java LocalDateTime or old java Date. Varchar stands for variable character and is like a String. The variable length part means that the database doesn’t need to allocate space for all 255 characters and should only use the space for the actual length of the string. (This matters when you frequently update the field with values of different lengths)
  • the primary key for each table – this tells the database how to you uniquely identify each row

Then the code runs seven SQL statements to insert rows into these tables. The order of the data matches the order the fields were defined in the create statements.

Finally, the code runs a query to check the rows were added to the database. The count(*) function in SQL always returns a number. For an empty table, this number is zero. Therefore, we can call rs.next() outside of a conditional or loop. We know there is always a number being returned.

Derby will create a “zoo” directory and a derby.log file in whatever directory you ran the program in. The zoo directory is your database.

Frequently Encountered Problems

If you have an error that isn’t here or have trouble with these instructions, feel free to ask a question in the CodeRanch forums

Error #1 – Derby is not in your classpath or points to an invalid location

Exact error message:

Exception in thread "main" java.sql.SQLException: No suitable driver found for jdbc:derby:zoo;create=true

at java.sql.DriverManager.getConnection(DriverManager.java:689)

at java.sql.DriverManager.getConnection(DriverManager.java:270)

at derby.SetupDerbyDatabase.main(SetupDerbyDatabase.java:9)

Solution:

Check you are actually pointing to Derby in your classpath. Also check your classpath has the three required components

Error #2 – The current directory is not in your classpath

Exact error message:

Could not find or load main class derby.SetupDerbyDatabase

Solution:

Check you have the current directory (dot) in your classpath. Also, check you have the correct separator for your operating system (semicolon for Windows, colon for Mac/Linux).

Error #3 – The tables already exist

Exact error message:


Exception in thread "main" java.sql.SQLException: Table/View 'SPECIES' already exists in Schema 'APP'.

at org.apache.derby.impl.jdbc.SQLExceptionFactory40.getSQLException(Unknown Source)

at org.apache.derby.impl.jdbc.Util.generateCsSQLException(Unknown Source)

Solution:

The program can only be run once as is. If you want to run it again, uncomment the two “drop table” lines.

I can’t find derby.jar in my Java install directory?

Make sure you are looking at your JDK and not a JRE. The JRE has less things included. For example, it doesn’t have the javac command. And it doesn’t have Derby.

comparing strings with compareTo

Thinking about using our OCA 8 book to study for the Java Foundations Junior Associate exam? It covers most of the topics. See what other topics you need to learn and where to read about that. One of those topics is comparing two Strings using compareTo(). Luckily there are only two things you need to know.

What does compareTo() return.

Scenario Result
The two Strings are equal 0
The first String sorts earlier alphabetically  a negative number
The first String sorts later alphabetically a positive number

Let’s look at some examples:

String first = "abc";
String second = "def";
System.out.println(first.equals(first));  // true
System.out.println(first.compareTo(first)); // 0

System.out.println(first.equals(second));  // false
System.out.println(first.compareTo(second)); // -3
System.out.println(second.compareTo(first)); // 3

Don’t worry. You don’t have to know the answer is -3. You just have to know that it is negative or positive or zero.

How is alphabetically defined?
For the exam, you need to know that numbers sort before letters and uppercase sorts before lowercase. What do you think the output of this code is?

public class PlayTest {

	public static void main(String[] args) {

		String nums = "123";
		String uppercase = "ABC";
		String lowercase = "abc";
		printComparison(nums, nums);
		printComparison(nums, uppercase);
		printComparison(nums, lowercase);
		System.out.println();
		printComparison(uppercase, nums);
		printComparison(uppercase, uppercase);
		printComparison(uppercase, lowercase);
		System.out.println();
		printComparison(lowercase, nums);
		printComparison(lowercase, uppercase);
		printComparison(lowercase, lowercase);
	}

	private static void printComparison(String one, String two) {
		int result = one.compareTo(two);
		if (result == 0) {
			System.out.println("0");
		} else if (result < 0) {
			System.out.println("negative");
		} else {
			System.out.println("positive");
		}
	}

The answer is:

0
negative
negative

positive
0
negative

positive
positive
0

Make sure you can fill this in by yourself. You should also know the space sorts before letters. For example, printComparison(“ABC”, “A C”); prints out a positive number.

Summary

There’s not much you have to memorize. The key facts are:

  • The method name is compareTo()
  • Numbers sort before capital letters which sort before lowercase letters
  • Spaces sort before letters

Practice Questions

Question 1

What does the following output? (Choose all that apply)

String first = "MOO";
String second = "moo";
System.out.println(first.compareTo(second));
System.out.println(first.equals(second));

A: A negative number

B: Zero

C: A positive number

D: true

E: false

F: none of the above

Question 2

What does the following output? (Choose all that apply)

String first = "moo";
String second = " moo";
System.out.println(first.compareTo(second));
System.out.println(first.equals(second));

A: A negative number

B: Zero

C: A positive number

D: true

E: false

F: none of the above

Question 3

What does the following output? (Choose all that apply)

String first = "MOO";
String second = "MOO";
System.out.println(first.compareTo(second));
System.out.println(first.equals(second));

A: A negative number

B: Zero

C: A positive number

D: true

E: false

F: none of the above

Question 4

What does the following output? (Choose all that apply)

String first = "moo";
String second = "MOO";
System.out.println(first.compare(second));
System.out.println(first.equals(second));

A: A negative number

B: Zero

C: A positive number

D: true

E: false

F: none of the above

Question 5

What does the following output? (Choose all that apply)

String first = "MOO";
String second = "1";
System.out.println(first.compareTo(second));
System.out.println(first.equals(second));

A: A negative number

B: Zero

C: A positive number

D: true

E: false

F: none of the above

The answers are posted here.

using iterators in java

Thinking about using our OCA 8 book to study for the Java Foundations Junior Associate exam? It covers most of the topics. See what other topics you need to learn and where to read about that. One of those topics is iterating through a list.

Since Java 5, the most common way to iterate though a list (if you don’t need the loop index) is:

List<String>  list = Arrays.asList("sheep", "deer", "rat");
for (String name : list) {
   System.out.println(name);
}

Before Java 5 came along, there was another way:

List list = Arrays.asList("sheep", "deer", "rat");
 Iterator it = list.iterator();
 while (it.hasNext()) {
   String name = (String) it.next();
   System.out.println(name);
 }

But we are told to use generics in new code which would give us:

List<String> list = Arrays.asList("sheep", "deer", "rat");
 Iterator<String> it = list.iterator();
 while (it.hasNext()) {
   String name = it.next();
   System.out.println(name);
 }

Why would you do this? Shrug. For reading old code I guess. But it is on the test so no time like the present to learn this idiom. See what is wrong here?

// DOES NOT COMPILE
 List<String> list = Arrays.asList("sheep", "deer", "rat");
 Iterator<String> it = list.iterator();
 while (it.next()) {
   String name = it.hasNext();
   System.out.println(name);
 }

This one reverses the order of hasNext/next. Remember that you have to check that the iterator has a next element before getting it. Now what do you think is the problem with this?

// BAD
 List<String> list = Arrays.asList("sheep", "deer", "rat");
 Iterator<String> it = list.iterator();
 System.out.println(it.next());

If the list is empty, this code throws an exception. Probably not what you had in mind. Instead, you should write:


 List<String> list = Arrays.asList("sheep", "deer", "rat");
 Iterator<String> it = list.iterator();
 if (it.hasNext()) System.out.println(it.next());

Summary

There’s not much you have to memorize. The key facts are:

  • Call hasNext() in an if statement or while loop
  • Call next() once you know there is a next element
  • If the Iterator doesn’t use generics, you must cast unless you want Object

Practice Questions

Question 1

Which correctly fill in the blanks?


 List<String> list = Arrays.asList("a", "b", "c");
 Iterator<String> it = list.iterator();
 while (it._____()) {
   String name = it.______();
   System.out.println(name);
 }

A: hasNext, next

B: next, hasNext

C: The code does not compile with either A or B

D: The code throws an exception after being completed with A or B

Question 2

Which correctly fill in the blanks?


 List<String> list = Arrays.asList("a", "b", "c");
 Iterator it = list.iterator();
 while (it._____()) {
   String name = it.______();
   System.out.println(name);
 }

A: hasNext, next

B: next, hasNext

C: The code does not compile with either A or B

D: The code throws an exception after being completed with A or B

Question 3

Which correctly fill in the blanks?


 List list = Arrays.asList("a", "b", "c");
 Iterator<String> it = list.iterator();
 while (it._____()) {
   String name = it.______();
   System.out.println(name);
 }

A: hasNext, next

B: next, hasNext

C: The code does not compile with either A or B

D: The code throws an exception after being completed with A or B

The answers are posted here.