5.1 JDBC API

1. JDBC (Java Database Connectivity) is an API for interacting with a database in Java.

2. Each database vendor produces a driver that translates JDBC requests to the database-specific protocol.

3. JDBC is based on SQL (Standard Query Lanauge) for database access.

4. JDBC provides classes for issuing SQL statements and for working with the query results.

5. Object-relational mappers provide a higher-level mechanism (Hibernate or JPA) for working with a database, but you should understand SQL/JDBC to use them effectively.


5.2 Requirements for Using JDBC

1. You need a database, we use Mysql as example

About how to install Mysql, you can refer to https://www.cnblogs.com/bruce-he/p/10454856.html, it is similar in Windows.

2. You need a database driver JAR, such as mysql-connector-j-8.0.32.jar for Mysql

Without using Spring MVC or Spring Boot framework, you can follow below steps to add it in IdeaJ.

1. Vist https://mvnrepository.com/, then type "mysql-connector-java" to search
2. In the first "MySQL Connector/J" item, download the latest JDBC driver. Choose "jar" Files to download.
3. In the IdeaJ, follow the detailed step in the picture below.

3. Config the database connection properties.

jdbc.drivers=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306/javatest?userUnicode=true&characterEncoding=utf8
jdbc.username=root
jdbc.password=root

4. Use this code to establish a JDBC connection:

// use Properties to parse jdbc.properties
var props = new Properties();
try (InputStream in = Files.newInputStream(Paths.get("./v2ch05/src/database.properties"))) {
props.load(in);
}
String drivers = props.getProperty("jdbc.drivers");
if (drivers != null) {
System.setProperty("jdbc.drivers", drivers);
}
String url = props.getProperty("jdbc.url");
String username = props.getProperty("jdbc.username");
String password = props.getProperty("jdbc.password"); Connection conn = DriverManager.getConnection(url, username, password);
return conn;

5. You use the Connection object to create SQL statement

try (Connection conn = getConnection();
// Statement 是 Java 执行数据库操作的一个重要接口,用于在已经建立数据库连接的基础上,向数据库发送要执行的SQL语句。Statement对象,用于执行不带参数的简单SQL语句。
Statement stat = conn.createStatement()) {
stat.executeUpdate("CREATE TABLE Greetings (Message CHAR(20))");
}

6. Database connections are a limited resource. When you are done, be sure to close the connection.


5.4 Executing SQL Statements

5.4.1 Executing SQL

1. To execute a SQL statement, create a Statement object:

Statement stat = conn.createStatement();

2. To update the database (INSERT, UPDATE, DELETE), call the executeUpdate method, and the number of affected rows is returned.

String command = "UPDATE Books SET Price = Price - 5.00 WHERE Title NOT LIKE '%Introduction%'";
int rows = stat.executeUpdate(command);

3. Use executeQuery to issue a SELECT query, and an ResultSet type object is returned.

ResultSet result = stat.executeQuery("SELECT * FROM Books");

4. Use execute to issue arbitrary SQL commands.

5.4.2 Managing JDBC objects

1. A connection object can produce one or more Statement objects.

  • Some database drivers only allow one Statement at a time.
  • Call DatabaseMetaData.getMaxStatements to find out.

2. You can use the same Statement object for multiple queries.

3. A Statement can have at most one open ResultSet.

  • Don't work with multiple result sets at a time. Issue a query that gives you all data in one result set.

4. When you execute another query or close a Statement, an open result set is closed.

  • The Statement.closeOnComplete method closes the statement as soon as an open result set is closed.
  • Some other person, put the each Connection, Statement and ResultSet in try-with-resources.

5. When you close a Connection, all statements are closed.

5.4.3 SQLExceptions and Warnings

1. A SQLException has a chain of SQLException objects. This is in addition to the "cause" chain that all exceptions have.

2. The  SQLException class extends the Iterable<Throwable> interface, you can iterate over all exceptions like this:

for (Throwable t : sqlException) {
do something with t
}

3. The SQLException.getSQLState method yields a string that is standardized by either X/Open or SQL:2003.

  • Call DatabaseMetaData.getSQLStateType to find out which standard is used by your driver.

4. There is also a chain of warnings:

SQLWarning w = stat.getWarning();
while (w != null) {
do something with w
w = w.nextWarning(); // it's different from SQLException, each warning has a nextWarning() method
}

5.4.4 Result Sets

1. A query yields a ResultSet:

ResultSet rs = stat.exectQuery("SELECT * FROM Books");

2. Use this loop to iterate over the rows:

while (rs.next()) {
look at a row of the result set
}

3. To get at the columns of a row, use one of the get methods:

String isbn = rs.getString(1);  // The first(!) column, to get the value using column index
double price = rs.getDouble("Price"); // to get the value using column name

5.5 Executing Query Operation

5.5.1 Prepared Statements

1. When a query has variable parts, you don't want to formulate it through string concatenation:

String query = "SELECT * FROM Books WHERE Books.Title = ; + title;    // Don't - or you may become the victim of SQL injection

2. Instead, use a prepared statement:

String query = "SELECT * FROM Books WHERE Books.Title = ?";
PreparedStatement stat = conn.preparedStatement(query);
stat.setString(1, title); // 1) setString() for String, setInt() for Integer, SetDouble() for Double; 2) first index is 1
ResultSet rs = stat.executeQuery();

3. A preparedStatement becomes invalid after closing the Connection that created it. But the database will cache the query plan.

5.5.3 SQL Escapes

1. The "escape" syntax supports features for which database syntax varies.

2. Specify date and time literals as:

{d '2008-01-24'}
{t '23:59:59'}
{ts '2008-01-24 23:59:59.999' }

3. To call a scalar function (that is , a function returning a single value), embed the standard function name and argument like this:

{fn left(?, 20)}
{fn user()}

4. Here is how to call a stored procedure:

{call PROC1(?, ?)}
{call PROC2}
{? = call PROC3(?)}

5. The {oj ...} escape lets you fomulate outer joins in a database-independent way.

6. You can specifiy an escape character, for example, to match all titles containg a literal %

... WHERE ? like %!_% {escape '!'}    // ! 为转义字符, !_ 表示字面常量下划线,如查找 "javacore_chapter1"

5.5.4 Multiple Results

1. It is possible for a query to return multiple result sets or update counts.

  • This can happen with stored procedures.
  • Some databases allow you to submit multiple SELECT statements together.

2. Use the following loop to analyze the query result:

boolean isResult = stat.execute(command);
boolean done = false;
while (!done) {
if (isResult) {
ResultSet result = stat.getResultSet();
do something with result
}
else {
int updateCount = stat.getUpdateCount();
if (updateCount >= 0) {
do something with updateCount
}
else {
done = true;
}
}
if (!done) {
isResult = stat.getMoreResults();
}
}

获取所有结果集的步骤:

  • 1. 使用 execute() 执行 SQL 语句;
  • 2. 获取第一个结果集或更新计数;
  • 3. 重复调用 getMoreResults() 以移动到下一个结果集;
  • 4. 当不存在更多的结果集或更新计数时,完成操作

5.5.5 Retrieving Autogenerated Values

1. Most databases support some mechanism for automatcally generating values.

  • MySQL: Id INTEGER AUTO_INCREMENT
  • Derby: Id INTEGER GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1)

2. You can retrieve the autogenerated values that were generated by an INSERT statement:

stat.executeUpdate(insertStatement, Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stat.getGeneratedKeys();
if (rs.next()) {
int key = rs.getInt(1);
Do something with key
}

5.6 Scrollable Result Sets

1. The ResultSet.next() iterates over the rows of a result set.

2. A scrollable result set allows you to move the current row by arbitrary amounts and to arbitrary positions.

3. A scrollable result set can be updatable: you can set the column values, and the changes are reflected in the database.

4. Construct a scrollable or updatable result set like this:

Statement stat = conn.createStatement(type, concurrency);

PreparedStatement stat = conn.preparedStatement(command, type, concurrency);

5. To scroll within the result set, call:

rs.previous()
rs.relative(n)
rs.absolute(n)

6. The getCurrentRow() yields the current row number (starting at 1) or 0 if the cursor is before the first or after the last row.

7. If the result set is updatable, call one of the update() to change a column value:

double price = rs.getDouble("Price");
rs.updateDouble("Price", price + increase);
rs.updateRow(); // call updateRow() to store the changes in database

8. To insert a new row, call

rs.moveToInsertRow();
call rs.updateXxx(...)
rs.insertRow();
rs.moveToCurrentRow();

9. The ResultSet.deleteRow() removes the row from the result set and the database.

10. Update result sets are intended for table editing by end users. If you want to update the database programmatically, use SQL queries.


5.7 Row Sets

5.7.2 Cached Row Sets

1. Updatable result sets require a connection to the database, while connections are scarce resources.

2. A cached row set is like an updatable result set, but it can be disconnected from the database.

3. Obtain a cached row set like this:

RowSetFactory factory = RowSetFactory.newFactory();
CachedRowSet crs = factory.createCachedRowSet();

4. Then populate it with a result set:

ResultSet result = ...;
crs.populate(result);
conn.close(); // now OK to close the database connection

5. Now you can view and update the row set. When you are done, call crs.acceptChanges(conn), passing a new Connection object.

6. Alternatively, you can let the cached row set establish a connection automatically as needed. First, set up the connection parameters:

crs.setURL("jdbc:mysql://127.0.0.1:3308/javatest)
crs.setUsername("root");
crs.setPassword("root");

7. Then set the query statement and any parameters, and execute the query:

crs.setCommand("SELECT * FROM Books WHERE Title = ?");
crs.setString(1, title);
crs.execute();

8. When you are done updating the row set, you can call crs.acceptChanges() without a Connection parameter.


5.8 Metadata

1. Metadata are data that describe the database or its parts.

2. First, get a DatabaseMetaData object from a connection:

DatabaseMetaData meta = conn.getMetaData();

3. This call yields a result set that lists all tables in the database:

ResultSet mrs = meta.getTables(null, null, null, new String[] {"TABLE"});

4. As it happens, the third column is the table name:

while (mrs.next()) {
System.out.println(mrs.getString(3));
}

5. There are many methods to disclose how the database driver behave under conditions that are not standardized, such as:

meta.supportsCatalogsInPrivilegeDefinitions()
meta.nullPlusNonNullIsNull()

Result Set Metadata

1. The ResultSetMetaData interface has methods to describe a result set.

2. This is particularly useful for generic tools that work with arbitrary tables.

3. Here we find out column sizes and column labels, useful information for displaying a result:

ResultSet rs = stat.executeQuery("SELECT * FROM " + tableName);
ResultSetMetaData meta = rs.getMetaData();
for (int i = 1; i <= meta.getColumnCount(); i++) {
String columnName = meta.getColumnLabel(i);
String columnWidth = meta.getColumnDisplaySize(i);
...
}

5.9 Transactions

5.9.1 Transactions

1. You can group a set of statements to form a transaction. When all has gone well, the transaction is committed, If something goes wrong, the transaction is rolled back, as if none of its statement has been issued.

2. By default, a connection is in "autocommit" mode: Each statement is committed as it is executed.

3. In order to use tansaction, first turn off autocommit, then execute any number of statements and commit your work.

conn.setAutoCommit(false);
Statement stat = conn.createStatement();
stat.executeUpdate(command1);
stat.executeUpdate(command2);
...
conn.commit();

4. However, if an error occurred, call:

conn.rollback();

5.9.3 Batch Updates

1. Suppose an application populates a database with many INSERT statements. You can improve performance with a batch update instead of calling executeUpdate, call the addBatch method:

String command = "CREATE TABLE ...";
stat.addBatch(command);
while (...) {
command = "INSERT INTO ... VALUES(" + ... + ")";
stat.addBatch(command);
}

2. Finally, submit the entire batch:

int counts = stat.executeBatch();    // Yields row counts for all submitted statements

读后笔记 -- Java核心技术(第11版 卷 II) Chapter5 数据库编程的更多相关文章

  1. java核心技术(第十版卷一)笔记(纯干货!)

    这是我读过的第三本关于java基础的书.第一本<<java从入门到精通>>这本书让我灵识初开.第二本<<java敏捷开发>>这本书则是有一次被一位师傅批 ...

  2. java核心技术第十版 笔记

    1.java区分大小写 2.类名是以大写字母开头 (驼峰) 3.http://docs.oracle.com/javase/specs  java语言规范 4. /* */ 注释不能嵌套 5. Jav ...

  3. Java JDBC数据库编程

    课程  Java面向对象程序设计 一.实验目的 掌握数据库编程技术 二.实验环境 1.微型计算机一台 2.WINDOWS操作系统,Java SDK,Eclipse开发环境,Microsoft SQL  ...

  4. 《Java核心技术 卷II 高级特性(原书第9版)》

    <Java核心技术 卷II 高级特性(原书第9版)> 基本信息 原书名:Core Java Volume II—Advanced Features(Ninth Edition) 作者: ( ...

  5. Java核心技术·卷 II(原书第10版)分享下载

    Java核心技术·卷 II 内容介绍 Java领域最有影响力和价值的著作之一,由拥有20多年教学与研究经验的资深Java技术专家撰写(获Jolt大奖),与<Java编程思想>齐名,10余年 ...

  6. 《Java核心技术卷I》观赏指南

    Tomxin7 如果你有想看书的计划,但是还在纠结哪些书值得看,可以简单看看"观赏指南"系列,本文会简单列出书中内容,给还没有买书的朋友提供一个参考. 前言 秋招过去很久了,虽然在 ...

  7. Java核心技术卷阅读随笔--第4章【对象与类】

    对 象 与 类 4.1 面向对象程序设计概述 面向对象程序设计(简称 OOP) 是当今主流的程序设计范型, 它已经取代了 20 世纪 70 年代的" 结构化" 过程化程序设计开发技 ...

  8. 《Java核心技术卷1》拾遗

    之前对Java的基础知识有过学习,现在开始学习<Java核心技术卷1>,将一些新学的知识点,做简要记录,以备后续回顾: 1.double (1)所有的“非数值”都认为是不相同的 if(x= ...

  9. java的优点和误解 《java核心技术卷i》第一章

    <java核心技术卷i>第一章主要内容包括三点: 1:Java白皮书的关键术语:描述Java的十一个关键字: 2:Java applet 3 :关于Java的常见误解   1:第一章:Ja ...

  10. Java核心技术卷阅读随笔--第3章【Java 的基本程序设计结构】

    Java 的基本程序设计结构 现在, 假定已经成功地安装了 JDK,并且能够运行第 2 章中给出的示例程序.我们从现在开始将介绍 Java 应用程序设计.本章主要介绍程序设计的基本概念(如数据类型.分 ...

随机推荐

  1. 使用 Three.js 的 3D 制作动画场景

    推荐:将 NSDT场景编辑器 加入你的3D开发工具链. 由于 GSL 语法的复杂性,对于许多开发人员来说 WebGL 是一个未知的领域.但是有了 Three.js,在浏览器中 3D 的实现变得简单.下 ...

  2. Android:遍历视图

    <LinearLayout android:id="@+id/ques2_layout" android:layout_width="match_parent&qu ...

  3. 信息学奥赛介绍-CSP

    什么是信息学奥赛 信息学奥赛,全称为信息学奥林匹克竞赛,是教育部和中国科协委托中国计算机 学会举办的一项全国青少年计算机程序设计竞赛.主要分为NOIP(全国联赛),夏令营 NOI比赛的扩展赛,也称全国 ...

  4. 【面试题】面试突击71:GET 和 POST 有什么区别?

    携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情 GET 和 POST 是 HTTP 请求中最常用的两种请求方法,在日常开发的 RESTful 接口中,都能 ...

  5. Nacos服务管理

    注:基于SpringBoot项目 一.服务注册 1. 依赖引入 # 首先父工程中引入 SpringCloudAlibaba 版本管理依赖,其中会包含 nacos 的版本 <!-- SpringC ...

  6. Spring全家桶(一)之Spring总结

    0. Spring常用注解汇总 Spring常用注解汇总 使用注解之前要开启自动扫描功能,其中base-package为需要扫描的包(含子包). <context:component-scan ...

  7. 超级详细的Vue安装与配置教程

    原文: https://www.jb51.net/article/251371.htm 超级详细的Vue安装与配置教程   Vue web前端三大主流框架之一,是一套用于构建用户界面的渐进式框架,下面 ...

  8. 集合(Collection)

    前几天做数据结构题碰到了集合,当时并没有学,只是通过做题对此稍微有了了解.今天正好学到了,来做一下学习记录. 一.集合总体框架 由上图可知,集合的实现方式有两大类: (1)线性接口:该集合的顶层接口是 ...

  9. javase_note

    我上班摸鱼重新学习java基础做的笔记,从面向对象开始 面向对象基础 类与对象 人类.鸟类.鱼类...所谓类,就是对一类事物的描述 对象是某一类事物实际存在的每个个体,因此也称为实例 类是抽象概念,对 ...

  10. Dockerfile打包java应用

    #基础镜像 FROM openjdk:8-jre # 作者 MAINTAINER hg #挂载目录 VOLUME /home/hg #创建目录 RUN mkdir /home/hg #指定工作目录 W ...