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. ACR2022的辩论:DMARDs在pre-RA中的作用

    ACR2022的辩论:DMARDs在pre-RA中的作用 2022年11月13日   亚临床RA在风湿病学实践中越来越常见:然而,目前尚不清楚如何管理这些患者,以及启动DMARD是否可以预防RA的发展 ...

  2. CCRD_TOC_2007_EULAR专辑_1

    中信国健临床通讯 EULAR 2007专辑I 目 录 类风湿关节炎 1 TEMPO 研究第一年影像学数据显示:骨侵蚀修复 (repair) 几乎只出现在无关节肿胀或肿胀改善组 van der Heij ...

  3. vue2和vue3区别

    1. vue2和vue3双向数据绑定原理发生了改变 vue2的双向数据绑定是利用了es5 的一个API Object.definepropert() 对数据进行劫持 结合发布订阅模式来实现的.vue3 ...

  4. day08-MyBatis的关联映射02

    MyBatis的关联映射02 3.一对多 3.1基本介绍 mybatis – MyBatis 3 | XML 映射器 多对一关系也是一个基本的映射关系,多对一,也可以理解为一对多.例如: User-- ...

  5. .NET AsyncLocal 避坑指南

    目录 AsyncLocal 用法简介 AsyncLocal 实现原理 AsyncLocal 的坑 AsyncLocal 的避坑指南 HttpContextAccessor 的实现原理 AsyncLoc ...

  6. LeetCode-429 N叉树的层次遍历

    来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/n-ary-tree-level-order-traversal著作权归领扣网络所有.商业转载请联 ...

  7. 0627.selenium请求库*2

    昨天已经介绍了关于selenium的简单基本基本使用--通过两种方式自动打开和关闭谷歌浏览器今天,我们将介绍的模块将是在昨天打开谷歌浏览器的基础上,打开某一个电商平台,并搜索某一个产品,利用前面学的知 ...

  8. 记录一次Python环境安装出现的问题(已安装java)

    之前是在其他电脑上安装python环境,没有问题. 换了一台电脑开始安装(注:已配置java环境) 安装包准备好 ( 这里使用的是python 3.6.5(64位) ,下载地址选择官网) 教程百度都有 ...

  9. 图文并茂解释开源许可证 GPL、BSD、MIT、Mozilla、Apache和LGPL的区别?

    BSD开源协议BSD开源协议是一个给于使用者很大自由的协议.基本上使用者可以"为所欲为",可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布. 但" ...

  10. CSS滚动条样式修改::-webkit-scrollbar

    修改滚动条样式通过伪元素::-webkit-scrollbar:::-webkit-scrollbar - CSS(层叠样式表) | MDN (mozilla.org) :-webkit-scroll ...