jdbc和mysql做游戏排行榜_MySQL数据库与JDBC编程
歡迎關(guān)注公眾號(hào):xfxuezhang
MySQL數(shù)據(jù)庫(kù)與JDBC編程
JDBC (Java Database Connectivity)
DDL(Data Definition Language,數(shù)據(jù)定義語(yǔ)言)語(yǔ)句
創(chuàng)建表
修改表結(jié)構(gòu)
增加列定義
修改列定義
刪除列
刪除數(shù)據(jù)表
清空表
MySQL重命名數(shù)據(jù)表
MySQL修改列名
數(shù)據(jù)庫(kù)約束
索引(一個(gè)數(shù)據(jù)庫(kù)對(duì)象)
視圖
DML(Data Definition Language,數(shù)據(jù)定義語(yǔ)言)語(yǔ)句
insert into語(yǔ)句
update語(yǔ)句
delete from語(yǔ)句
單表查詢
where后的其他運(yùn)算符
order by輸出排序
數(shù)據(jù)庫(kù)函數(shù)
MySQL單行函數(shù)
分組和組函數(shù)
group by分組
多表連接查詢
交叉連接
自然連接
using子句連接
on子句連接
左、右、全外連接
子查詢
集合運(yùn)算
union并運(yùn)算
minus差運(yùn)算
intersect交運(yùn)算
JDBC的經(jīng)典用法
JDBC編程步驟
示例:簡(jiǎn)單SQL查詢
執(zhí)行SQL語(yǔ)句的方法
使用executeLargeUpdate方法執(zhí)行DDL和DML語(yǔ)句
示例:讀取ini文件,連接并創(chuàng)建數(shù)據(jù)表
使用PreparedStatement執(zhí)行SQL語(yǔ)句
示例:使用PreparedStatement插入記錄
使用CallableStatement調(diào)用存儲(chǔ)過程
示例:調(diào)用存儲(chǔ)功能
管理結(jié)果集
可滾動(dòng)、可更改的結(jié)果集
示例:創(chuàng)建可滾動(dòng)、可更改的結(jié)果集
處理Blob類型數(shù)據(jù)
示例:通過SQL的Blob存儲(chǔ)并讀取圖片數(shù)據(jù)
使用ResultSetMetaData分析結(jié)果集
示例:分析結(jié)果集
使用RowSet包裝結(jié)果集
RowSetFactory和RowSet
示例:通過RowSetFactory使用jdbcRowSet
離線RowSet
示例:CachedRowSet離線操作SQL
事務(wù)處理
事務(wù)的概念
JDBC事務(wù)支持
使用批量更新
MySQL數(shù)據(jù)庫(kù)與JDBC編程
JDBC (Java Database Connectivity)
對(duì)于關(guān)系數(shù)據(jù)庫(kù)而言,最基本的數(shù)據(jù)存儲(chǔ)單元是數(shù)據(jù)表。
SQL:Structured Query Language,結(jié)構(gòu)化查詢語(yǔ)言。
DDL(Data Definition Language,數(shù)據(jù)定義語(yǔ)言)語(yǔ)句
主要操作數(shù)據(jù)庫(kù)對(duì)象。
創(chuàng)建表
CREATE TABLE [模式名.] 表名
(
columnName1 datatype [default expr],
...
)
利用子查詢建表
CREATE TABLE [模式名.] 表名 [col[, col]]
as
select * from user_inf;
修改表結(jié)構(gòu)
增加列定義
ALTER TABLE 表名
add
(
columnName1 datatype [default expr],
...
);
字符串值由單引號(hào)引起。
修改列定義
ALTER TABLE 表名
modify columnName datatype [default expr] [first|afterColName];
first、afterColName指定需要將目標(biāo)修改到指定位置。
刪除列
ALTER TABLE 表名
drop columnName;
刪除數(shù)據(jù)表
DROP TABLE 表名;
表結(jié)構(gòu)刪除,表對(duì)象不再存在;表的所有數(shù)據(jù)被刪除;該表所有相關(guān)的索引、約束也被刪除。
清空表
TRUNCATE 表名;
刪除表內(nèi)的全部數(shù)據(jù),但保留表結(jié)構(gòu)。
MySQL重命名數(shù)據(jù)表
ALTER TABLE 表名 rename to 新表名;
MySQL修改列名
ALTER TABLE 表名 CHANGE 列名 新列名 type [default expr] [first|afterColName]
數(shù)據(jù)庫(kù)約束
5種完整性約束
1、NOT NULL:非空約束,指定某列不能為空。
CREATE TABLE 表名 (id int NOT NULL);
2、UNIQUE:唯一約束,指定某列或者某幾列組合不能重復(fù)。
1、列級(jí)約束
name VARCHAR(255) UNIQUE;
?
2、表級(jí)約束(為多列組合建立唯一約束,或想自行指定約束名)
CREATE TABLE 表名(
# 表級(jí)約束語(yǔ)法建立唯一約束
UNIQUE (name),
# 并指定約束名
CONSTRAINT 新約束名 UNIQUE(pass),
# 指定兩列組合不允許重復(fù)
CONSTRAINT 新約束名 UNIQUE(name, pass)
)
?
3、MySQL刪除約束
ALTER TABLE 表名 DROP INDEX 約束名;
?
4、大部分?jǐn)?shù)據(jù)庫(kù)刪除約束
ALTER TABLE 表名 DROP CONSTRAINT 約束名;
3、PRIMARY KEY:主鍵,指定該列的值可以唯一地標(biāo)識(shí)該條記錄。
1、列級(jí)約束
CREATE TABLE 表名 (id INT PRIMARY KEY);
?
2、表級(jí)約束
CREATE TABLE 表名 (
id INT,
CONSTRAINT 約束名 PRIMARY KEY(id)
);
?
3、建立多列組合的主鍵約束
CREATE TABLE 表名 (
id INT,
name VARCHAR(255),
PRIMARY KEY(id, name)
);
?
4、刪除主鍵約束
ALTER TABLE 表名 DROP PRIMARY KEY;
?
5、增加主鍵約束
MODIFY:采用列級(jí)約束語(yǔ)法
ADD:采用表級(jí)約束語(yǔ)法
?
6、主鍵自增長(zhǎng)
id INT AUTO_INCREMENT PRIMARY KEY
4、FOREIGN KEY:外鍵,指定該行記錄從屬于主表中的一條記錄,主要用于保證一個(gè)或兩個(gè)數(shù)據(jù)表之間的參照完整性。
1、指定兩列的聯(lián)合外鍵
CREATE TABLE 表名(
Sname VARCHAR(255),
Spass VARCHAR(255),
CONSTRAINT 約束名 FOREIGN KEY(Sname, Spass) REFERENCES 主表名(Fname, Fpass)
);
2、級(jí)聯(lián)刪除(定義當(dāng)刪除主表記錄時(shí),從表記錄也會(huì)隨之級(jí)聯(lián)刪除/從表記錄的外鍵設(shè)置為null)
CREATE TABLE 表名(
Sname VARCHAR(255),
FOREIGN KEY(Sname) REFERENCES 主表名(Fid) ON DELETE CASCADE # 也可用ON DELETE SET NULL
);
5、CHECK:檢查,制定一個(gè)布爾表達(dá)式,用于指定對(duì)應(yīng)列的值必須滿足該表達(dá)式。(MySQL不支持)
CREATE TABLE 表名(
key INT,
CHECK(key>10)
);
索引(一個(gè)數(shù)據(jù)庫(kù)對(duì)象)
創(chuàng)建索引的唯一作用是加速對(duì)表的查詢,索引通過使用快速路徑訪問方法來(lái)快速定位數(shù)據(jù),從而減少了磁盤的I/0。
創(chuàng)建索引:
1、自動(dòng)
當(dāng)在表上定義主鍵約束、唯一約束、外鍵約束時(shí),系統(tǒng)自動(dòng)創(chuàng)建對(duì)應(yīng)的索引。
2、手動(dòng)
CREATE INDEX 索引名 ON 表名(name, pass);
刪除索引:
1、自動(dòng)
數(shù)據(jù)表被刪除時(shí),該表上的索引自動(dòng)被刪除。
2、手動(dòng)
DROP INDEX 索引名 ON 表名;
視圖
數(shù)據(jù)表中數(shù)據(jù)的邏輯顯示。
創(chuàng)建視圖,且不允許修改數(shù)據(jù):
CREATE OR REPLACE VIEW 視圖名 AS 查詢語(yǔ)句 WITH CHECK OPTION;
刪除視圖
DROP VIEW 視圖名;
DML(Data Definition Language,數(shù)據(jù)定義語(yǔ)言)語(yǔ)句
主要操作數(shù)據(jù)表里的數(shù)據(jù)。由insert into、update、delete from三個(gè)命令組成。
insert into語(yǔ)句
向數(shù)據(jù)表中插入記錄:
INSERT INTO 表名 (id, name, age) VALUES(1, "sxf", null);
帶子查詢的插入(要求所選的數(shù)據(jù)列個(gè)數(shù)相等、類型匹配):
INSERT INTO 表名 (name) SELECT name FROM 表2;
MySQL多條插入
INSERT INTO 表名 (id, name) VALUES(1, "a"), (2,"b");
update語(yǔ)句
修改數(shù)據(jù)表的記錄。
UPDATE 表名 SET name="sxf", pass="123" WHERE id=1;
delete from語(yǔ)句
刪除指定數(shù)據(jù)表的記錄。總是整行刪除。
DELETE FROM 表名 WHERE id>1 AND id<5;
單表查詢
字符串連接用:concat();為數(shù)據(jù)列和表達(dá)式起別名用:as或空格;為表起別名用:as或空格;去除重復(fù)行用:distinct;
SELECT DISTINCT CONCAT("na", "me") AS myName FROM table t WHERE id*2>4;
where后的其他運(yùn)算符
1、expr2<=expr1<=expr3
expr1 BETWEEN expr2 AND expr3;
2、expr1等于括號(hào)里的任意一個(gè)表達(dá)式的值
expr1 IN(expr2, expr3, ...);
3、字符串匹配,下劃線代表一個(gè)字符,百分號(hào)代表任意多個(gè)字符
like ‘_%’;
4、是否為null
is null;
order by輸出排序
desc降序,默認(rèn)asc升序。如果按多列排序,則每列的asc、desc必須單獨(dú)設(shè)定。
SELECT * FROM table ORDER BY name DESC, id ASC;
數(shù)據(jù)庫(kù)函數(shù)
多用在select和where后面。
MySQL單行函數(shù)
選出字符長(zhǎng)度
SELECT char_length(ip) FROM IP;
計(jì)算sin值
SELECT sin(1.57);
為日期添加一定時(shí)間
SELECT ADDDATE('1998-01-02', 3);
獲取當(dāng)前日期
SELECT CURDATE();
獲取當(dāng)前時(shí)間
SELECT curtime();
如果expr1=null,返回expr2,否則返回expr1
ifnull(expr1, expr2)
如果expr1=expr2,返回null,否則返回expr1
nullif(expr1, expr2)
類似于三目運(yùn)算符“:?”
if(expr1, expr2, expr3)
如果expr1為null,返回true,否則返回false
isnull(expr1)
選擇流程控制
CASE value
WHEN value1 THEN result1
WHEN value2 THEN result2
...
ELSE result
END
CASE
WHEN condition1 THEN result1
WHEN condition2 THEN result2
...
ELSE result
END
分組和組函數(shù)
將一組記錄作為整體計(jì)算,返回一個(gè)結(jié)果。
計(jì)算多行expr的平均值,數(shù)據(jù)類型必須是數(shù)值型。distinct不計(jì)算重復(fù)值;默認(rèn)all計(jì)算重復(fù)值
avg([distinct|all] expr)
計(jì)算多行expr的總條數(shù),數(shù)據(jù)類型可以是任意類型。*表示統(tǒng)計(jì)該表內(nèi)的記錄行數(shù);distinct不計(jì)算重復(fù)值
count({*|[distinct|all] expr})
計(jì)算多行expr的最大值
max(expr)
計(jì)算多行expr的最小值
min(expr)
計(jì)算多行expr的綜合
sum([distinct|all] expr)
group by分組
對(duì)記錄進(jìn)行顯示分組。
相同的記錄當(dāng)成一組,并過濾組having
SELECT * FROM ip GROUP BY ip HAVING count(*)>2;
多列的值完全相同時(shí)才會(huì)被當(dāng)成一組
SELECT count(*) FROM ip GROUP BY id, ip;
多表連接查詢
交叉連接
無(wú)需任何連接條件。
SELECT s.*, name FROM studentTable s CROSS JOIN teacherTable t;
自然連接
以兩個(gè)表中的同名列作為連接條件;若沒有同名列,則效果等同交叉連接。
SELECT s.*, name FROM studentTable s NATURAL JOIN teacherTable t;
using子句連接
顯式指定兩個(gè)表中的哪些同名列作為連接條件,要求必須有同名列;自然連接無(wú)法指定。
SELECT s.*, name FROM studentTable s JOIN teacherTable t USING(id);
on子句連接
每個(gè)on子句只能指定一個(gè)連接條件。如果需要進(jìn)行N表連接,則需要N-1個(gè)join...on對(duì)。
SELECT s.*, name FROM studentTable s JOIN teacherTable t ON s.teacher=t.id;
左、右、全外連接
分別使用left[outer]join、right[outer]join、full[outer]join,連接條件通過on子句指定。左外連接:把左邊表中所有不滿足連接條件的記錄全部列出。
右外連接:把右邊表中所有不滿足連接條件的記錄全部列出。
全外連接(MySQL不支持):把兩個(gè)表中所有不滿足連接條件的記錄全部列出。
SELECT s.*, name FROM studentTable s LEFT JOIN teacherTable t ON s.teacher=t.id;
子查詢
在查詢語(yǔ)句中嵌套另一個(gè)查詢,支持多層嵌套。出現(xiàn)在from語(yǔ)句后當(dāng)成數(shù)據(jù)表;
出現(xiàn)在where條件后作為過濾條件的值;
子查詢要用括號(hào)括起來(lái);
把子查詢當(dāng)成數(shù)據(jù)表時(shí),可以為該子查詢起別名。
SELECT * FROM (SELECT * FROM ip) t WHERE t.id>1;
SELECT * FROM ip WHERE id>(SELECT Sid FROM Stable WHERE Sname='SXF');
集合運(yùn)算兩個(gè)結(jié)果集所包含的數(shù)據(jù)列的數(shù)量必須相等。
兩個(gè)結(jié)果集所包含的數(shù)據(jù)列的數(shù)據(jù)類型也必須一一對(duì)應(yīng)。
union并運(yùn)算
SELECT 語(yǔ)句 UNION SELECT 語(yǔ)句;
minus差運(yùn)算
MySQL不支持,使用not in代替。
SELECT 語(yǔ)句 MINUS SELECT 語(yǔ)句;
SELECT XX FROM XX WHERE (XX, XX) NOT IN (XX, XX);
intersect交運(yùn)算
MySQL不支持,使用join...on代替。
SELECT 語(yǔ)句 INTERSECT SELECT 語(yǔ)句;
SELECT XX FROM XX JOIN XX ON (XX=XX) WHERE XX=XX;
JDBC的經(jīng)典用法
JDBC編程步驟
Java 連接 MySQL 需要驅(qū)動(dòng)包,最新版下載地址為:
1、加載數(shù)據(jù)庫(kù)驅(qū)動(dòng)
通常使用Class類的forName()靜態(tài)方法來(lái)加載驅(qū)動(dòng)。
Class.forName("com.mysql.ch.hdbc.Driver");
Class.forName("oracle.jdbc.driver.OracleDriver");
2、通過DriverManager獲取數(shù)據(jù)庫(kù)連接
DriverManager.getConnection("jdbc:mysql://hostname:port/databasename", "user", "pwd");
3、通過Connection對(duì)象創(chuàng)建Statement對(duì)象createStatement():創(chuàng)建基本的Statement對(duì)象;
prepareStatement(String sql):根據(jù)傳入的SQL語(yǔ)句創(chuàng)建預(yù)編譯的Statement對(duì)象;
prepareCall(String sql):根據(jù)傳入的SQL語(yǔ)句創(chuàng)建CallableStatement對(duì)象;
4、使用Statement執(zhí)行SQL語(yǔ)句execute():可以執(zhí)行任何SQL語(yǔ)句,但比較麻煩;
executeUpdate():主要用于執(zhí)行DML和DDL語(yǔ)句。執(zhí)行DML語(yǔ)句返回受SQL語(yǔ)句影響的行數(shù),執(zhí)行DDL語(yǔ)句返回0;
executeQuery():只能執(zhí)行查詢語(yǔ)句,執(zhí)行后返回代表查詢結(jié)果的ResultSet對(duì)象;
5、操作結(jié)果集next()、previous()、first()、last()、beforeFirst()、afterLast()、absolute()等移動(dòng)記錄指針的方法;
getXxx()方法獲取指針指向行、特定列的值。既可以使用列索引作為參數(shù),也可使用列名作為參數(shù)。
6、回收數(shù)據(jù)庫(kù)資源
示例:簡(jiǎn)單SQL查詢
package com.sxf.sql;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
public class Main {
public static void main(String[] args) throws Exception{
// 1、加載驅(qū)動(dòng),使用反射知識(shí)。 Class.forName("com.mysql.cj.jdbc.Driver");
try {
// 2、使用DriverManager獲取數(shù)據(jù)庫(kù)連接。 Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/tz_music?useSSL=false&serverTimezone=UTC",
"root", "1061700625");
// 3、使用Connection創(chuàng)建Statement對(duì)象。 Statement state = conn.createStatement();
// 4、執(zhí)行SQL語(yǔ)句。 // execute:可執(zhí)行任何SQL語(yǔ)句,返回一個(gè)boolean值 // executeQuery:執(zhí)行查詢語(yǔ)句,返回一個(gè)結(jié)果集 // executeUpdate:執(zhí)行DML語(yǔ)句,返回一個(gè)整數(shù) ResultSet res = state.executeQuery("select * from tz_music;");
// 5、獲取數(shù)據(jù)。 // next:將記錄指針下移一行,若有效則返回true // getXxx:通過列名或列索引獲取記錄指針 while (res.next()){
System.out.println(res.getString("music_name"));
}
}catch (Exception e){
e.printStackTrace();
}
}
}
執(zhí)行SQL語(yǔ)句的方法
使用executeLargeUpdate方法執(zhí)行DDL和DML語(yǔ)句
示例:讀取ini文件,連接并創(chuàng)建數(shù)據(jù)表
; mysql.ini文件
driver=com.mysql.cj.jdbc.Driver
url=jdbc:mysql://127.0.0.1:3306/tz_music?useSSL=false&serverTimezone=UTC
user=root
pwd=1061700625
package com.sxf.sql;
import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
class Sql{
private String driver;
private String url;
private String user;
private String pwd;
public void initParam(String paramFile) throws Exception{
var props = new Properties();
props.load(new FileInputStream(paramFile));
driver = props.getProperty("driver");
url = props.getProperty("url");
user = props.getProperty("user");
pwd = props.getProperty("pwd");
}
public void createTable(String sql) throws Exception{
Class.forName(driver);
try (
Connection conn = DriverManager.getConnection(url, user, pwd);
Statement state = conn.createStatement();
)
{
state.executeUpdate(sql);
}
}
}
public class Main {
public static void main(String[] args) throws Exception{
Sql sql = new Sql();
sql.initParam("mysql.ini");
sql.createTable("create table jdbc(id int primary key, name varchar(255));");
System.out.println("OK");
}
}
使用PreparedStatement執(zhí)行SQL語(yǔ)句
PreparedStatement的好處與作用:預(yù)編譯SQL語(yǔ)句,性能更好;
無(wú)需“拼接”SQL語(yǔ)句,編程更簡(jiǎn)單;
可以防止SQL注入,安全性更好。
示例:使用PreparedStatement插入記錄
class Sql
{
... ...
public void insertTable() throws Exception{
Class.forName(driver);
try (
Connection conn = DriverManager.getConnection(url, user, pwd);
PreparedStatement state = conn.prepareStatement("insert into jdbc values(?, ?);");
)
{
state.setInt(1, 1);
state.setString(2, "a");
state.executeUpdate();
state.setInt(1, 2);
state.setString(2, "a");
state.executeUpdate();
}
}
}
public class Main {
public static void main(String[] args) throws Exception{
Sql sql = new Sql();
sql.initParam("mysql.ini");
sql.insertTable();
System.out.println("OK");
}
}
使用CallableStatement調(diào)用存儲(chǔ)過程
調(diào)用存儲(chǔ)過程的SQL語(yǔ)句格式:{call 過程名(? ,?, ?...)},其中的問號(hào)作為存儲(chǔ)過程參數(shù)的占位符。
存儲(chǔ)過程的參數(shù)既有傳入?yún)?shù),也有傳出參數(shù)。傳入?yún)?shù):通過setXxx()方法為傳入?yún)?shù)設(shè)置值。
傳出參數(shù):調(diào)用registerOutParameter()方法注冊(cè)該參數(shù);通過getXxx()方法獲取指定傳出參數(shù)的值。
示例:調(diào)用存儲(chǔ)功能
public void callProc() {
try {
Class.forName(driver);
Connection conn= DriverManager.getConnection(url, user, pwd);
CallableStatement cstmt = conn.prepareCall("{call add_pro(?, ?, ?)}");
cstmt.setInt(1, 4);
cstmt.setInt(2, 5);
// 注冊(cè)第三個(gè)參數(shù)是int類型的輸出參數(shù) cstmt.registerOutParameter(3, Types.INTEGER);
cstmt.execute();
System.out.println(cstmt.getInt(3));
}catch (Exception e){
e.printStackTrace();
}
}
管理結(jié)果集
可滾動(dòng)、可更改的結(jié)果集
可滾動(dòng):可以使用方法自由移動(dòng)記錄指針的ResultSet。
可更新:可調(diào)用ResultSet的方法來(lái)修改記錄指針?biāo)赣涗洝⑻囟械闹怠?/p>
示例:創(chuàng)建可滾動(dòng)、可更改的結(jié)果集
public void query(String sql) throws Exception
{
Class.forName(driver);
try (
Connection conn = DriverManager.getConnection(url, user, pwd);
// 傳入控制結(jié)果集可滾動(dòng)、可更新的參數(shù) PreparedStatement state = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
ResultSet res = state.executeQuery();
)
{
res.last();
int rowCount = res.getRow();
for (int i = rowCount; i >0; i--) {
res.absolute(i);
System.out.println(res.getString(1)+" - "+res.getString(2));
res.updateString(2, "abc");
res.updateRow();
}
}
}
sql.query("select * from jdbc");
處理Blob類型數(shù)據(jù)Blob(Binary Long Object)二進(jìn)制長(zhǎng)對(duì)象,用于存儲(chǔ)大文件,典型的Blob內(nèi)容是一張圖片或一個(gè)聲音文件。
Blob數(shù)據(jù)插入數(shù)據(jù)庫(kù)需要使用PreparedStatement,該對(duì)象有一個(gè)方法:setBinaryStream(int index, InputStream x),該方法可以為指定參數(shù)傳入二進(jìn)制輸入流,從而可以實(shí)現(xiàn)將Blob數(shù)據(jù)保存到數(shù)據(jù)庫(kù)中。
調(diào)用ResultSet的getBlob(int index)方法可以從ResultSet里取出Blob數(shù)據(jù),該方法返回一個(gè)Blob對(duì)象。
Blob對(duì)象提供了getBinaryStream()方法來(lái)獲取該Blob數(shù)據(jù)的輸入流,也可以使用Blob對(duì)象提供的getBytes()方法直接取出該Blob對(duì)象封裝的二進(jìn)制數(shù)據(jù)。
建立數(shù)據(jù)表時(shí),創(chuàng)建一個(gè)mediumblob類型的數(shù)據(jù)列,用于保存圖片數(shù)據(jù)。
MySQL里數(shù)據(jù)庫(kù)里的blob類型最多只能存儲(chǔ)64KB內(nèi)容,而mediumblob類型可以存儲(chǔ)16MB的內(nèi)容。
示例:通過SQL的Blob存儲(chǔ)并讀取圖片數(shù)據(jù)
public void blobDemo(String fileName) throws Exception
{
Connection conn;
PreparedStatement state;
PreparedStatement query;
Class.forName(driver);
try {
conn = DriverManager.getConnection(url, user, pwd);
state = conn.prepareStatement("insert into jdbc values (?,?,?)", Statement.RETURN_GENERATED_KEYS);
query = conn.prepareStatement("select image from jdbc");
String imageName = fileName.substring(fileName.lastIndexOf('\\')+1, fileName.lastIndexOf('.'));
var f = new File(fileName);
var is = new FileInputStream(f);
state.setObject(1, 8);
state.setObject(2, "img");
state.setBinaryStream(3, is, (int)f.length());
int affect = state.executeUpdate();
System.out.println(affect);
ResultSet res = query.executeQuery();
if(res.next()){
Blob imgBlob = res.getBlob(3);
var out = imgBlob.getBinaryStream();
}
}catch (Exception e){
e.printStackTrace();
}
}
使用ResultSetMetaData分析結(jié)果集
描述其他數(shù)據(jù)的數(shù)據(jù),用以獲取關(guān)于ResultSet的描述信息。通過getMetaData()方法獲得ResultSetMetaData對(duì)象。需要一定的系統(tǒng)開銷。
三個(gè)常用方法:int getColumnCount():返回改ResultSet的列數(shù)量
String getColumnName(int column):返回指定索引的列名
int getColumnType(int column):返回指定索引的列類型
示例:分析結(jié)果集
public void metaData() throws Exception
{
Class.forName(driver);
Connection conn = DriverManager.getConnection(url, user, pwd);
Statement state = conn.createStatement();
ResultSet set = state.executeQuery("select * from jdbc");
ResultSetMetaData rsmd = set.getMetaData();
System.out.println(rsmd.getColumnCount());
System.out.println(rsmd.getColumnName(2));
System.out.println(rsmd.getColumnType(2));
}
使用RowSet包裝結(jié)果集
RowSet接口下包含jdbcRowSet、CachedRowSet、FilteredRowSet、JoinRowSet、WebRowSet常用子接口。
jdbcRowSet需要保持與數(shù)據(jù)庫(kù)的連接;其余4個(gè)是離線的RowSet,無(wú)需保持連接。
RowSetFactory和RowSet
RowSet常用方法:
setUrl(String url)、setUsername(String name)、setPassword(String pwd)、setCommand(String sql)、execute()
示例:通過RowSetFactory使用jdbcRowSet
public void update(String sql) throws Exception
{
Class.forName(driver);
// 創(chuàng)建RowSetFactory RowSetFactory factory = RowSetProvider.newFactory();
// 創(chuàng)建實(shí)例 JdbcRowSet jdbcRs = factory.createJdbcRowSet();
// 設(shè)置連接信息 jdbcRs.setUrl(url);
jdbcRs.setUsername(user);
jdbcRs.setPassword(pwd);
jdbcRs.setCommand(sql);
// 執(zhí)行查詢 jdbcRs.execute();
jdbcRs.afterLast();
// 向前滾動(dòng)結(jié)果集 while (jdbcRs.previous()){
System.out.println(jdbcRs.getString(1));
// 修改記錄行 jdbcRs.updateString(2, "123");
// 提交修改 jdbcRs.updateRow();
}
}
離線RowSet
直接將底層數(shù)據(jù)讀入內(nèi)存中,封裝成RowSet對(duì)象,而RowSet對(duì)象完全可以當(dāng)成Java Bean來(lái)使用。
示例:CachedRowSet離線操作SQL
public void query(String sql) throws Exception
{
Class.forName(driver);
// 獲取數(shù)據(jù)庫(kù)連接 Connection conn = DriverManager.getConnection(url, user, pwd);
Statement stmt = conn.createStatement();
ResultSet res = stmt.executeQuery(sql);
// 創(chuàng)建RowSetFactory RowSetFactory factory = RowSetProvider.newFactory();
// 創(chuàng)建實(shí)例 CachedRowSet cachedRs = factory.createCachedRowSet();
// 裝填RowSet cachedRs.populate(res);
// 關(guān)閉資源 res.close();
stmt.close();
conn.close();
cachedRs.afterLast();
// 重新獲取數(shù)據(jù)庫(kù)連接 Connection conn2 = DriverManager.getConnection(url, user, pwd);
conn2.setAutoCommit(false);
// 把對(duì)RowSet所做的修改同步到底層數(shù)據(jù)庫(kù) cachedRs.acceptChanges(conn2);
}
事務(wù)處理
事務(wù)的概念
事務(wù)ACID特性:原子性atomicity、一致性consistency、隔離性isolation、持續(xù)性durability
事務(wù)提交:顯示提交:使用commit
自動(dòng)提交:執(zhí)行DDL或DCL語(yǔ)句,或程序正常退出
事務(wù)回滾:顯式回滾:使用rollback
自動(dòng)回滾:系統(tǒng)錯(cuò)誤,或強(qiáng)行退出
普通的提交、回滾都會(huì)結(jié)束當(dāng)前事務(wù),但回滾到指定中間點(diǎn)因?yàn)橐廊惶幱谑聞?wù)之中,所以不會(huì)結(jié)束當(dāng)前事務(wù)。
JDBC事務(wù)支持
調(diào)動(dòng)Connection的setAutoCommit()方法來(lái)關(guān)閉自動(dòng)提交,開啟事務(wù)。
當(dāng)Connection遇到一個(gè)未處理的SQLException異常時(shí),系統(tǒng)將會(huì)非正常退出,事務(wù)也會(huì)自動(dòng)回滾。但如果程序捕獲了該異常,則需要再異常處理塊中顯式地回滾事務(wù)。
// 關(guān)閉自動(dòng)提交,開啟事務(wù) conn.setAutoCommit(false);
// 提交事務(wù) conn.commit();
// 回滾事務(wù) conn.rollback();
// 創(chuàng)建保存點(diǎn) point = conn.setSavePoint();
// 回滾到保存點(diǎn) conn.rollback(point);
使用批量更新多條SQL語(yǔ)句將被作為一批操作被同時(shí)收集,同時(shí)提交。
使用批量更新也需要先創(chuàng)建一個(gè)Statement對(duì)象,然后利用該對(duì)象的addBatch()方法將多條SQL語(yǔ)句同時(shí)收集起來(lái),最后調(diào)用Statement對(duì)象的executeLargeBatch()或executeBatch()方法同時(shí)執(zhí)行這些SQL語(yǔ)句。
如果在批量更新的addBatch()方法中添加select查詢語(yǔ)句,程序?qū)⒅苯映霈F(xiàn)錯(cuò)誤。
為了讓批量操作可以正確地處理錯(cuò)誤,必須把批量執(zhí)行的操作視為單個(gè)事務(wù),如果批量更新在執(zhí)行過程中失敗,則讓事務(wù)回滾到批量操作開始之前的狀態(tài)。薇樂大道這種效果,程序應(yīng)該在開始批量操作之前先關(guān)閉自動(dòng)提交,然后開始收集更新語(yǔ)句,當(dāng)批量操作執(zhí)行結(jié)束后,提交事務(wù),并恢復(fù)之前的自動(dòng)提交模式。
Statement stmt = conn.createStatement();
stmt.addBatch(sql1);
stmt.addBatch(sql2);
stmt.addBatch(sql3);
... ...
stmt.executeLargeBatch();
總結(jié)
以上是生活随笔為你收集整理的jdbc和mysql做游戏排行榜_MySQL数据库与JDBC编程的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MapReduce操作时Error:Th
- 下一篇: logstash mysql增量_Log