MySQL與JDBC

1、 對數據庫的操做

1. 建立一個庫

create database 庫名java

create database 庫名 character set 編碼mysql

2. 刪除一個庫

drop database 庫名web

3. 使用庫

use 庫名面試

2、對數據庫表的操做

1.建立一張表

create table 表名(sql

字段名 類型(長度) [約束],數據庫

字段名 類型(長度) [約束],數組

字段名 類型(長度) [約束]瀏覽器

);服務器

 

 

2.查看數據庫表

建立完成後,咱們能夠查看數據庫表eclipse

show tables;

 

 

查看錶的結構

desc 表名

 

3.刪除一張表

drop table 表名

 

 

4.修改表

4.1 添加一列

alter table 表名 add 字段名 類型(長度) [約束]

 

 

4.2 修改列的類型(長度、約束)

alter table 表名 modify 要修改的字段名 類型(長度) [約束]

 

 

4.3 修改列的列名

alter table 表名 change 舊列名 新列名 類型(長度) [約束]

 

 

4.4 刪除表的列

alter table 表名 drop 列名

 

 

4.5 修改表名

rename table 表名 to 新表名

 

 

4.6 修改表的字符集

alter table 表名 character set 編碼 

3、對數據庫表記錄進行操做(修改)

 

1.插入記錄

insert into 表名(列名1,列名2,列名3……) values(1,2,3……)

 

 

insert into 表名 values(1,2,3……)

 

 

1.1 插入數據中文亂碼問題解決辦

set names gbk;

 

 

2.修改表記錄

2.1 不帶條件的

update 表名 set 字段名=, 字段名=, 字段名=……

 

它會將該列的全部記錄都更改

 

2.2 帶條件的

update 表名 set字段名=, 字段名=, 字段名=…… where 條件

 

3.刪除表記錄

3.1 帶條件的

delete from 表名 where 條件

 

注意,刪除後,uid不會重置!

 

3.2.不帶條件的

先準備數據

insert into tbl_user values(null,’老王’,’666’);

 

刪除操做

delete from 表名;

 

 

3.3 面試題

說說deletetruncate的區別?

delete刪除的時候是一條一條的刪除記錄,它配合事務,能夠將刪除的數據找回。

truncate刪除,它是將整個表摧毀,而後再建立一張如出一轍的表。它刪除的數據沒法找回。

 

注意:delete刪除,uid不會重置!而使用truncate操做,uid會重置

 

 

4.查詢操做

語法:

select [distinct] *| 列名,列名 from 表名 [where條件]

4.1 簡單查詢

1.查詢全部商品

select * from product

 

2. 查詢商品名和商品價格

select pname,price from product;

 

3.查詢全部商品信息使用表別名

select * from product as p;

 

4.查詢商品名,使用列別名

select pname as p from product

 

5.去掉重複值(按照價格)

select distinct(price) from product;

 

先準備數據:

insert into product values (null,'李士雪',38,null);

 

6.將全部的商品的價格+10進行顯示

select pname,price+10 from product;

4.2 分組操做

1.添加分類id (alter table product add cid varchar(32);)

2.初始化數據

update product set cid='1';

update product set cid='2' where  pid in (5,6,7);

 

1.根據cid字段分組,分組後統計商品的個數。

 

2.根據cid分組,分組統計每組商品的平均價格,而且平均價格大於20000元。

4.3 查詢總結

select  通常在的後面的內容都是要查詢的字段

from  要查詢到表

where

group by

having  分組後帶有條件只能使用having

order by 它必須放到最後面

 

2、回顧JDBC,完成查詢

1 什麼是JDBC

  JDBC(Java DataBase Connectivity)就是Java數據庫鏈接,說白了就是用Java語言來操做數據庫。原來咱們操做數據庫是在控制檯使用SQL語句來操做數據庫,JDBC是用Java語言向數據庫發送SQL語句。

2 JDBC

早期SUN公司的天才們想編寫一套能夠鏈接天下全部數據庫的API,可是當他們剛剛開始時就發現這是不可完成的任務,由於各個廠商的數據庫服務器差別太大了。後來SUN開始與數據庫廠商們討論,最終得出的結論是,由SUN提供一套訪問數據庫的規範(就是一組接口),並提供鏈接數據庫的協議標準,而後各個數據庫廠商會遵循SUN的規範提供一套訪問本身公司的數據庫服務器的API出現。SUN提供的規範命名爲JDBC,而各個廠商提供的,遵循了JDBC規範的,能夠訪問本身數據庫的API被稱之爲驅動!

 

JDBC是接口,而JDBC驅動纔是接口的實現,沒有驅動沒法完成數據庫鏈接!每一個數據庫廠商都有本身的驅動,用來鏈接本身公司的數據庫。

固然還有第三方公司專門爲某一數據庫提供驅動,這樣的驅動每每不是開源免費的!

 

3 JDBC核心類(接口)介

JDBC中的核心類有:DriverManager、Connection、Statement,和ResultSet!

DriverManger(驅動管理器)的做用有兩個:

l 註冊驅動:這可讓JDBC知道要使用的是哪一個驅動;

l 獲取Connection:若是能夠獲取到Connection,那麼說明已經與數據庫鏈接上了。

Connection對象表示鏈接,與數據庫的通信都是經過這個對象展開的:

l Connection最爲重要的一個方法就是用來獲取Statement對象;

l Statement是用來向數據庫發送SQL語句的,這樣數據庫就會執行發送過來的SQL語句

l void executeUpdate(String sql):執行更新操做(insert、update、delete等);

l ResultSet executeQuery(String sql):執行查詢操做,數據庫在執行查詢後會把查詢結果,查詢結果就是ResultSet;

ResultSet對象表示查詢結果集,只有在執行查詢操做後纔會有結果集的產生。結果集是一個二維的表格,有行有列。操做結果集要學習移動ResultSet內部的「行光標」,以及獲取當前行上的每一列上的數據:

l boolean next():使「行光標」移動到下一行,並返回移動後的行是否存在;

l XXX getXXX(int col):獲取當前行指定列上的值,參數就是列數,列數從1開始,而不是0。

 

4 Hello JDBC

 下面開始編寫第一個JDBC程序

 

介紹eclipse的相關知識

單元測試junit

4.1 導入mysql數據庫的驅動jar包:

mysql-connector-java-5.1.39-bin.jar

4.2 註冊驅

看清楚了,註冊驅動就只有一句話:Class.forName(「com.mysql.jdbc.Driver」),下面的內容都是對這句代碼的解釋。從此咱們的代碼中,與註冊驅動相關的代碼只有這一句。

DriverManager類的registerDriver()方法的參數是java.sql.Driver,但java.sql.Driver是一個接口,實現類由mysql驅動來提供,mysql驅動中的java.sql.Driver接口的實現類爲com.mysql.jdbc.Driver!那麼註冊驅動的代碼以下:

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

上面代碼雖然能夠註冊驅動,可是出現硬編碼(代碼依賴mysql驅動jar包),若是未來想鏈接Oracle數據庫,那麼必需要修改代碼的。而且其實這種註冊驅動的方式是註冊了兩次驅動!

JDBC中規定,驅動類在被加載時,須要本身「主動」把本身註冊到DriverManger中,下面咱們來看看com.mysql.jdbc.Driver類的源代碼:

com.mysql.jdbc.Driver.java

public class Driver extends NonRegisteringDriver implements java.sql.Driver {

static {

try {

java.sql.DriverManager.registerDriver(new Driver());

} catch (SQLException E) {

throw new RuntimeException("Can't register driver!");

}

}

……

}

 

com.mysql.jdbc.Driver類中的static塊會建立本類對象,並註冊到DriverManager中。這說明只要去加載com.mysql.jdbc.Driver類,那麼就會執行這個static塊,從而也就會把com.mysql.jdbc.Driver註冊到DriverManager中,因此能夠把註冊驅動類的代碼修改成加載驅動類

Class.forName(「com.mysql.jdbc.Driver」);

4.3 獲取鏈接

獲取鏈接須要兩步,一是使用DriverManager來註冊驅動,二是使用DriverManager來獲取Connection對象。

 

獲取鏈接的也只有一句代碼:

DriverManager.getConnection(url,username,password),

其中username和password是登陸數據庫的用戶名和密碼,若是我沒說錯的話,你的mysql數據庫的用戶名和密碼分別是:root、123。

url查對複雜一點,它是用來找到要鏈接數據庫「網址」,就比如你要瀏覽器中查找百度時,也須要提供一個url。下面是mysql的url:

jdbc:mysql://localhost:3306/mydb1

JDBC規定url的格式由三部分組成,每一個部分中間使用冒號分隔。

l 第一部分是jdbc,這是固定的;

l 第二部分是數據庫名稱,那麼鏈接mysql數據庫,第二部分固然是mysql了;

l 第三部分是由數據庫廠商規定的,咱們須要瞭解每一個數據庫廠商的要求,mysql的第三部分分別由數據庫服務器的IP地址(localhost)、端口號(3306),以及DATABASE名稱(mydb1)組成。

  

下面是獲取鏈接的語句:

Connection con = DriverManager.getConnection(「jdbc:mysql://localhost:3306/web08」,」root」,」root」);

 

還能夠在url中提供參數:

jdbc:mysql://localhost:3306/web08?useUnicode=true&characterEncoding=UTF8

useUnicode參數指定這個鏈接數據庫的過程當中,使用的字節集是Unicode字節集;

characherEncoding參數指定穿上鍊接數據庫的過程當中,使用的字節集編碼爲UTF-8編碼。請注意,mysql中指定UTF-8編碼是給出的是UTF8,而不是UTF-8。要當心了!

 

4.4 獲取Statement

在獲得Connectoin以後,說明已經與數據庫鏈接上了,下面是經過Connection獲取Statement對象的代碼:

Statement stmt = con.createStatement();

Statement是用來向數據庫發送要執行的SQL語句的!

4.5 發送SQL查詢語句

String sql = 「select * from user」;

ResultSet rs = stmt.executeQuery(sql);

注意,執行查詢使用的不是executeUpdate()方法,而是executeQuery()方法。executeQuery()方法返回的是ResultSet,ResultSet封裝了查詢結果,咱們稱之爲結果集。

4.6 讀取結果集中的數據

ResultSet就是一張二維的表格,它內部有一個「行光標」,光標默認的位置在「第一行上方」,咱們能夠調用rs對象的next()方法把「行光標」向下移動一行,當第一次調用next()方法時,「行光標」就到了第一行記錄的位置,這時就可使用ResultSet提供的getXXX(int col)方法來獲取指定列的數據了:

rs.next();//光標移動到第一行

rs.getInt(1);//獲取第一行第一列的數據

當你使用rs.getInt(1)方法時,你必須能夠確定第1列的數據類型就是int類型,若是你不能確定,那麼最好使用rs.getObject(1)。在ResultSet類中提供了一系列的getXXX()方法,比較經常使用的方法有:

Object getObject(int col)

String getString(int col)

int getInt(int col)

double getDouble(int col)

4.7 關閉

與IO流同樣,使用後的東西都須要關閉!關閉的順序是先獲得的後關閉,後獲得的先關閉。

rs.close();

stmt.close();

con.close();

4.8 完成查詢操做代碼 

public static Connection getConnection() throws Exception {

Class.forName("com.mysql.jdbc.Driver");

String url = "jdbc:mysql://localhost:3306/web08";

return DriverManager.getConnection(url, "root", "root");

}

@Test

public void query() throws Exception {

Connection con = getConnection();

Statement stmt = con.createStatement();

String sql = "select * from user";

ResultSet rs = stmt.executeQuery(sql);

while(rs.next()) {

String username = rs.getString(1);

String password = rs.getString(2);

System.out.println(username + ", " + password);

}

}

 

4.9 規範化代碼

所謂規範化代碼就是不管是否出現異常,都要關閉ResultSet、Statement,以及Connection,若是你還記得IO流的規範化代碼,那麼下面的代碼你就明白什麼意思了。

 

@Test

public void query() {

Connection con = null;

Statement stmt = null;

ResultSet rs = null;

try {

con = getConnection();

stmt = con.createStatement();

String sql = "select * from user";

rs = stmt.executeQuery(sql);

while(rs.next()) {

String username = rs.getString(1);

String password = rs.getString(2);

System.out.println(username + ", " + password);

}

} catch(Exception e) {

throw new RuntimeException(e);

} finally {

try {

if(rs != null) rs.close();

if(stmt != null) stmt.close();

if(con != null) con.close();

} catch(SQLException e) {}

}

}

 

JDBC對象介紹

 

1 JDBC中的主要類(接口

在JDBC中經常使用的類有:

l DriverManager;

l Connection;

l Statement;

l ResultSet。

 

2 DriverManager

其實咱們從此只須要會用DriverManager的getConnection()方法便可:

Class.forName(「com.mysql.jdbc.Driver」);//註冊驅動

String url = 「jdbc:mysql://localhost:3306/web08」;

String username = 「root」;

String password = 「root」;

Connection con = DriverManager.getConnection(url, username, password);

 

注意,上面代碼可能出現的兩種異常:

ClassNotFoundException:這個異常是在第1句上出現的,出現這個異常有兩個可能:

l 你沒有給出mysql的jar包;

l 你把類名稱打錯了,查看類名是否是com.mysql.jdbc.Driver。

 

SQLException:這個異常出如今第5句,出現這個異常就是三個參數的問題,每每username和password通常不是出錯,因此須要認真查看url是否打錯。

 

對於DriverManager.registerDriver()方法瞭解便可,由於咱們從此註冊驅動只會Class.forName(),而不會使用這個方法。

3 Connection

Connection最爲重要的方法就是獲取Statement:

l Statement stmt = con.createStatement();

 

後面在學習ResultSet方法時,還要學習一下下面的方法:

l Statement stmt = con.createStatement(int,int);

 

4 Statement

Statement最爲重要的方法是:

l int executeUpdate(String sql):執行更新操做,即執行insert、update、delete語句,其實這個方法也能夠執行create table、alter table,以及drop table等語句,但咱們不多會使用JDBC來執行這些語句;

l ResultSet executeQuery(String sql):執行查詢操做,執行查詢操做會返回ResultSet,即結果集。

 

l   boolean execute()

Statement還有一個boolean execute()方法,這個方法能夠用來執行增、刪、改、查全部SQL語句。該方法返回的是boolean類型,表示SQL語句是否執行成功。

若是使用execute()方法執行的是更新語句,那麼還要調用int getUpdateCount()來獲取insert、update、delete語句所影響的行數。

若是使用execute()方法執行的是查詢語句,那麼還要調用ResultSet getResultSet()來獲取select語句的查詢結果。

 

5 ResultSet之滾動結果集(瞭解

ResultSet表示結果集,它是一個二維的表格!ResultSet內部維護一個行光標(遊標),ResultSet提供了一系列的方法來移動遊標:

l void beforeFirst():把光標放到第一行的前面,這也是光標默認的位置;

l void afterLast():把光標放到最後一行的後面;

l boolean first():把光標放到第一行的位置上,返回值表示調控光標是否成功;

l boolean last():把光標放到最後一行的位置上;

l boolean isBeforeFirst():當前光標位置是否在第一行前面;

l boolean isAfterLast():當前光標位置是否在最後一行的後面;

l boolean isFirst():當前光標位置是否在第一行上;

l boolean isLast():當前光標位置是否在最後一行上;

l boolean previous():把光標向上挪一行;

l boolean next():把光標向下挪一行;

l boolean relative(int row):相對位移,當row爲正數時,表示向下移動row行,爲負數時表示向上移動row行;

l boolean absolute(int row):絕對位移,把光標移動到指定的行上;

l int getRow():返回當前光標全部行。

 

上面方法分爲兩類,一類用來判斷遊標位置的,另外一類是用來移動遊標的。若是結果集是不可滾動的,那麼只能使用next()方法來移動遊標,而beforeFirst()、afterLast()、first()、last()、previous()、relative()方法都不能使用!!!

結果集是否支持滾動,要從Connection類的createStatement()方法提及。也就是說建立的Statement決定了使用Statement建立的ResultSet是否支持滾動。

Statement createStatement(int resultSetType, int resultSetConcurrency)

resultSetType的可選值:

l ResultSet.TYPE_FORWARD_ONLY:不滾動結果集;

l ResultSet.TYPE_SCROLL_INSENSITIVE:滾動結果集,但結果集數據不會再跟隨數據庫而變化;

l ResultSet.TYPE_SCROLL_SENSITIVE:滾動結果集,但結果集數據不會再跟隨數據庫而變化;

 

能夠看出,若是想使用滾動的結果集,咱們應該選擇TYPE_SCROLL_INSENSITIVE!其實不多有數據庫驅動會支持TYPE_SCROLL_SENSITIVE的特性!一般咱們也不須要查詢到的結果集再受到數據庫變化的影響。

 

resultSetConcurrency的可選值:

CONCUR_READ_ONLY:結果集是隻讀的,不能經過修改結果集而反向影響數據庫;

l CONCUR_UPDATABLE:結果集是可更新的,對結果集的更新能夠反向影響數據庫。

 

一般可更新結果集這一「高級特性」咱們也是不須要的! 

 

獲取滾動結果集的代碼以下:

Connection con = …

Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, CONCUR_READ_ONLY);

String sql = …//查詢語句

ResultSet rs = stmt.executeQuery(sql);//這個結果集是可滾動的

 

6 ResultSet之獲取列數

能夠經過next()方法使ResultSet的遊標向下移動,當遊標移動到你須要的行時,就須要來獲取該行的數據了,ResultSet提供了一系列的獲取列數據的方法:

l String getString(int columnIndex):獲取指定列的String類型數據;

l int getInt(int columnIndex):獲取指定列的int類型數據;

l double getDouble(int columnIndex):獲取指定列的double類型數據;

l boolean getBoolean(int columnIndex):獲取指定列的boolean類型數據;

l Object getObject(int columnIndex):獲取指定列的Object類型的數據。

 

上面方法中,參數columnIndex表示列的索引,列索引從1開始,而不是0,這第一點與數組不一樣。若是你清楚當前列的數據類型,那麼可使用getInt()之類的方法來獲取,若是你不清楚列的類型,那麼你應該使用getObject()方法來獲取。

ResultSet還提供了一套經過列名稱來獲取列數據的方法:

l String getString(String columnName):獲取名稱爲columnName的列的String數據;

l int getInt(String columnName):獲取名稱爲columnName的列的int數據;

l double getDouble(String columnName):獲取名稱爲columnName的列的double數據;

l boolean getBoolean(String columnName):獲取名稱爲columnName的列的boolean數據;

l Object getObject(String columnName):獲取名稱爲columnName的列的Object數據;

 

PreparedStatement

1 什麼是SQL

在須要用戶輸入的地方,用戶輸入的是SQL語句的片斷,最終用戶輸入的SQL片斷與咱們DAO中寫的SQL語句合成一個完整的SQL語句!例如用戶在登陸時輸入的用戶名和密碼都是爲SQL語句的片斷!

 

2 演示SQL

首先咱們須要建立一張用戶表,用來存儲用戶的信息。

CREATE TABLE user(

uidCHAR(32) PRIMARY KEY,

usernameVARCHAR(30) UNIQUE KEY NOT NULL,

PASSWORD VARCHAR(30)

);

 

INSERT INTO user VALUES('U_1001', 'zs', 'zs');

SELECT * FROM user;

如今用戶表中只有一行記錄,就是zs。

下面咱們寫一個login()方法!

public void login(String username, String password) {

Connection con = null;

Statement stmt = null;

ResultSet rs = null;

try {

con = JdbcUtils.getConnection();

stmt = con.createStatement();

String sql = "SELECT * FROM user WHERE " +

"username='" + username +

"' and password='" + password + "'";

rs = stmt.executeQuery(sql);

if(rs.next()) {

System.out.println("歡迎" + rs.getString("username"));

} else {

System.out.println("用戶名或密碼錯誤!");

}

} catch (Exception e) {

throw new RuntimeException(e);

} finally {

JdbcUtils.close(con, stmt, rs);

}

}

 

下面是調用這個方法的代碼:

login("a' or 'a'='a", "a' or 'a'='a");

 

這行當前會使咱們登陸成功!由於是輸入的用戶名和密碼是SQL語句片斷,最終與咱們的login()方法中的SQL語句組合在一塊兒!咱們來看看組合在一塊兒的SQL語句:

SELECT * FROM tab_user WHERE username='a' or 'a'='a' and password='a' or 'a'='a'

 

3 防止SQL

l 過濾用戶輸入的數據中是否包含非法字符;

l 分步校驗!先使用用戶名來查詢用戶,若是查找到了,再比較密碼;

l 使用PreparedStatement。

4 PreparedStatement是什麼

PreparedStatement叫預編譯聲明!

PreparedStatement是Statement的子接口,你可使用PreparedStatement來替換Statement。

PreparedStatement的好處:

l 防止SQL攻擊;

提升代碼的可讀性,以可維護性;

l 提升效率。

5 PreparedStatement的使

l 使用Connection的prepareStatement(String sql):即建立它時就讓它與一條SQL模板綁定;

l 調用PreparedStatement的setXXX()系列方法爲問號設置值

l 調用executeUpdate()或executeQuery()方法,但要注意,調用沒有參數的方法;

 

String sql = 「select * from tab_student where s_number=?」;

PreparedStatement pstmt = con.prepareStatement(sql);

pstmt.setString(1, 「S_1001」);

ResultSet rs = pstmt.executeQuery();

rs.close();

pstmt.clearParameters();

pstmt.setString(1, 「S_1002」);

rs = pstmt.executeQuery();

 

在使用Connection建立PreparedStatement對象時須要給出一個SQL模板,所謂SQL模板就是有「?」的SQL語句,其中「?」就是參數。

在獲得PreparedStatement對象後,調用它的setXXX()方法爲「?」賦值,這樣就能夠獲得把模板變成一條完整的SQL語句,而後再調用PreparedStatement對象的executeQuery()方法獲取ResultSet對象。

注意PreparedStatement對象獨有的executeQuery()方法是沒有參數的,而Statement的executeQuery()是須要參數(SQL語句)的。由於在建立PreparedStatement對象時已經讓它與一條SQL模板綁定在一塊兒了,因此在調用它的executeQuery()和executeUpdate()方法時就再也不須要參數了。

PreparedStatement最大的好處就是在於重複使用同一模板,給予其不一樣的參數來重複的使用它。這纔是真正提升效率的緣由。

 

因此,建議你們在從此的開發中,不管什麼狀況,都去須要PreparedStatement,而不是使用Statement。

相關文章
相關標籤/搜索