PreparedStatement and ResultSet

Inserting a Product

String sql = "insert into products (name, price, stock, category) values (?, ?, ?, ?)";
try (Connection conn = dataSource.getConnection();
     PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
    ps.setString(1, "Boat Rockerz 450");
    ps.setBigDecimal(2, new BigDecimal("1499.00"));
    ps.setInt(3, 120);
    ps.setString(4, "Electronics");
    int rows = ps.executeUpdate();              // INSERT/UPDATE/DELETE -> row count

    try (ResultSet keys = ps.getGeneratedKeys()) {
        if (keys.next()) System.out.println("Inserted id " + keys.getLong(1) + ", rows=" + rows);
    }
}

Each ? is a parameter placeholder. You fill it with a typed setter (setString, setBigDecimal...). Index starts at 1, not 0.

Reading Rows with ResultSet

String sql = "select id, name, price, stock from products where category = ? order by price";
List<Product> result = new ArrayList<>();
try (Connection conn = dataSource.getConnection();
     PreparedStatement ps = conn.prepareStatement(sql)) {
    ps.setString(1, "Electronics");
    try (ResultSet rs = ps.executeQuery()) {
        while (rs.next()) {                      // moves the cursor to the next row
            Product p = new Product();
            p.setId(rs.getLong("id"));
            p.setName(rs.getString("name"));
            p.setPrice(rs.getBigDecimal("price"));
            p.setStock(rs.getInt("stock"));
            result.add(p);
        }
    }
}

Output

# printing result

Example output

[Product{id=7, name=USB-C Cable, price=199.00, stock=500},
 Product{id=1, name=Boat Rockerz 450, price=1499.00, stock=120},
 Product{id=3, name=Noise ColorFit Pro, price=2299.00, stock=40}]

Transactions in JDBC

try (Connection conn = dataSource.getConnection()) {
    conn.setAutoCommit(false);                 // start a transaction
    try {
        reduceStock(conn, productId, qty);
        insertOrder(conn, order);
        conn.commit();                         // both succeed...
    } catch (SQLException e) {
        conn.rollback();                       // ...or neither
        throw e;
    }
}

Tip: In JPA and Spring you will replace this boilerplate with em.getTransaction().begin()/commit() or simply @Transactional.