© Luciano Manelli and Giulio Zambon 2020
L. Manelli, G. ZambonBeginning Jakarta EE Web Developmenthttps://doi.org/10.1007/978-1-4842-5866-8_4

4. Databases

Luciano Manelli1  and Giulio Zambon2
(1)
Taranto, Italy
(2)
Harrison, ACT, Australia
 

In many cases, a web application is nothing more than a front end for a database (DB). In fact, what makes web pages dynamic is precisely the fact that there is a significant amount of data behind them. In this chapter you will learn to working with databases and SQL.

A database consists of organized data, that is, the data itself and a schema that provides data structures. Nowadays, most databases are organized in tables consisting of rows and columns. This is a natural way of organizing data, and you’re probably familiar with it through the use of spreadsheets. You can define the table characteristics independently of the actual data you’re going to store into it. This is another instance of the separation of formatting and content, which you’ve already encountered in Chapter 3, when we discussed web applications. For example, a table of employees would probably include columns named FirstName, LastName, and SocialSecurityNumber containing strings of text; columns named EmployeeNumber and YearSalary would contain numbers; and columns named DateOfBirth and EmployedSince would contain dates. The data associated with each employee would then all be stored into a row.

A field is an individual data item within a table, corresponding to the intersection of a row and a column. One or more columns can be specified as unique keys, used to identify each individual employee. For this purpose, you could use either one of the columns mentioned previously (e.g., EmployeeNumber) or the combination of first and last name and date of birth. The unique key used in preference over the others is called the primary key of a table.

An additional type of key is the foreign key. In this case, the column is defined as a reference to a unique key of another table. Besides avoiding duplication of data, this type of constraint increases the consistency of the database. For example, a table containing customer contracts could include a column referring to the column of employee numbers defined in the employee table. This would ensure that each contract would be associated with an existing salesperson.

Sometimes it’s useful to present only some columns and rows, as if they were a table in their own right. Such virtual tables are called views.

An important property is the transaction that represents a key concept in DBMSs in terms of concurrent access to the same tables and indicates a series of operations that have to be performed without interruption, that is, without any other operation “sneaking in” between them. A transaction is characterized by four properties—atomicity, consistency, isolation, and durability (ACID):
  • Atomicity: It guarantees that either all the individual steps of an operation are performed or none at all. You must not be able to perform partial transactions.

  • Consistency: It refers to the fact that a transaction is not supposed to violate the integrity of a database.

  • Isolation: It means that concurrent operations cannot see intermediate values of a transaction.

  • Durability: It refers to the capacity of a database to guarantee that a transaction, once completed, is never going to be “forgotten,” even after a system failure.

DBMS

A database management system (DBMS), such as MySQL, is a software package that lets you create, read, update, and delete (CRUD) both items of data and elements of the schema.

Therefore, when talking about a database, you need to distinguish between three aspects:
  • The data it contains

  • The structure you impose on the data in order to CRUD it efficiently

  • The software that allows you to manipulate both the data itself and the database structure (the DBMS)

Working with a database means that you’re interacting with its DBMS. You can do that through a command-line interface (CLI) , through graphical user interfaces (GUIs) provided by the DBMS vendor and third parties, or programmatically through an API.

The DBMS can build an index for each key, so that the data can be retrieved more quickly. This will obviously slow down insertion and deletion of rows (i.e., of new records), because the DBMS will have to spend time updating the indexes, but most databases are more frequently interrogated than modified. Therefore, it usually pays to define indexes, at least those that can speed up the most common queries.

In this chapter’s examples and in the book as Eshop database, I’ll use MySQL as the DBMS of choice, because, first, it’s available for free and, second, it’s the most widely used of the freely available DBMSs. As such, it has been proven to work reliably in all sorts of environments.

Structured Query Language

Structured Query Language (SQL) is the most widely used language to interact with DBMSs. Most DBMSs don’t support the whole SQL standard. Moreover, vendors sometimes add nonstandard elements that, in practice, prevent full portability across DBMSs. In general, regardless of whether we’re talking about database organization, table structure, or actual data, you’ll need to perform four CRUD operations. The corresponding SQL statements begin with a keyword that identifies the operation (e.g., INSERT, SELECT, UPDATE, or DELETE), followed when necessary by a keyword specifying on what type of entity the operation is to be performed (e.g., DATABASE, TABLE, or INDEX) and by additional elements. You use the SELECT statement for retrieving information.

You can create databases, tables, and indexes with the CREATE statement, update them with ALTER, and delete them with DROP. Similarly, you can create and delete views with CREATE and DROP, but you cannot update them once you’ve created them. You use INSERT to create new rows within a table, and you use DELETE to delete them. The UPDATE statement lets you modify entire rows or one or more individual fields within them.

The statements that let you modify the structures are collectively referred to as Data Definition Language (DDL), while those that let you modify the content are called Data Manipulation Language (DML).

In many applications, the structure of databases, tables, indexes, and views, once initially defined, remains unchanged. Therefore, you’ll often need within your applications only the statements operating on rows and fields. In any case, you’ll certainly need SELECT, which you use to interrogate databases both in terms of their structure and the data they contain. Finally, to complete the list of statements you’re likely to need when developing applications, there are START TRANSACTION, COMMIT, and ROLLBACK, which you need to use transactions.

When you want to retrieve, update, or delete rows, you obviously have to identify them. You do this with the WHERE keyword followed by a <where_condition>.

INSERT

INSERT stores one or more rows in an existing table or view. See Listing 4-1 for a description of its format.
INSERT INTO {tbl_name | view_name} [(col_name [, col_name ...])]
    {VALUES (<val> [, <val> ...]) | <select>};
    ;
<select> = A SELECT returning the values to be inserted into the new rows
Listing 4-1

The SQL Statement INSERT

You can use INSERT to create one row in a table (or a single-table view) from scratch or to create one or more rows by copying data from other tables.

UPDATE

UPDATE modifies the content of one or more existing rows in a table (or single-table view). See Listing 4-2 for a description of its format.
UPDATE {tbl_name | view_name} SET col_name = <val> [, col_name = <val> ...]
    [WHERE <where_condition>];
Listing 4-2

The SQL Statement UPDATE

DELETE

DELETE removes one or more rows from an existing table or a view that is not read-only. See Listing 4-3 for a description of its format.
DELETE FROM {tbl_name | view_name} [WHERE <where_condition>];
Listing 4-3

The SQL Statement DELETE

SELECT

In particular, SELECT (that can be used also to obtain the result of applying a function to the data) retrieves data from one or more tables and views.

Listing 4-4 shows how you use SELECT to obtain data.
SELECT [ALL | DISTINCT ] {* | <select_list>}
    [FROM <table_references> [WHERE <where_condition>]]
    [ORDER BY <order_list>]
    ;
<select_list> = col_name [, <select_list>]
<table_references> = one or more table and/or view names separated by commas
<order_list> = col_name [ASC | DESC] [, <order_list> ...]
Listing 4-4

SELECT to Obtain Data

Conceptually, it is simple: SELECT one, some, or all columns FROM one or more tables or views WHERE certain conditions are satisfied; then present the rows ORDERed as specified. Some examples will clarify the details:
  • SELECT * is the simplest possible SELECT, but you’ll probably never use it. It returns everything you have in your database.

  • SELECT * FROM table is the simplest practical form of SELECT. It returns all the data in the table you specify.

  • SELECT a_col_name, another_col_name FROM table still returns all the rows of a table, but for each row, it returns only the values in the columns you specify. Use the keyword DISTINCT to tell the DBMS that it should not return any duplicate row.

  • SELECT * FROM table WHERE condition only returns the rows for which the condition you specify is satisfied.

  • SELECT * FROM table ORDER BY col_name returns all the rows of a table ordered on the basis of a column you specify.

The SQL standard has been widely adopted, and, as a result, most of what I’m going to say concerning SQL actually applies to all DBMSs. As you can imagine, there are still proprietary additions and variations that, in some cases, make SQL less portable than what it could and should be, but it won’t affect us. The SQL standard specifies a lot of reserved words as keywords; therefore, it should be clear that in this chapter, I couldn’t possibly give you more than a small introduction to SQL and DBMS.

At last, to write comments in an SQL script, you enclose them between /* and */, like Java’s block comments.

Introducing eshop application

Now, in this section, I will introduce the eshop application, which will remain with us through the rest of the book.

The first thing is to create a simple database, which we will use in the eshop application you will encounter in the next chapter. It is important to emphasize on design of database, because a good design ensures elimination of data redundancy, consistent data, and high-performance application.

Taking an object-oriented approach, I’ll begin by specifying the objects that the application needs to handle, the operations which those objects support, and the roles of the people who perform those operations.

Each role corresponds to a separate user interface, and the two main roles are the administrator and the customer. The administrators manage products, orders, and customer records, but for our purposes, it is sufficient to implement the public interface of a customer buying from a catalog.

Entities and Operations

In eshop we won’t keep track of orders and customers. Once the customer goes to the checkout, enters credit-card information, and checks out, we’ll save the order, but we won’t do anything with it. In the real world, we’d have to process the purchase by charging the credit-card account and dispatching the order.

Product Categories

It makes sense to group the products into categories, especially if the catalog is diversified and substantial. As eshop only sells books, its categories refer to broad book subjects, such as Historical Mysteries, Science Fiction, and Web Development.

Each category has a name and an identifier. The identifier is guaranteed to be unique, thereby allowing us to refer to each category without ambiguity. Normally, a category would have additional attributes, like description, status, date of creation, and so on. To implement the customer interface, the only operation you need with such a bare-bones category definition is obtaining a category name given its ID.

Books

Each book has a title, an author, a price, a unique identifier, a category ID, and an image of the front cover. Customers must be able to select books from a category, search for books, display the book details, and put books into a shopping cart.

Shopping Cart

The minimum amount of information stored in a shopping cart is a list of items, each consisting of a book identifier and the number of ordered copies. I decided to duplicate in the shopping cart title, description, and price of the books instead of using their book IDs. Besides simplifying the application, this also protects the customer from book updates that might occur while he or she is still shopping. In a more sophisticated application, when some book attributes change, you might want to inform the customers who’ve placed the book in their cart but haven’t yet completed the checkout. You wouldn’t be able to do so without saving the original information. Obviously, this only avoids a problem due to concurrent access of data. To protect the information from more serious occurrences like server failures, you would have to implement more general solutions, like saving session data on non-volatile storage and server clustering.

Customers must be able to change the number of copies of each book in the cart, remove a book altogether, and go to the checkout. They should also be able to display the shopping cart at any time.

Order

Although this sample application doesn’t cover orders, it’s useful to specify the structure of an order. You need two separate classes: one to represent the ordered items and one with the customer’s data.

For each ordered item, you need to save the book data obtained from the shopping cart. Additionally, for each order, you need to save the customer data and a unique order number.

Creating MySQL Schema and Tables

Now we will create and populate our database. First, define the DB “shop”. Once we create the DB, it is possible to create the tables following from the entities discussed in previous section, which are
  • categories table

  • books table

  • orders table

  • order_details table

The logic design of the database is shown in the following tables (Table 4-1, Table 4-2, Table 4-3, and Table 4-4), characterized by name, length, type of data, and constraints (i.e., a field is a primary key and another must be not null).
Table 4-1

Categories Table

Field Name

Length

Type

Constraints

category_id

INT

Primary Key

Not null

Index

category_name

70

VARCHAR

Not Null

Table 4-2

Books Table

Field Name

Length

Type

Constraints

book_id

INT

Primary Key

Not null

Index

title

70

VARCHAR

Not Null

author

70

VARCHAR

price

DOUBLE

Not Null

category_id

INT

Foreign Key of categories table

Not null

Table 4-3

Orders Table

Field Name

Length

Type

Constraints

order_id

BIGINT

Primary Key

Not null

Index

delivery_name

70

VARCHAR

Not Null

delivery_address

70

VARCHAR

Not Null

cc_name

70

VARCHAR

Not Null

cc_number

32

VARCHAR

Not Null

cc_expiry

10

VARCHAR

Not Null

Table 4-4

Order_details Table

Field Name

Length

Type

Constraints

id

BIGINT

Primary Key

Not null

Index

book_id

INTEGER

Foreign Key of books table

Not null

title

70

VARCHAR

Not Null

author

70

VARCHAR

 

quantity

INT

Not Null

price

DOUBLE

Not Null

order_id

BIGINT

Foreign Key of categories table

Not null

The Index speeds up the search of an element in a table.

I use VARCHAR data type for cc_number and cc_expire to simplify controls for these fields. In an application ready for production, you should use a numeric data type for cc_number and date data type for cc_expire. Note that I used INT for book id and categories, while I used BIGINT for orders and order details, because I supposed a number of orders bigger than the books.

Listing 4-5 shows the SQL script for the creation of the ‘shop’ database.
01  DROP DATABASE IF EXISTS `shop`;
02  CREATE DATABASE `shop`;
03  CREATE TABLE `shop`.`categories` (
04  `category_id` int NOT NULL AUTO_INCREMENT,
05  `category_name` varchar(70) NOT NULL,
06  PRIMARY KEY (`category_id`),
07  KEY `category_id_key` (`category_id`)
08  );
09  CREATE TABLE `shop`.`books` (
10  `book_id` int NOT NULL AUTO_INCREMENT,
11  `title` varchar(70) NOT NULL,
12  `author` varchar(70) DEFAULT NULL,
13  `price` double NOT NULL,
14  `category_id` int NOT NULL,
15  PRIMARY KEY (`book_id`),
16  KEY `book_id_key` (`book_id`),
18  CONSTRAINT `category_id` FOREIGN KEY (`category_id`) REFERENCES `categories` (`category_id`)
19  );
20  CREATE TABLE `shop`.`orders` (
21  `order_id` bigint NOT NULL AUTO_INCREMENT,
22  `delivery_name` varchar(70) NOT NULL,
23  `delivery_address` varchar(70) NOT NULL,
24  `cc_name` varchar(70) NOT NULL,
25  `cc_number` varchar(32) NOT NULL,
26  `cc_expiry` varchar(20) NOT NULL,
27  PRIMARY KEY (`order_id`),
28  KEY `order_id_key` (`order_id`)
29  );
30  CREATE TABLE `order_details` (
31  `id` bigint NOT NULL AUTO_INCREMENT,
32  `book_id` int NOT NULL,
33  `title` varchar(70) NOT NULL,
34  `author` varchar(70) DEFAULT NULL,
35  `quantity` int NOT NULL,
36  `price` double NOT NULL,
37  `order_id` bigint NOT NULL,
38  PRIMARY KEY (`id`),
39  KEY `order_details_id_key` (`id`),
42  CONSTRAINT `book_id` FOREIGN KEY (`book_id`) REFERENCES `books` (`book_id`),
43  CONSTRAINT `order_id` FOREIGN KEY (`order_id`) REFERENCES `orders` (`order_id`)
44  );
Listing 4-5

shop_create.sql

Line 01 removes the database. The IF EXISTS option allows you to delete it only if it already exists. This option is used to prevent the reported error when you use the creation script the first time if the database does not exist. The DROP statement deletes the database and the physical disk files, so you should have a backup of the database if you want to restore it in the future.

Line 02 creates a blank database named shop.

Lines 03 to 08 create a table to store book categories.

Lines 09 to 19 create a table to store book records.

Lines 20 to 29 create a table to store book orders.

Lines 30 to 44 create a table to store book order_details.

Lines 06, 15, 27, and 38 set the primary keys in the tables.

Lines 18, 42, and 43 set the foreign keys in the tables.

To execute the SQL script, you can use the command-line client you see in Chapter 1. You will find the script in the software package for this chapter.

Open the command-line client. Open shop_create.sql with a text editor, copy everything, and paste it onto the command-line client. Listing 4-6 shows what you will get.
Enter password: ****
Welcome to the MySQL monitor.  Commands end with ; or g.
Your MySQL connection id is 334
Server version: 8.0.19 MySQL Community Server - GPL
Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
mysql> DROP DATABASE IF EXISTS `shop`;
Query OK, 4 rows affected (4.45 sec)
mysql> CREATE DATABASE `shop`;
Query OK, 1 row affected (0.18 sec)
mysql> CREATE TABLE `shop`.`categories` (
    ->   `category_id` int NOT NULL AUTO_INCREMENT,
    ->   `category_name` varchar(70) NOT NULL,
    ->   PRIMARY KEY (`category_id`),
    ->   KEY `category_id_key` (`category_id`)
    ->   );
Query OK, 0 rows affected (1.55 sec)
mysql> CREATE TABLE `shop`.`books` (
    ->   `book_id` int NOT NULL AUTO_INCREMENT,
    ->   `title` varchar(70) NOT NULL,
    ->   `author` varchar(70) DEFAULT NULL,
    ->   `price` double NOT NULL,
    ->   `category_id` int NOT NULL,
    ->   PRIMARY KEY (`book_id`),
    ->   KEY `book_id_key` (`book_id`),
    ->   CONSTRAINT `category_id` FOREIGN KEY (`category_id`) REFERENCES `categories` (`category_id`)
    -> );
Query OK, 0 rows affected (1.30 sec)
mysql> CREATE TABLE `shop`.`orders` (
    ->   `order_id` bigint NOT NULL AUTO_INCREMENT,
    ->   `delivery_name` varchar(70) NOT NULL,
    ->   `delivery_address` varchar(70) NOT NULL,
    ->   `cc_name` varchar(70) NOT NULL,
    ->   `cc_number` varchar(32) NOT NULL,
    ->   `cc_expiry` varchar(20) NOT NULL,
    ->   PRIMARY KEY (`order_id`),
    ->   KEY `order_id_key` (`order_id`)
    -> );
Query OK, 0 rows affected (1.54 sec)
mysql> CREATE TABLE `shop`.`order_details` (
    ->   `id` bigint NOT NULL AUTO_INCREMENT,
    ->   `book_id` int NOT NULL,
    ->   `title` varchar(70) NOT NULL,
    ->   `author` varchar(70) DEFAULT NULL,
    ->   `quantity` int NOT NULL,
    ->   `price` double NOT NULL,
    ->   `order_id` bigint NOT NULL,
    ->   PRIMARY KEY (`id`),
    ->   KEY `order_details_id_key` (`id`),
    ->   CONSTRAINT `book_id` FOREIGN KEY (`book_id`) REFERENCES `books` (`book_id`),
    ->   CONSTRAINT `order_id` FOREIGN KEY (`order_id`) REFERENCES `orders` (`order_id`)
    -> );
Query OK, 0 rows affected (1.51 sec)
mysql>
Listing 4-6

Log of shop_create.sql

Now that the database is in place, insert book categories and book records using the script shop_populate.sql by copying everything and pasting onto the console. The file is shown in Listing 4-7.
INSERT INTO `shop`.`categories` (`category_id`, `category_name`) VALUES ('1', 'Web Development');
INSERT INTO `shop`.`categories` (`category_id`, `category_name`) VALUES ('2', 'Science Fiction');
INSERT INTO `shop`.`categories` (`category_id`, `category_name`) VALUES ('3', 'Historical Mysteries');
INSERT INTO `shop`.`books` (`book_id`, `title`, `author`, `price`, `category_id`) VALUES ('1', 'MYSQL 8 Query Performance Tuning', 'Jesper Wisborg Krogh', '34.31', '1');
INSERT INTO `shop`.`books` (`book_id`, `title`, `author`, `price`, `category_id`) VALUES ('2', 'JavaScript Next', 'Raju Gandhi', '36.70', '1');
INSERT INTO `shop`.`books` (`book_id`, `title`, `author`, `price`, `category_id`) VALUES ('3', 'The Complete Robot', 'Isaac Asimov', '12.13', '2');
INSERT INTO `shop`.`books` (`book_id`, `title`, `author`, `price`, `category_id`) VALUES ('4', 'Foundation and Earth', 'Isaac Asimov', '11.07', '2');
INSERT INTO `shop`.`books` (`book_id`, `title`, `author`, `price`, `category_id`) VALUES ('5', 'The Da Vinci Code', 'Dan Brown', '7.99', '3');
INSERT INTO `shop`.`books` (`book_id`, `title`, `author`, `price`, `category_id`) VALUES ('6', 'A Column of Fire', 'Ken Follett', '6.99', '3');
Listing 4-7

shop_populate.sql

To execute the SQL script, you can also use the Workbench introduced in Chapter 1. The first thing is to launch Workbench and go to SCHEMAS tab. Now, as shown in Figure 4-1, right-click and select “Create Schema…” on the context menu. If the “shop” database exists, right-click it, select “Drop Schema…”, and delete it.
../images/309332_3_En_4_Chapter/309332_3_En_4_Fig1_HTML.jpg
Figure 4-1

MySQL workbench—how to create a new schema

Now create the Schema. Type “shop” in the name input and click “apply”, as shown in Figure 4-2.
../images/309332_3_En_4_Chapter/309332_3_En_4_Fig2_HTML.jpg
Figure 4-2

MySQL workbench—creating a new schema

Before applying, the tool asks for a confirmation. Figure 4-3 shows the final window that confirms the (correct) execution of the (and of every) script with its log.
../images/309332_3_En_4_Chapter/309332_3_En_4_Fig3_HTML.jpg
Figure 4-3

MySQL workbench—execution of a script

Now, as shown in Figure 4-4, right-click “Tables” label and select “Create Table…” in the context menu.
../images/309332_3_En_4_Chapter/309332_3_En_4_Fig4_HTML.jpg
Figure 4-4

MySQL workbench—how to create a new table

Type “categories” in the name input as shown in Figure 4-5.
../images/309332_3_En_4_Chapter/309332_3_En_4_Fig5_HTML.jpg
Figure 4-5

MySQL workbench—creating a new table

Now, in the “Columns” tab, type names and select types and constraints in the input columns as shown in Figure 4-6.
../images/309332_3_En_4_Chapter/309332_3_En_4_Fig6_HTML.jpg
Figure 4-6

MySQL workbench—creating columns in a table

Then, type the index “category_id_key” related to category_id in the “Indexes” tab as shown in Figure 4-7.
../images/309332_3_En_4_Chapter/309332_3_En_4_Fig7_HTML.jpg
Figure 4-7

MySQL workbench—creating a new index

At the end, click “apply” for applying SQL script to the database. Then, after a control, the script is executed. It is possible to create the other tables in this way.

Figure 4-8 shows how to create a foreign key (in this case, for books table): type the name “category_id”—related to categories table—in the “Foreign Keys” tab.
../images/309332_3_En_4_Chapter/309332_3_En_4_Fig8_HTML.jpg
Figure 4-8

MySQL workbench—creating a foreign key

You can continue creating the other tables with Workbench.

It is also possible to create the database with a script.

Copy the CREATE statement present in the shop_create.sql file into the Query section of the Workbench and execute it clicking the lightning icon. Figure 4-9 shows the output log.
../images/309332_3_En_4_Chapter/309332_3_En_4_Fig9_HTML.jpg
Figure 4-9

MySQL workbench—creating the shop database

Now that the database is in place, insert book categories and book records by using the MySQL Workbench, as shown in Figure 4-10. Select the table categories ➤, click the grid icon ➤, and insert category names and id in the new lines of the result grid (as in spreadshetets).
../images/309332_3_En_4_Chapter/309332_3_En_4_Fig10_HTML.jpg
Figure 4-10

Workbench—list of all categories

Do the same for books table. At last, the query “select * from books;” will list all the books you have inserted, as shown in Figure 4-11.
../images/309332_3_En_4_Chapter/309332_3_En_4_Fig11_HTML.jpg
Figure 4-11

List of all books

MySQL/Tomcat Test

First, you need to have the Java connector corresponding to the used database version and type that lead you to access programmatically. Therefore, as shown in Figure 4-12, go to https://dev.mysql.com/downloads/connector/j/ and download mysql-connector-java-8.0.20.zip. Ensure that the selected platform is “Platform Independent”: this is important for the distribution of the software on different systems.
../images/309332_3_En_4_Chapter/309332_3_En_4_Fig12_HTML.jpg
Figure 4-12

MySQL Connector download page

To install a JDBC, you can copy the JAR file in the lib folder of your web application, or better, you can copy its JAR file (mysql-connector-java-8.0.19.jar) into %CATALINA_HOME%lib. In the second case, you avoid an eventually memory lack of the server, while in the first case, you can use the application in different environments, without updating the lib folder of the servers.

To be sure that everything works, you still need to check that you can access the database from Tomcat using JSP. That is, the Tomcat is able to use the JDBC connector. To do so, you can use the JSP page shown in Listing 4-8, which lists all books in the database.
01    <%@page language="java" contentType="text/html"%>
02    <%@page import="java.sql.*"%>
03    <html><head><title>JDBC test</title></head><body>
04    <%
05      Class.forName("com.mysql.cj.jdbc.Driver");
06      Connection conn = DriverManager.getConnection(
07          "jdbc:mysql://localhost:3306/shop", "root", "root");
08      Statement stmt = conn.createStatement();
09      ResultSet rs = stmt.executeQuery("select * from books");
10      %><table border= "1"><%
11      ResultSetMetaData resMetaData = rs.getMetaData();
12      int nCols = resMetaData.getColumnCount();
13      %><tr><%
14      for (int kCol = 1; kCol <= nCols; kCol++) {
15        out.print("<td><b>" + resMetaData.getColumnName(kCol) + "</b></td>");
16        }
17      %></tr><%
18      while (rs.next()) {
19        %><tr><%
20        for (int kCol = 1; kCol <= nCols; kCol++) {
21          out.print("<td>" + rs.getString(kCol) + "</td>");
22          }
23        %></tr><%
24        }
25      %></table><%
26      conn.close();
27      %>
28    </body></html>
Listing 4-8

jdbc.jsp

Here is how jdbc.jsp obtains the list of books from the database and then displays them:
05:       Load JDBC to connect to the database server.
06–07:    Connect to the database.
08:       Create an empty statement to query the database.
09:       Execute the query to list all books and store the result set into a local variable.
11:       Obtain information on the structure of the result set.
12:       Obtain the number of columns of the result set.
13–17:    Display the column names.
18–23:    List the books one per row.
26:       Close the connection to the database server.

Don’t worry if things are not completely clear. Later in the next chapter, I will explain in detail how you access a database from Java. For the time being, I just want to give you an example of how you can test database connectivity with a simple JSP page.

To execute the page, create a simple web project “conn” as shown in Chapter 1: copy the code in a new jsp page and the jdbc driver in the lib directory. Figure 4-13 shows how the generated page appears in a web browser.
../images/309332_3_En_4_Chapter/309332_3_En_4_Fig13_HTML.jpg
Figure 4-13

jdbc.jsp output

In a more realistic situation, you would replace the category identifiers with the category names, but I want to keep this first example as simple as possible.

There is one thing, though, that deserves a comment: it is bad practice to hard-code in a page the name of the database, of the user ID, and of the access password. Sooner or later, you might need to change one of those parameters, and the last thing you want to do is to go through all your pages to do it. The initialization parameters exist precisely to avoid such error-prone procedure.

First, you need to include the parameter definitions in the web.xml file that’s inside the WEB-INF folder of your application’s root directory. You need to insert the lines shown in Listing 4-9 within the body of the web-app element.
<context-param>
  <param-name>dbName</param-name>
  <param-value>my-database-name</param-value>
  </context-param>
<context-param>
  <param-name>dbUser</param-name>
  <param-value>my-userID</param-value>
  </context-param>
<context-param>
  <param-name>dbPass</param-name>
  <param-value>my-password</param-value>
  </context-param>
Listing 4-9

web.xml Fragment to Define Initialization Parameters

In the example, my-database-name would be jdbc:mysql://localhost:3306/shop, and my-userID and my-password would be root.

To access the parameters from within any JSP page, you then just need to type something like the following:
String dbName = application.getInitParameter("dbName");
String dbUser = application.getInitParameter("dbUser");
String dbPass = application.getInitParameter("dbPass");
After that, you can replace lines 6 and 7 of the example with
Connection conn = DriverManager.getConnection(dbName, dbUser, dbPass);

You can modify the jdbc.jsp or create a new file (I created a new jdbcParam.jsp).

Database Architecture

In some cases, a database might contain a small amount of data, have a simple structure, and reside together with the application software on a home PC. In other cases, at the higher end of the scale, it might hold millions of records, have a data structure of great complexity, and run on a cluster of powerful servers.

In any case, regardless of size, environment, and complexity, the DBMS is organized around the client/server architecture. The system on which your DB resides is the server, and the system from which you need to access your DB is the client, even when they’re one and the same PC. Therefore, in order to be able to work with data and a data structure, you first have to establish a connection from the client to the database on the server. To be able to do so, you need the following three pieces of information:
  • The URL of your server

  • A user ID that allows you to access the DB

  • The password that goes together with the user ID

Once you establish the connection, you can then begin to manipulate the DB structure and its content via SQL statements. Be aware that although you need to provide a user ID and password when you connect to the server, this doesn’t automatically mean that a user has access to all databases on the same server. You can (and, in most cases, should) allow access to specific databases to some users and not others. In fact, you can define one or more new users for each new database you create and group them according to the capabilities they are required to have (i.e., database administrators, developers, etc.). This ensures total confidentiality of data when several users share a database server. It’s good practice to define different users for different applications so that you don’t risk “cross-polluting” data.

To design a web application for the created database, you basically associate each Java class to a table that represents the data you need to store permanently. Each column of your table then becomes an attribute of your class. In a sense, to express it in OO terminology, each row corresponds to an instantiation of your class containing different data. For example, the Java class shown in Listing 4-10 is modeled to reflect book categories.
package eshop.beans;
public class Category {
  private int id;
  private String name;
  public Category(int id, String name) {
    this.id = id;
    this.name = name;
    }
  public int getId() { return id; }
  public void setId(int id) { this.id = id; }
  public String getName() { return name; }
  public void setName(String name) { this.name = name; }
  }
Listing 4-10

Category.java

Accordingly, to store data in the shop database, you can use different SQL insert statements. Each SQL statement consists of a verb that defines the operation to be done, the identifier of the object operated on, and one or more operation parameters, often enclosed in parentheses. For example, use this code, which stores a new record in the database:
INSERT INTO `shop`.`categories` (`category_id`, `category_name`) VALUES ('3', 'Historical Mysteries');

Incidentally, be aware that SQL, contrary to Java, is not case-sensitive.

Use the powerful select SQL statement to read data. It lets you create complex queries that include sorting the data. Here’s a simple example:
SELECT category_id,category_name FROM shop.categories WHERE category_id=

To retrieve all columns of a table, you replace the comma-separated list of columns with an asterisk. The WHERE clause can consist of several conditions composed by means of logical operators.

You use the UPDATE statement to modify row contents:
UPDATE shop.categories SET category_name='Science Fiction'   WHERE category_id=2
Using DELETE, you can remove rows:
DELETE FROM shop.categories WHERE category_id > '3';
You can also operate on the data structure. To do so, you use the alter statement, as in the following example:
alter table categories add new_column_name column-definition;

This lets you add a column to an existing table. If you replace add with modify or drop, the alter statement will let you redefine a column or remove it.

In general, the SQL statements are grouped depending on their purposes. Table 4-5 gives you a summary of their classification.
Table 4-5

Classification of SQL Statements

Group

Description

Data Definition Language (DDL)

Statements used to define the DB structure (e.g., create, alter, drop, and rename)

Data Manipulation Language (DML)

Statements used to manage data (e.g., select, insert, update, and delete)

Data Control Language (DCL)

Statements used to control access to the data (e.g., grant, used to give access rights to a user, and revoke, used to withdraw them)

Transaction ControL (TCL)

Statements used to group together DML statements into logical transactions (e.g., commit and rollback)

In the next chapter, I’ll explain how to execute any SQL statement, but we’ll concentrate mainly on DML.

Summary

In this chapter, I introduced you to working with databases and SQL. Then I introduced you to Eshop application and I guided you to the design of its database and to its creation with MySQL tools. At last, I explained how to access databases from a simple JSP.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.154.208