jdbc操作資料庫學習
阿新 • • 發佈:2018-12-02
jdbc程式設計的步驟大致分為:
1.載入資料庫驅動,首先對於不同的資料庫要匯入其相應的jar包,我這裡是mysql資料庫,可直接在eclipse中建立maven專案,在maven中匯入其對應的jar包
以下為載入jdbc驅動
Class.forName("com.mysql.jdbc.Driver");
2.通過DriverManager獲取資料庫連線
其中第一個引數為mysql地址和其對應的埠(當然如果有伺服器也可以使用伺服器的公網ip和mysql的埠),第二個引數和第三個引數為mysql的使用者名稱和密碼
Connection conn = DriverManager.getConnection( "jdbc:mysql://127.0.0.1:3306/class", "root","123456" );
3.通過Statement物件執行sql語句,可通過Connection建立Statement物件
Statement stmt = conn.createStatement();
學過mysql的都知道sql語句分為
1、資料操縱語言(DML):用來操縱資料庫中資料的命令。包括:select、insert、update、delete。 2、資料定義語言(DDL):用來建立資料庫、資料庫物件和定義列的命令。包括:create、alter、drop。 3、資料控制語言(DCL):用來控制資料庫元件4.資料庫查詢語言(DQL):用來查詢資料庫
其中對於DML語言
執行DML時使用executeUpdate(sql)返回受影響的行數
執行DQL時使用executeQuery(sql)返回一個ResultSet物件,ResultSet中的next()方法使結果集的指標指向下一行,ResultSet結果集的指標預設指向第一行
ResultSet s = stmt.executeQuery("select languages.*"+"from languages"
);
while(s.next()) {
System.out.println(s.getInt(1)+"\t"+s.getString(2));
}
方法getInt(1)表示獲取第一列的資料,當然你如果知道列名也可以用列名做引數
執行DDL時使用 使用execute 返回型別為Boolean型別 表示執行該sql後是否返回ResultSet結果集 如果有 可以調getResultSet來返回ResultSet物件,getUpdateCount返回受影響的行數
使用PreparedStatement執行sql語句,在執行sql語句時,資料庫都會根據sql語句來建立新的執行計劃,如果反覆執行類似的sql語句,必定會降低資料庫的執行效率,所以使用預編譯的sql語句可大大提高資料庫效率,同時PreparedStatement還可有效的防止sql注入
PreparedStatement pstm = conn.prepareStatement("insert into jdbc_test values(null,?,1);");
pstm.setString(1, "ruby");
pstm.executeUpdate();
使用ResultSetMeteData分析結果集
//得到RsesultSetMetaData物件
ResultSetMetaData rd = rs.getMetaData();
//獲取列的數量
int col_number = rd.getColumnCount();
System.out.println("列的數量為"+col_number);
//獲取指定索引的列名與列的型別
for(int i = 1;i < col_number;i++) {
System.out.println("索引"+i+"的列名:"+rd.getColumnName(i)+"型別:"+rd.getColumnTypeName(i));
}
使用資料庫池管理連線:
資料庫每次建立連線都會消耗一定的時間,使用資料庫連線池的好處就是當用戶不使用連線是,把連線儲存起來,給下一個使用者使用,從而提高資料庫使用效率
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(user);
ds.setPassword(pass);
ds.setInitialSize(2);
ds.setMaxActive(100);
//使用連線池中的資料庫連線
Connection conn = ds.getConnection();
String sql = "select * from languages";
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(sql);
封裝
為了使用jdbc的效率,不能每次都寫載入資料等一些重複的工作
所以我們可以寫一個工具類,提供一些方法來獲取和關閉連線
我這裡以資料庫連線池為例
import org.apache.commons.dbcp.BasicDataSource;
/**
* 使用連線池技術管理資料庫連線
*
* @author Administrator
*
*/
public class DButil2 {
// 資料庫連線池
private static BasicDataSource ds;
// 為不同執行緒管理連線
private static ThreadLocal<Connection> tl;
static {
try {
Properties prop = new Properties();
// InputStream is =
// DButil2.class.getClassLoader().getResourceAsStream("day01/config.properties");
FileInputStream is = new FileInputStream("C:\\Users\\Administrator\\Desktop\\mysql.ini");
prop.load(is);
is.close();
System.out.println("k");
// 初始化連線池
ds = new BasicDataSource();
// 設定驅動 (Class.forName())
ds.setDriverClassName(prop.getProperty("driver"));
// 設定url
ds.setUrl(prop.getProperty("url"));
// 設定資料庫使用者名稱
ds.setUsername(prop.getProperty("user"));
// 設定資料庫密碼
ds.setPassword(prop.getProperty("pwd"));
// 初始連線數量
ds.setInitialSize(Integer.parseInt(prop.getProperty("initsize")));
// 連線池允許的最大連線數
ds.setMaxActive(Integer.parseInt(prop.getProperty("maxactive")));
// 設定最大等待時間
// ds.setMaxWait(Integer.parseInt(prop.getProperty("maxwait")));
// // 設定最小空閒數
// ds.setMinIdle(Integer.parseInt(prop.getProperty("minidle")));
// // 設定最大空閒數
// ds.setMaxIdle(Integer.parseInt(prop.getProperty("maxidle")));
// // 初始化執行緒本地
tl = new ThreadLocal<Connection>();
System.out.println("k");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 獲取資料庫連線
*
* @throws SQLException
*/
// String sql = "select * from languages";
public static Connection getConnection() {
/*
* 通過連線池獲取一個空閒連線
*/
try {
Connection conn = ds.getConnection();
return conn;
}
catch (Exception e) {
//System.out.println("j");
e.printStackTrace();
throw new RuntimeException(e);
}
// tl.set(conn);
}
/**
* 關閉資料庫連線
*/
public static void closeConnection(Connection conn) {
try {
if (conn != null) {
/*
* 通過連線池獲取的Connection 的close()方法實際上並沒有將 連線關閉,而是將該連結歸還。
*/
conn.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
資料庫事物
我們知道資料庫的修改表上的資料時是自動提交 儲存 如果表上的資料被改動,沒有經過提交儲存就再次改就會丟擲異常 以下是一個例子
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Scanner;
import day01.DBUtil2;
/**
* 與使用者相關的業務邏輯
*
* @author Administrator
*
*/
public class UserService {
public static void main(String[] args) {
/*
* 程式啟動後: 選擇1,2,3,4等操作 1:註冊新使用者 使用者ID從1開始 2:更改使用者資訊 3:刪除使用者資訊 4:查詢使用者資訊
*/
System.out.println("請輸入選項:");
System.out.print("1:註冊 ");
System.out.print("2:登入 ");
System.out.print("3:修改 ");
System.out.print("4:刪除 ");
System.out.println("5:查詢 ");
System.out.println("6:轉賬 ");
Scanner scanner = new Scanner(System.in);
int option = Integer.parseInt(scanner.nextLine().trim());
switch (option) {
case 1:
// 註冊
regUser(scanner);
break;
case 2:
// 登入
login(scanner);
break;
case 3:
break;
case 4:
break;
case 5:
break;
case 6:
giveMoney(scanner);
break;
}
}
/**
* 轉賬操作
*
* @param scanner
*/
public static void giveMoney(Scanner scanner) {
/*
* 1:獲取使用者輸入的資訊 2:必要的驗證,看看轉出賬戶餘額是否夠 --事務開始的地方 3:更新轉出賬戶的餘額 4:更新轉入賬戶的餘額 --提交事務的地方
*/
System.out.println("現在是轉賬操作");
System.out.println("請輸入您的賬號");
String fromUser = scanner.nextLine().trim();
System.out.println("請輸入收款人的賬號");
String toUser = scanner.nextLine().trim();
System.out.println("請輸入轉出金額");
String money = scanner.nextLine().trim();
// 2
String countSql = "SELECT money " + "FROM user_fanchuanqi " + "WHERE name='" + fromUser + "'";
try {
Connection conn = DBUtil2.getConnection();
// 關閉自動提交事務
conn.setAutoCommit(false);
Statement state = conn.createStatement();
ResultSet rs = state.executeQuery(countSql);
// 判斷是否查詢出資料
if (rs.next()) {
int count = rs.getInt(1);
// 判斷餘額是否足夠
if (count >= Integer.parseInt(money)) {
// 執行轉賬操作
// 開始納入事務控制,因為開始執行DML操作了
String fromSql = "UPDATE user_fanchuanqi " + "SET money=money-" + money + " " + "WHERE name='"
+ fromUser + "'";
// 修改當前使用者的餘額
if (state.executeUpdate(fromSql) > 0) {
// 修改收款人的餘額
String toSql = "UPDATE user_fanchuanqi " + "SET money=money+" + money + " " + "WHERE name='"
+ toUser + "'";
if (state.executeUpdate(toSql) > 0) {
System.out.println("轉賬成功");
/*
* 兩次更新賬戶操作均成功,我們才 認為這次轉賬操作完畢。提交事務
*/
conn.commit();
} else {
System.out.println("轉賬失敗:沒有收款人" + toUser);
/*
* 若第二次更新操作失敗,那麼整次 操作就算作失敗。應該回滾事務。
*/
conn.rollback();
}
}
} else {
System.out.println("餘額不足");
}
} else {
System.out.println("沒有該使用者:" + fromUser);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil2.closeConnection();
}
}
/**
* 登入操作
*
* @param scanner
*/
public static void login(Scanner scanner) {
/*
* 1:要求用輸入使用者名稱及密碼 2:根據使用者輸入作為條件去表中查詢 3:若查詢出資料,說明輸入正確
*/
System.out.println("現在是登入操作");
System.out.println("請輸入使用者名稱:");
String user = scanner.nextLine().trim();
System.out.println("請輸入密碼:");
String pwd = scanner.nextLine().trim();
try {
Connection conn = DBUtil2.getConnection();
String sql = "SELECT * FROM user_fanchuanqi " + "WHERE name=? AND password=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, user);
ps.setString(2, pwd);
ResultSet rs = ps.executeQuery();
// 根據使用者輸入的能否查到資料
if (rs.next()) {
System.out.println("登入成功!");
} else {
System.out.println("使用者名稱或密碼錯誤!");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DBUtil2.closeConnection();
}
}
/**
* 註冊操作
*
* @param scanner
*/
public static void regUser(Scanner scanner) {
/*
* 若是註冊操作: 1:獲取使用者輸入的相關資訊 2:獲取連線 3:獲取Statement 4:先獲取id的最大值 5:對該值+1,作為當前記錄的主鍵值
* 6:插入記錄 7:關閉連線
*/
try {
// 1
System.out.println("現在是註冊操作:");
System.out.println("請輸入使用者名稱:");
String user = scanner.nextLine().trim();
System.out.println("請輸入密碼:");
String pwd = scanner.nextLine().trim();
System.out.println("請輸入賬戶金額:");
String money = scanner.nextLine().trim();
System.out.println("請輸入郵箱:");
String email = scanner.nextLine().trim();
// 2
Connection conn = DBUtil2.getConnection();
// 3
Statement state = conn.createStatement();
// 4
String idSql = "SELECT MAX(id) id FROM user_fanchuanqi";
// 5
ResultSet rs = state.executeQuery(idSql);
int id = -1;
if (rs.next()) {
id = rs.getInt("id");
}
// 統計出最大值後,對ID加1
id++;
rs.close();
// 6
/*
* INSERT INTO user_fanchuanqi VALUES(1,'jack','1234',5000,'[email protected]')
*
*/
String sql = "INSERT INTO user_fanchuanqi " + "VALUES" + "(" + id + "," + "'" + user + "'," + "'" + pwd
+ "'," + "" + money + "," + "'" + email + "'" + ")";
System.out.println(sql);
if (state.executeUpdate(sql) > 0) {
System.out.println("註冊成功!歡迎你:" + user);
} else {
System.out.println("呵呵");
}
DBUtil2.closeConnection();
} catch (Exception e) {
e.printStackTrace();
}
}
}
批量更新資料
/**
* 使用批處理批量更新資料
* @author Administrator
*
*/
public class BatchDemo {
public static void main(String[] args){
try{
Connection conn
= DBUtil2.getConnection();
Statement state
= conn.createStatement();
for(int i=1000;i<20000;i++){
String sql
="INSERT INTO user_fanchuanqi " +
"(id,name) " +
"VALUES" +
"("+i+",'test"+i+"')";
// state.executeUpdate(sql);
//快取,等待一起執行
state.addBatch(sql);
if(i%500==0){
state.executeBatch();
state.clearBatch();
}
}
state.executeBatch();
}catch(Exception e){
e.printStackTrace();
}finally{
DBUtil2.closeConnection();
}
}