文章目錄
來源於how2j
建立連接
導入Mysql-jdbc的jar包
初始化驅動
- 通過Class.forName(“com.mysql.jdbc.Driver”);
- 初始化驅動類com.mysql.jdbc.Driver;就在 mysql-connector-java-5.0.8-bin.jar中
- 如果忘記了第一個步驟的導包,就會拋出ClassNotFoundException
- Class.forName是把這個類加載到JVM中,加載的時候,就會執行其中的靜態初始化塊,完成驅動的初始化的相關工作。
- 代碼:
package jdbc;
public class TestJDBC {
public static void main(String[] args) {
//初始化驅動
try {
//驅動類com.mysql.jdbc.Driver
//就在 mysql-connector-java-5.0.8-bin.jar中
//如果忘記了第一個步驟的導包,就會拋出ClassNotFoundException
Class.forName("com.mysql.jdbc.Driver");
System.out.println("數據庫驅動加載成功 !");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- res:
建立與數據庫的連接
- 建立與數據庫的Connection連接
- 這裏需要提供:
數據庫所處於的ip:127.0.0.1 (本機)
數據庫的端口號: 3306 (mysql專用端口號)
數據庫名稱 how2java
編碼方式 UTF-8
賬號 root
密碼 admin
- 代碼:
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
public class TestJDBC {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
// 建立與數據庫的Connection連接
// 這裏需要提供:
// 數據庫所處於的ip:127.0.0.1 (本機)
// 數據庫的端口號: 3306 (mysql專用端口號)
// 數據庫名稱 how2java
// 編碼方式 UTF-8
// 賬號 root
// 密碼 admin
Connection c = DriverManager
.getConnection(
"jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
"root", "admin");
System.out.println("連接成功,獲取連接對象: " + c);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- res:
創建Statement
- Statement是用於執行SQL語句的,比如增加,刪除
- 代碼:
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection c = DriverManager
.getConnection(
"jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
"root", "admin");
// 注意:使用的是 java.sql.Statement
// 不要不小心使用到: com.mysql.jdbc.Statement;
Statement s = c.createStatement();
System.out.println("獲取 Statement對象: " + s);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- res:
執行SQL語句
-s.execute
執行sql語句;執行成功後,用mysql-front進行查看,明確插入成功
- 代碼:
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
Connection c = DriverManager
.getConnection(
"jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
"root", "admin");
Statement s = c.createStatement();
// 準備sql語句
// 注意: 字符串要用單引號'
String sql = "insert into hero values(null,"+"'提莫'"+","+313.0f+","+50+")";
s.execute(sql);
System.out.println("執行插入語句成功");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
關閉連接
- 數據庫的連接是有限資源,相關操作結束後,養成關閉數據庫的好習慣
- 先關閉Statement
- 後關閉Connection
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC {
public static void main(String[] args) {
Connection c = null;
Statement s = null;
try {
Class.forName("com.mysql.jdbc.Driver");
c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8", "root",
"admin");
s = c.createStatement();
String sql = "insert into hero values(null," + "'提莫'" + "," + 313.0f + "," + 50 + ")";
s.execute(sql);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
// 數據庫的連接時有限資源,相關操作結束後,養成關閉數據庫的好習慣
// 先關閉Statement
if (s != null)
try {
s.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 後關閉Connection
if (c != null)
try {
c.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
JDBC的增刪改
增
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try (
Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
"root", "admin");
Statement s = c.createStatement();
)
{
String sql = "insert into hero values(null," + "'提莫'" + "," + 313.0f + "," + 50 + ")";
s.execute(sql);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
刪除
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try (
Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
"root", "admin");
Statement s = c.createStatement();
)
{
String sql = "delete from hero where id = 5";
s.execute(sql);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
修改
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try (
Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
"root", "admin");
Statement s = c.createStatement();
)
{
String sql = "update hero set name = 'name 5' where id = 3";
s.execute(sql);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
通用方法
- 設計一個方法:
public static void execute(String sql)
:方法接受的參數是SQL語句,無論是增加,刪除,還是修改,都調用這個方法,每次傳不同的SQL語句作爲參數 - 代碼:
public static void execule(String sql)
{
Connection c = null;
Statement s = null;
try
{
Class.forName("com.mysql.jdbc.Driver");
c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root","admin");
s = c.createStatement();
s.execute(sql);
System.out.println("操作成功!");
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
catch (SQLException e)
{
e.printStackTrace();
}
finally
{
if(s != null)
{
try
{
s.close();
}
catch(SQLException e)
{
e.printStackTrace();
}
}
if(c != null)
{
try
{
c.close();
}
catch(SQLException e)
{
e.printStackTrace();
}
}
}
}
查詢
利用ResultSet接收返回值
- 代碼:
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
"root", "admin"); Statement s = c.createStatement();) {
String sql = "select * from hero";
// 執行查詢語句,並把結果集返回給ResultSet
ResultSet rs = s.executeQuery(sql);
while (rs.next()) {
int id = rs.getInt("id");// 可以使用字段名
String name = rs.getString(2);// 也可以使用字段的順序
float hp = rs.getFloat("hp");
int damage = rs.getInt(4);
System.out.printf("%d\t%s\t%f\t%d%n", id, name, hp, damage);
}
// 不一定要在這裏關閉ReultSet,因爲Statement關閉的時候,會自動關閉ResultSet
// rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- res:
SQL語句判斷賬號密碼是否正確
-
判斷賬號密碼的正確方式是根據賬號和密碼到表中去找數據,如果有數據,就表明密碼正確了,如果沒數據,就表明密碼錯誤。
-
不恰當的方式 是把uers表的數據全部查到內存中,挨個進行比較。 如果users表裏有100萬條數據呢? 內存都不夠用的。
-
代碼:
try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
"root", "admin");
Statement s = c.createStatement();
) {
String name = "dashen";
//正確的密碼是:thisispassword
String password = "thisispassword1";
String sql = "select * from user where name = '" + name +"' and password = '" + password+"'";
// 執行查詢語句,並把結果集返回給ResultSet
ResultSet rs = s.executeQuery(sql);
if(rs.next())
System.out.println("賬號密碼正確");
else
System.out.println("賬號密碼錯誤");
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
- 即sql找到了結果 ResultSet裏纔有next對象
- res:
找到總數
- 設計一個方法,進行分頁查詢:
public static void list(int start, int count)
:start 表示開始頁數,count表示一頁顯示的總數;list(0,5) 表示第一頁,一共顯示5條數據;list(10,5) 表示第三頁,一共顯示5條數據 - 代碼:
String sql = "select count(*) from hero";
ResultSet rs = s.executeQuery(sql);
int total = 0;
while (rs.next()) {
total = rs.getInt(1);//字段順序
}
分頁查詢
- 代碼:
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestJDBC {
public static void main(String[] args) {
list(0, 5);
System.out.println();
list(5, 10);
}
public static void list(int start, int count) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
}
Connection c = null;
try {
c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8"
,"root","admin");
Statement s = c.createStatement();
String str = "select * from hero limit "+start+","+count;
ResultSet rs = s.executeQuery(str);
while(rs.next()) {
int id = rs.getInt(1);
String name = rs.getString(2);
float hp = rs.getFloat(3);
int damage = rs.getInt(4);
System.out.printf("%d \t %s \t %f \t %d %n",id,name,hp,damage);
}
} catch (SQLException e) {
// TODO 自動生成的 catch 塊
e.printStackTrace();
}
}
}
- res:
PreparedStatement
PreparedStatement的使用
- 和 Statement一樣,PreparedStatement也是用來執行sql語句的
- 與創建Statement不同的是,需要根據sql語句創建PreparedStatement
- 除此之外,還能夠通過設置參數,指定相應的值,而不是Statement那樣使用字符串拼接
- 代碼:
package jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class TestJDBC {
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String sql = "insert into hero values(null,?,?,?)";
try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
// 根據sql語句創建PreparedStatement
PreparedStatement ps = c.prepareStatement(sql);
) {
// 設置參數
ps.setString(1, "提莫");
ps.setFloat(2, 313.0f);
ps.setInt(3, 50);
// 執行
ps.execute();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
- res:
PreparedStatement的優點
- Statement 需要進行字符串拼接,可讀性和維護性比較差
String sql = "insert into hero values(null,"+"'提莫'"+","+313.0f+","+50+")";
- PreparedStatement 使用參數設置,可讀性好,不易犯錯
String sql = "insert into hero values(null,?,?,?)";
String sql = "insert into hero values(null,?,?,?)";
PreparedStatement ps = c.prepareStatement(sql);
// PreparedStatement 使用參數設置,可讀性好,不易犯錯
// "insert into hero values(null,?,?,?)";
ps.setString(1, "提莫");
ps.setFloat(2, 313.0f);
ps.setInt(3, 50);
ps.execute();
- PreparedStatement有預編譯機制,性能比Statement更快
// PreparedStatement 執行10次,只需要1次把SQL語句傳輸到數據庫端
// 數據庫對帶?的SQL進行預編譯
// 每次執行,只需要傳輸參數到數據庫端
// 1. 網絡傳輸量比Statement更小
// 2. 數據庫不需要再進行編譯,響應更快
- PreparedStatement的優點3-防止SQL注入式攻擊:
- 代碼:
public static void main(String[] args) {
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
String sql = "select * from hero where name = ?";
try (Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8","root", "admin");
Statement s = c.createStatement();
PreparedStatement ps = c.prepareStatement(sql);
) {
// 假設name是用戶提交來的數據,可以自己編輯,如果惡意編輯爲以下
String name = "'蓋倫' OR 1=1";
String sql0 = "select * from hero where name = " + name;
// 拼接出來的SQL語句就是
// select * from hero where name = '蓋倫' OR 1=1
// 因爲有OR 1=1,所以恆成立
// 那麼就會把所有的英雄都查出來,而不只是蓋倫
// 如果Hero表裏的數據是海量的,比如幾百萬條,把這個表裏的數據全部查出來
// 會讓數據庫負載變高,CPU100%,內存消耗光,響應變得極其緩慢
System.out.println(sql0);
ResultSet rs0 = s.executeQuery(sql0);
while (rs0.next()) {
String heroName = rs0.getString("name");
System.out.println(heroName);
}
s.execute(sql0);
// 使用預編譯Statement就可以杜絕SQL注入
ps.setString(1, name);
ResultSet rs = ps.executeQuery();
// 查不出數據出來
while (rs.next()) {
String heroName = rs.getString("name");
System.out.println(heroName);
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
execute與executeUpdate
- execute與executeUpdate的相同點:都可以執行增加,刪除,修改
- 不同1:execute可以執行查詢語句,然後通過getResultSet,把結果集取出來;executeUpdate不能執行查詢語句
- 不同2:execute返回boolean類型,true表示執行的是查詢語句,false表示執行的是insert,delete,update等等
executeUpdate返回的是int,表示有多少條數據受到了影響