1 of 26

Relational Databases Part 3: JDBC

CS 240 – Advanced Programming Concepts

2 of 26

JDBC Overview

Executing SQL from Java

3 of 26

Database Access from Java

  • Load database driver
  • Open a database connection
  • Start a transaction 
  • Execute queries and/or updates
  • Commit or Rollback the transaction
  • Close the database connection

  • Retrieving auto-increment ids

Omit transaction steps if you only need to execute a single statement.

4 of 26

5 of 26

JDBC Drivers and Connections

6 of 26

Making the JDBC Driver Available to Your Project

Three Ways:

  1. Add the dependency from File / Project Structure
    • Search for mysql-connector-j and select the latest version
  2. Create a Maven project and add the dependency to your pom.xml file

<dependency>

<groupId>com.mysql</groupId>

<artifactId>mysql-connector-j</artifactId>

<version>8.1.0</version>

</dependency>

  1. Create a Gradle project and add the dependency to your build.gradle file

implementation group: 'com.mysql', name: 'mysql-connector-j', version: '8.1.0'

7 of 26

Load Database Driver

try {

// Legacy. Modern DB drivers don’t require this

Class.forName("org.sqlite.JDBC");

} catch(ClassNotFoundException e) {

// ERROR! Could not load database driver

}

8 of 26

Open a Database Connection / Start a Transaction

import java.sql.*;

...

String connectionURL = "jdbc:mysql://localhost:3306/BookClub?" +

"user=jerodw&password=mypassword";

Connection connection = null;

try(Connection c = DriverManager.getConnection(connectionURL)) {

    connection = c;

    // Start a transaction

    connection.setAutoCommit(false);

// Use connection ...

} catch(SQLException ex) {

    // ERROR

}

Close the connection when you are through with it. Or open it in a try-with-resources statement.

Don’t close before you commit or rollback your transaction.

9 of 26

10 of 26

Executing Queries with JDBC

11 of 26

Execute a Query

List<Book> books = new ArrayList<>();

String sql = 

    "select id, title, author, genre, category_id from book";

try(PreparedStatement stmt = connection.prepareStatement(sql);

    ResultSet rs = stmt.executeQuery()) {

    while(rs.next()) {

        int id = rs.getInt(1);

        String title = rs.getString(2);

        String author = rs.getString(3);

        String genre = rs.getString(4);

        int categoryId = rs.getInt(5);

        books.add(new Book(id, title, author, genre, categoryId));

    }

} catch (SQLException ex) {

    // ERROR

}

12 of 26

13 of 26

Executing Insert, Update and Delete Statements

14 of 26

Execute an Insert, Update, or Delete

String sql = "update book " +

    "set title = ?, author = ?, genre = ?, category_id = ? " +

    "where id = ?";

try(PreparedStatement stmt = connection.prepareStatement(sql)) {

    stmt.setString(1, book.getTitle());

    stmt.setString(2, book.getAuthor());

    stmt.setString(3, book.getGenre());

    stmt.setInt(4, book.getCategoryId());

    stmt.setInt(5, book.getId());

    if(stmt.executeUpdate() == 1) {

        System.out.println("Updated book " + book.getId());

    } else {

        System.out.println(

            "Failed to update book " + book.getId());

    }

} catch(SQLException ex) {

    // ERROR

}

Assumes we have a reference named ‘book’ to an object that contains the values we need.

15 of 26

Prevent SQL Injection Attacks with Parameter Replacement in PreparedStatements

1

16 of 26

Citations (Java Database Access with JDBC)

1. Randall Munroe. Exploits of a Mom. xkcd. (CC BY-NC 2.5)

17 of 26

Retrieving Auto-Increment Primary Keys and Ending Transactions

18 of 26

Retrieving Auto-increment PKs (from MySQL)

String sql = "insert into book (title, author, genre, category_id)

values (?, ?, ?, ?)";

try(PreparedStatement stmt = connection.prepareStatement(sql,

Statement.RETURN_GENERATED_KEYS)) {

for(Book book : books) {

stmt.setString(1, book.getTitle());

stmt.setString(2, book.getAuthor());

stmt.setString(3, book.getGenre());

stmt.setInt(4, book.getCategoryId());

if(stmt.executeUpdate() == 1) {

try(ResultSet generatedKeys = stmt.getGeneratedKeys()) {

generatedKeys.next();

int id = generatedKeys.getInt(1); // ID of the inserted book

book.setId(id);

}

System.out.println("Inserted book " + book);

} else {

System.out.println("Failed to insert book");

}

}

}

19 of 26

Commit or Rollback a Transaction

Connection connection = null;

try(Connection c = DriverManager.getConnection(connectionURL)) {

    connection = c;

    ...

    connection.commit();

} catch(SQLException ex) {

    if(connection != null) {

        connection.rollback();

    }

    throw ex;

}

Close the connection when you are through with it, or open it in a try-with-resources statement.

20 of 26

21 of 26

Usernames, Passwords and User Permissions

22 of 26

Usernames, Passwords and Database Permissions

String connectionURL =

"jdbc:mysql://localhost:3306/BookClub?” +

“user=jerodw&password=mypassword";

Note: In practice, don’t put username and password in source code. Can read from a gitignored config file instead.

Requires a user with permission to access the database:

  • CREATE USER 'jerodw'@'localhost' IDENTIFIED BY 'mypassword';
  • GRANT ALL on BookClub.* to 'jerodw'@'localhost';

23 of 26

24 of 26

JDBC: Putting it All Together

25 of 26

Putting It All Together

  • Code Example

26 of 26

BLANK SLIDE