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. TikTok 推荐引擎强大的秘密

    作者:Heorhii Skovorodnikov 深入研究TikTok令人惊叹的实时推荐系统的内部工作原理,了解是什么使它成为该领域最好的产品之一. 为什么TikTok的feed如此让人上瘾?秘诀在于 ...

  2. 登峰造极,师出造化,Pytorch人工智能AI图像增强框架ControlNet绘画实践,基于Python3.10

    人工智能太疯狂,传统劳动力和内容创作平台被AI枪毙,弃尸尘埃.并非空穴来风,也不是危言耸听,人工智能AI图像增强框架ControlNet正在疯狂地改写绘画艺术的发展进程,你问我绘画行业未来的样子?我只 ...

  3. Linux:find 指令的选项 +n、-n、n

    描述 find 指令查找文件时可以通过时间来锁定或缩小搜查范围.其中需要利用到文件的三个时间?:Access Time(atime).Modify Time(mtime) 和 Change Time( ...

  4. unity通过隐藏layer隐藏组件

    设置组件layer 修改组件layer为需要隐藏的layer  隐藏组件 修改layer为隐藏状态 CenterCam.GetComponent<Camera>().cullingMask ...

  5. Kotlin学习-基础知识点

    一:基础要点 //常量定义 valval arg_a1: Int = 1  //变量定义varvar arg_a2 = 5  // 系统自动推断变量类型为Int备注:kotlin 定义变量必须给定初始 ...

  6. 一台电脑连接多个不同IP段

    1.首先让电脑能联网,则在ipv4里面设置好能上网的ip地址,dns则为路由器ip 备用dns8.8.8.8 2.点击高级依次添加其他内网ip段 例如192.168.0.66 ----------19 ...

  7. element-ui动态表单验证

    由于项目中固定标签的数据是由后端查询回来的数组,需要进行表单验证,代码如下: <template> <div class="form"> <el-fo ...

  8. linux下启动jar包

    一.jdk 1.安装jdk 2.查看 摘自:(29条消息) Linux如何查看JDK的安装路径_fanyuna的博客-CSDN博客_linux查看jdk安装位置 1:echo $JAVA_HOME 使 ...

  9. unity工程多开Bat

    %cd%:: 源路径set sourceDir=C:\Projects\XXX:: 目标路径set destDir=C:\Projects\XXX_Clone :: 如果目标路径不存在就创建if no ...

  10. 图片在div中居中

    要将一张图片垂直和水平居中在一个 <div> 元素中,你可以使用以下 CSS 样式: div { display: flex; justify-content: center; align ...