Advanced Java (Multithreading, Collections, JDBC)

Chapter 12
JDBC Architecture and Database Connectivity

Diploma in Programming Languages (Java & Python)
Advanced Java (Multithreading, Collections, JDBC)   •   Diploma

JDBC Architecture and Database Connectivity

Introduction

Most useful software systems store information beyond the lifetime of a single program execution. Student records, orders, payments, inventory, authentication data, and reports are commonly managed by relational database management systems (RDBMSs). Java Database Connectivity (JDBC) is the standard Java API for connecting to relational databases, sending SQL statements, processing results, and managing database resources.

JDBC is not itself a database and does not replace SQL. It provides a consistent programming interface between Java applications and database-specific drivers. A Java application can therefore communicate with PostgreSQL, MySQL, Oracle Database, Microsoft SQL Server, and other systems using broadly similar Java code, although the database URL, driver dependency, SQL dialect, and configuration may differ.

JDBC remains important even when applications use higher-level technologies such as Jakarta Persistence, Spring Data, or object-relational mapping frameworks. Those frameworks ultimately depend on database connectivity, transactions, SQL execution, and resource management. A sound understanding of JDBC is therefore foundational for diagnosing performance problems, connection failures, transaction errors, and SQL-related security weaknesses.

Learning Objectives

After completing this chapter, the learner should be able to:

  • explain the layered architecture of JDBC;
  • distinguish the principal JDBC driver types and select an appropriate driver;
  • describe the roles of the JDBC API, driver, DriverManager, DataSource, Connection, Statement, PreparedStatement, CallableStatement, and ResultSet;
  • construct and interpret database URLs;
  • execute queries and updates safely using parameterized SQL;
  • explain SQL fundamentals relevant to JDBC programming;
  • manage connections, statements, result sets, and transactions;
  • apply try-with-resources correctly;
  • identify common portability, security, and performance problems; and
  • design a small, maintainable JDBC data-access component.

1. The JDBC Programming Model

JDBC follows a layered model. Application code calls interfaces in the java.sql and javax.sql packages. A JDBC driver implements the database-specific communication required by those interfaces. The driver translates JDBC operations into the protocol understood by the target database.

The principal flow is:

  1. The application obtains a connection.
  2. It creates a statement object.
  3. It binds input values, if required.
  4. It sends SQL to the database.
  5. The database parses and executes the SQL.
  6. The application reads a ResultSet or an update count.
  7. The application commits or rolls back the transaction.
  8. JDBC resources are closed.

The JDBC API is based mainly on interfaces rather than concrete implementation classes. This separation allows the same application design to work with different database vendors.

A simplified architecture is:

Java application → JDBC API → JDBC driver → database protocol → RDBMS

The application should normally depend on JDBC interfaces such as Connection and PreparedStatement, not on vendor-specific implementation classes. This improves portability and testability.

2. Core JDBC Components

JDBC API

The JDBC API consists primarily of interfaces, classes, and exceptions in java.sql and javax.sql. Important types include:

TypeMain responsibility
DriverConnects JDBC to a particular database implementation
DriverManagerSelects a suitable registered driver and creates connections
DataSourceProvides connections, often with pooling and configuration support
ConnectionRepresents a session with a database
StatementExecutes static SQL text
PreparedStatementExecutes parameterized, precompiled SQL
CallableStatementInvokes stored procedures or functions
ResultSetRepresents rows returned by a query
SQLExceptionReports database and JDBC errors
DatabaseMetaDataDescribes database and driver capabilities
ResultSetMetaDataDescribes columns in a result set

Connection

A Connection represents an active logical session with a database. It is used to create statements, control transactions, inspect metadata, and configure properties such as auto-commit and isolation level.

A connection is not merely a lightweight object. It may represent a network socket, server-side session, authentication state, transaction state, and allocated database resources. Connections must therefore be closed promptly. In production systems, a DataSource may return a pooled connection; closing it usually returns the connection to the pool rather than physically terminating the database session.

Statement and Its Variants

Statement is appropriate for SQL that contains no externally supplied values and does not need repeated parameter binding. For example:

try (Statement statement = connection.createStatement()) {
    statement.executeUpdate("CREATE TABLE audit_log (id INT, message VARCHAR(200))");
}

PreparedStatement is preferred for values supplied at runtime:

String sql = "SELECT id, name FROM student WHERE programme = ?";
try (PreparedStatement statement = connection.prepareStatement(sql)) {
    statement.setString(1, "Programming");
    try (ResultSet results = statement.executeQuery()) {
        while (results.next()) {
            System.out.println(results.getInt("id") + " "
                    + results.getString("name"));
        }
    }
}

Question-mark placeholders are indexed from 1, not 0. A PreparedStatement helps prevent SQL injection because values are transmitted as data rather than concatenated into SQL syntax. It can also improve performance when the same statement is executed repeatedly, although the exact preparation and caching behavior depends on the driver and database.

CallableStatement is used for database procedures and functions. Its syntax and parameter behavior vary by database vendor, so portability must be considered.

ResultSet

A ResultSet is a cursor over rows returned by a query. Initially, the cursor is positioned before the first row. Calling next() advances it and returns true if a row is available.

while (results.next()) {
    long id = results.getLong("id");
    String name = results.getString("name");
}

Column labels are often more maintainable than numeric indexes. A ResultSet also has metadata, null handling, and cursor characteristics. A SQL NULL is not the same as Java null, zero, or an empty string. After reading a primitive value, methods such as wasNull() may be used when the distinction matters.

3. JDBC Driver Types

Historically, JDBC drivers have been classified into four types.

TypeDescriptionCurrent relevance
Type 1JDBC-to-ODBC bridgeObsolete and removed from modern Java distributions
Type 2Partly Java; uses native database client librariesRequires platform-specific native installation
Type 3Pure Java client communicating with middlewareUncommon today
Type 4Pure Java driver communicating directly with the database protocolDominant modern approach

Type 4 drivers are generally preferred because they are platform-independent, require no native client library, and are deployable with ordinary Java dependencies. A driver is not automatically suitable merely because it is Type 4. It should also support the required Java version, database version, security features, SQL behavior, and operational environment.

Modern JDBC drivers commonly register themselves through the Java Service Provider mechanism. Consequently, explicit calls such as Class.forName("...") are usually unnecessary when the driver dependency is correctly included. Explicit loading may still appear in legacy code or special class-loader environments.

4. Database URLs and DriverManager

A JDBC URL identifies the target database and may include configuration properties. The broad form is:

jdbc:<subprotocol>:<subname>

Examples include:

jdbc:postgresql://localhost:5432/college
jdbc:mysql://localhost:3306/college
jdbc:sqlserver://localhost:1433;databaseName=college

The exact grammar is vendor-specific. A URL may identify a host, port, database or service name, and connection properties such as encryption or timeouts. Credentials should not normally be placed in source-controlled URLs.

DriverManager is a basic connection factory. A simple connection can be obtained as follows:

String url = "jdbc:postgresql://localhost:5432/college";
String user = System.getenv("DB_USER");
String password = System.getenv("DB_PASSWORD");

try (Connection connection = DriverManager.getConnection(url, user, password)) {
    System.out.println("Connected: " + !connection.isClosed());
}

DriverManager examines registered drivers and asks an appropriate driver to create the connection. It is convenient for teaching, command-line tools, and small applications. It is less suitable as the central connection-management strategy for a large server application because it does not itself provide connection pooling, centralized lifecycle management, health checks, or sophisticated configuration.

5. DataSource and Connection Pooling

DataSource is the preferred abstraction for managed applications. It represents a source of database connections and may be configured by an application server, framework, or connection-pool library.

DataSource dataSource = obtainConfiguredDataSource();

try (Connection connection = dataSource.getConnection()) {
    // use the connection
}

A connection pool maintains a set of established or reusable connections. When application code closes a pooled connection, the pool usually resets its state and makes it available to another request. Pooling reduces the repeated cost of network connection establishment, authentication, and session initialization. It does not eliminate the need to close connections; failure to close them can exhaust the pool.

Important pool settings include maximum pool size, minimum idle connections, connection timeout, idle timeout, maximum lifetime, validation behavior, and leak detection. These settings must reflect workload and database capacity. A larger pool is not automatically faster: too many concurrent database sessions can cause contention, memory pressure, lock waits, or CPU saturation.

6. SQL Fundamentals for JDBC Developers

JDBC sends SQL to a relational database. Developers therefore need a practical understanding of SQL categories.

CategoryExamplesPurpose
DDLCREATE, ALTER, DROPDefines database structures
DMLINSERT, UPDATE, DELETEChanges stored data
DQLSELECTRetrieves data
DCLGRANT, REVOKEControls privileges
Transaction controlCOMMIT, ROLLBACKControls transaction boundaries

A relational table consists of rows and columns. A primary key identifies a row. Foreign keys represent relationships between tables and enforce referential integrity when configured. Constraints such as NOT NULL, UNIQUE, CHECK, and foreign-key constraints protect data quality at the database boundary.

A basic query may contain clauses in the logical structure:

SELECT column_list
FROM table_expression
WHERE condition
GROUP BY grouping_columns
HAVING group_condition
ORDER BY ordering_columns;

WHERE filters rows before grouping. HAVING filters groups after aggregation. ORDER BY controls presentation order; without it, row order is not guaranteed. Joins combine related rows, while aggregate functions such as COUNT, SUM, AVG, MIN, and MAX summarize data.

SQL uses three-valued logic involving TRUE, FALSE, and UNKNOWN, particularly when NULL is involved. For example, column = NULL is not the correct test for missing data; column IS NULL must be used.

7. Executing SQL

The principal execution methods are:

  • executeQuery() for statements expected to return a ResultSet;
  • executeUpdate() for INSERT, UPDATE, DELETE, and many DDL statements, returning an update count; and
  • execute() when the result form may vary or multiple result forms must be processed.

An insert can be written as follows:

String sql = "INSERT INTO student (student_number, name, programme) "
        + "VALUES (?, ?, ?)";

try (PreparedStatement statement = connection.prepareStatement(sql)) {
    statement.setString(1, "S1007");
    statement.setString(2, "Amina Patel");
    statement.setString(3, "Programming");
    int affected = statement.executeUpdate();
    System.out.println("Rows inserted: " + affected);
}

For generated keys, request them when preparing the statement and then read the returned key result set. The exact generated-key behavior depends on database support and schema configuration.

Batch processing allows multiple similar changes to be submitted together:

String sql = "UPDATE stock SET quantity = ? WHERE product_id = ?";
try (PreparedStatement statement = connection.prepareStatement(sql)) {
    for (StockChange change : changes) {
        statement.setInt(1, change.quantity());
        statement.setLong(2, change.productId());
        statement.addBatch();
    }
    int[] counts = statement.executeBatch();
}

Batch execution can reduce network round trips, but batch size, generated keys, error handling, and transaction behavior must be tested with the chosen driver.

8. Transactions and Consistency

A transaction is a logical unit of work that should satisfy the database's consistency rules. JDBC connections use auto-commit mode by default in many configurations. In auto-commit mode, each successful statement is committed as an individual transaction.

For a multi-step operation, disable auto-commit, perform all required statements, and commit only if every step succeeds:

try (Connection connection = dataSource.getConnection()) {
    connection.setAutoCommit(false);
    try {
        // execute related statements
        connection.commit();
    } catch (SQLException failure) {
        connection.rollback();
        throw failure;
    } finally {
        connection.setAutoCommit(true);
    }
}

The finally reset is particularly important with pooled connections, because the next borrower must not inherit disabled auto-commit or other altered state.

Transaction isolation controls how one transaction can observe changes made by other transactions. JDBC defines constants such as TRANSACTION_READ_UNCOMMITTED, TRANSACTION_READ_COMMITTED, TRANSACTION_REPEATABLE_READ, and TRANSACTION_SERIALIZABLE. Actual guarantees and supported levels vary by database system. Stronger isolation can reduce anomalies but may increase locking, waiting, or serialization failures.

Applications should keep transactions short, avoid user interaction inside a transaction, and define retry policies carefully for transient deadlocks or serialization failures.

9. Resource Management and try-with-resources

Database resources are external resources and must be closed even when an exception occurs. Connection, Statement, PreparedStatement, CallableStatement, and ResultSet implement AutoCloseable or a related closeable contract.

The preferred pattern is try-with-resources:

String sql = "SELECT id, name FROM student WHERE programme = ?";

try (Connection connection = dataSource.getConnection();
     PreparedStatement statement = connection.prepareStatement(sql)) {

    statement.setString(1, "Programming");

    try (ResultSet results = statement.executeQuery()) {
        while (results.next()) {
            System.out.println(results.getLong("id"));
        }
    }
}

Resources are closed automatically in the reverse order of declaration. If the body throws an exception and closing also throws one, Java preserves the closing exception as a suppressed exception. This is safer and clearer than manually closing resources in nested finally blocks.

A common error is to return a ResultSet from a method after closing its connection. The result set is then invalid or driver-dependent. Prefer mapping rows to domain objects inside the resource scope and returning a collection of those objects.

10. Exceptions and Error Handling

SQLException provides an error message, SQL state, vendor-specific error code, and possibly a chain of related exceptions. Error handling should distinguish recoverable conditions from programming or configuration errors.

Examples of useful categories include:

  • invalid SQL or schema mismatch;
  • authentication or authorization failure;
  • network interruption;
  • constraint violation;
  • transaction deadlock or serialization failure;
  • connection-pool exhaustion; and
  • timeout.

Applications should log sufficient diagnostic context without exposing passwords, tokens, or sensitive personal data. SQL statements may be logged in a redacted or parameter-safe form. Low-level database exceptions can be translated into application-specific exceptions, but the original cause should be retained for diagnosis.

Do not catch SQLException and silently continue. A failed update that is ignored can produce inconsistent application state. Conversely, retrying every database exception may duplicate writes or hide permanent failures. Retrying should be limited to well-understood transient conditions and should respect transaction idempotency.

11. A Complete Data-Access Example

The following illustrative repository reads students from a database. It uses constructor-injected DataSource, parameterized SQL, row mapping, and try-with-resources.

public final class StudentRepository {
    private final DataSource dataSource;

    public StudentRepository(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public List<Student> findByProgramme(String programme) throws SQLException {
        String sql = "SELECT id, student_number, name, programme "
                   + "FROM student WHERE programme = ? ORDER BY name";
        List<Student> students = new ArrayList<>();

        try (Connection connection = dataSource.getConnection();
             PreparedStatement statement = connection.prepareStatement(sql)) {
            statement.setString(1, programme);
            try (ResultSet results = statement.executeQuery()) {
                while (results.next()) {
                    students.add(new Student(
                            results.getLong("id"),
                            results.getString("student_number"),
                            results.getString("name"),
                            results.getString("programme")));
                }
            }
        }
        return students;
    }
}

This design has several strengths: database configuration is external to the repository, values are bound rather than concatenated, resources have clear lifetimes, and database rows are converted before the connection is released. In a larger application, a service layer would coordinate repositories and transactions, while the repository would focus on persistence operations.

12. Applied Case: College Enrolment Transfer

Background

A college system records enrolments in a table containing a student identifier, module identifier, and enrolment status. A registrar needs to move a student from one module to another. Both operations must succeed together.

Problem

An early implementation executes a deletion and insertion in auto-commit mode. If the insertion fails because the destination module is full, the student has already been removed from the original module. The database now reflects an incomplete business operation.

Analysis

The two statements form one logical unit of work. They require an explicit transaction and appropriate constraint handling. The application must also ensure that the student is authorized to make the change and that the destination module is available.

Approach

String remove = "DELETE FROM enrolment "
              + "WHERE student_id = ? AND module_id = ?";
String add = "INSERT INTO enrolment (student_id, module_id, status) "
           + "VALUES (?, ?, ?)";

try (Connection connection = dataSource.getConnection()) {
    connection.setAutoCommit(false);
    try (PreparedStatement removeStatement = connection.prepareStatement(remove);
         PreparedStatement addStatement = connection.prepareStatement(add)) {

        removeStatement.setLong(1, studentId);
        removeStatement.setLong(2, oldModuleId);
        int removed = removeStatement.executeUpdate();
        if (removed != 1) {
            throw new SQLException("Expected one existing enrolment");
        }

        addStatement.setLong(1, studentId);
        addStatement.setLong(2, newModuleId);
        addStatement.setString(3, "ACTIVE");
        addStatement.executeUpdate();

        connection.commit();
    } catch (SQLException failure) {
        connection.rollback();
        throw failure;
    } finally {
        connection.setAutoCommit(true);
    }
}

Outcome

If either statement fails, the rollback restores the original state. If both succeed, the commit makes the transfer durable as one operation. In a production system, the design would additionally consider concurrency, module-capacity locking, authorization, audit records, and retry behavior.

Learning Points

The case demonstrates that connection acquisition, parameter binding, transaction boundaries, row-count validation, rollback, and resource closure are interdependent responsibilities. Correct JDBC code is not simply code that executes SQL; it preserves application and database invariants.

13. Security, Governance, and Professional Practice

SQL injection is one of the most important JDBC security risks. It occurs when untrusted input becomes part of SQL syntax. Parameterized statements are the primary defense for values. Allow-list validation is also required when users influence identifiers such as column names, sort directions, or table names, because placeholders cannot represent arbitrary SQL identifiers.

Database accounts should follow least privilege. An application that only reads student data should not have permission to drop tables or modify unrelated financial records. Credentials should be stored in a secret manager or protected deployment configuration, not committed to source control.

Transport encryption should be enabled where supported, and certificates should be validated rather than bypassed. Sensitive data should not be unnecessarily selected, logged, cached, or returned to clients. Audit requirements may require recording who performed changes, when, and under which authorization context.

Privacy regulations and institutional policies may govern student, health, financial, or identity data. JDBC developers must therefore consider data minimization, retention, access control, masking, and secure disposal in addition to code correctness.

14. Performance and Portability Considerations

Performance depends on the whole path from application to database. Important practices include:

  • select only required columns rather than using unrestricted SELECT *;
  • index columns used frequently in joins, filters, and ordering, based on measured workload;
  • use PreparedStatement and batches appropriately;
  • avoid holding connections while performing slow non-database work;
  • stream or paginate large result sets where suitable;
  • configure timeouts rather than allowing indefinite waits;
  • monitor pool usage, query latency, lock waits, and failure rates; and
  • inspect execution plans for expensive queries.

Portability has limits. SQL dialects differ in pagination syntax, generated keys, date functions, data types, locking clauses, stored procedures, and transaction behavior. JDBC standardizes the Java interface, not all SQL semantics. Vendor-specific features should be isolated behind clear boundaries and tested against the actual target database.

JDBC 4.2 and later support modern Java temporal types in appropriate drivers, but mappings for database-specific types may still vary. Applications should test time zones, precision, nullability, and character encoding explicitly.

15. Contemporary Development Practices

Many modern Java systems use a framework or persistence abstraction rather than hand-written JDBC everywhere. Such abstractions can provide transaction management, connection pooling, mapping, migrations, and observability. Nevertheless, JDBC remains the underlying execution model and is often used directly for reporting, high-performance queries, batch operations, and specialized integrations.

Database migration tools help version schema changes. Observability systems can measure connection acquisition time, query duration, result size, and transaction outcomes. Static analysis and code review can detect string-concatenated SQL, leaked resources, and unsafe exception handling. AI-assisted coding tools may generate JDBC code, but generated code must be reviewed for injection vulnerabilities, incorrect transaction boundaries, credential exposure, and incompatible SQL assumptions.

A professional development process combines automated tests, integration tests against a realistic database, migration testing, failure injection, security review, and production monitoring. Mocking JDBC interfaces alone is insufficient for discovering SQL dialect, constraint, transaction, and performance problems.

Challenges and Limitations

JDBC provides a powerful common interface, but it does not remove database complexity. Drivers differ in feature support and behavior. SQL remains dialect-sensitive. Connection pools can be misconfigured. Transactions can deadlock or fail under concurrency. Large result sets can consume memory, and careless logging can expose sensitive values. Finally, low-level JDBC code can become repetitive when mapping many tables and relationships.

These limitations do not make JDBC unsuitable. They indicate where design discipline is needed: isolate persistence code, test with the real database, use explicit transaction policies, measure performance, apply least privilege, and document vendor-specific behavior.

Chapter Summary

JDBC is Java's standard API for relational database connectivity. Its architecture separates application code from database-specific drivers and protocols. Modern applications generally use Type 4 drivers, obtain connections through DataSource, and use DriverManager mainly for simple or controlled environments.

Connection represents a database session; statements execute SQL; PreparedStatement safely binds values; ResultSet exposes query rows; and SQLException reports failures. SQL knowledge is essential because JDBC transports and executes SQL rather than replacing it. Correct programs use parameterized statements, explicit transaction boundaries for multi-step work, appropriate isolation, least-privilege credentials, and careful error handling.

Try-with-resources is the standard mechanism for closing connections, statements, and result sets. Connection pooling improves efficiency but makes reliable closure and state reset even more important. Professional JDBC development also requires attention to security, privacy, portability, observability, testing, and database-specific behavior.

Key Terms

JDBC: Java API for connecting applications to relational databases.

JDBC driver: Database-specific software implementing JDBC interfaces.

Type 4 driver: A pure Java driver that communicates directly using a database protocol.

Database URL: A string identifying a JDBC target and connection properties.

DriverManager: A basic service that selects a registered driver and creates connections.

DataSource: A connection-factory abstraction commonly used with configuration and pooling.

Connection: A logical session between an application and a database.

Statement: JDBC object for executing static SQL.

PreparedStatement: Parameterized statement that binds values separately from SQL text.

CallableStatement: Statement used to invoke stored procedures or functions.

ResultSet: Cursor-like representation of rows returned by a query.

SQL NULL: Database marker representing an absent or unknown value.

Transaction: A logical unit of database work.

Auto-commit: Mode in which individual statements are committed automatically.

Transaction isolation: Rules governing visibility of concurrent transaction changes.

Connection pool: Managed collection of reusable database connections.

SQL injection: Exploitation caused by treating untrusted input as SQL syntax.

Try-with-resources: Java construct that automatically closes closeable resources.

Batch execution: Submission of multiple similar operations as a group.

Least privilege: Security principle granting only the permissions required.

Review Questions

Short Answer Questions

  1. What is the role of a JDBC driver?
  1. Why is PreparedStatement generally preferred over concatenating user input into SQL?
  1. State one difference between DriverManager and DataSource.
  1. What does ResultSet.next() do?
  1. Why must pooled connections still be closed by application code?

Long Answer Questions

  1. Explain the complete flow from a Java application to an RDBMS through the JDBC architecture.
  1. Compare the four historical JDBC driver types and explain why Type 4 drivers dominate modern applications.
  1. Describe JDBC transaction management, including auto-commit, commit, rollback, and isolation.
  1. Explain how try-with-resources manages JDBC resources and why nested resource scopes are useful.
  1. Discuss security, privacy, and least-privilege considerations in a JDBC-based application.

Analytical / Application Questions

  1. A method executes an update and then reads a result set but returns the result set after closing the connection. Identify the defect and redesign the method.
  1. An enrolment transfer consists of a delete followed by an insert. Explain the failure scenario in auto-commit mode and propose a transaction-safe design.
  1. A web application experiences connection-pool exhaustion during peak traffic. Identify at least four possible causes and explain how you would investigate them.

Multiple Choice Questions with Answers

Question 1

Which JDBC component is primarily responsible for providing configured database connections, often through pooling?

A. ResultSet

B. DataSource

C. SQLException

D. ResultSetMetaData

Correct Answer: B. DataSource

Question 2

What is the main security advantage of a PreparedStatement?

A. It automatically encrypts the database

B. It eliminates the need for transactions

C. It separates parameter values from SQL syntax

D. It guarantees that every query uses an index

Correct Answer: C. It separates parameter values from SQL syntax

Question 3

Which method is normally used to execute a SELECT statement that returns rows?

A. executeQuery()

B. executeUpdate()

C. rollback()

D. addBatch()

Correct Answer: A. executeQuery()

Question 4

In JDBC parameter binding, the first question-mark parameter has which index?

A. 0

B. 1

C. -1

D. The number of parameters

Correct Answer: B. 1

Question 5

What is the principal purpose of calling connection.rollback()?

A. To close the JDBC driver

B. To release a ResultSet only

C. To undo changes in the current transaction

D. To create a new database schema

Correct Answer: C. To undo changes in the current transaction

Question 6

Which driver type communicates directly with the database protocol and is implemented entirely in Java?

A. Type 1

B. Type 2

C. Type 3

D. Type 4

Correct Answer: D. Type 4

Question 7

Why is try-with-resources recommended for JDBC code?

A. It automatically writes SQL queries

B. It closes eligible resources even when exceptions occur

C. It converts SQL into Java classes

D. It prevents all database deadlocks

Correct Answer: B. It closes eligible resources even when exceptions occur

Question 8

Which SQL condition correctly tests whether a column contains a database NULL?

A. column = NULL

B. column == NULL

C. column IS NULL

D. column EQUALS NULL

Correct Answer: C. column IS NULL

Question 9

What is a likely consequence of failing to close connections obtained from a connection pool?

A. The pool may become exhausted

B. The database automatically grants more privileges

C. All SQL becomes read-only

D. The Java compiler removes the connection

Correct Answer: A. The pool may become exhausted

Question 10

Which practice best supports least privilege?

A. Using one administrator account for every application

B. Granting an application only the database permissions it requires

C. Embedding credentials in every SQL statement

D. Disabling database authentication

Correct Answer: B. Granting an application only the database permissions it requires

Advanced Java (Multithreading, Collections, JDBC)
Chapter 12 of 15