文章目錄
- 導入包
- con、stmt、rs 三者存在一定的關系
- getInt和getString
- input.nextInt();簡單使用講解
- ResultSet和Statement
- PreparedStatement的用法
- JDBC連接代碼
- 更多樣例
導入包
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.statement;
import java.sql.ResultSet;
import java.util.Scanner;import java sql.*;
con、stmt、rs 三者存在一定的關系
(1)連接數據庫后 實例化con
(2)創建stmt=con.createstatement();
(3)然后執行rs=stmt.excuteQuery()執行sql語句,產生單個結果集;
getInt和getString
ResultSet rs = null;
String sql="SELECT flow_id,Type,id_card,exam_card,student_name,location,grade FROM examstudent";rs = st.executeQuery(sql); //rs:數據集
rs.getInt(int index);
rs.getInt(String columName); //你可以通過索引或者列名來獲得查詢結果集中的某一列的值。//舉例
while(rs.next)
{rs.getInt(1)//等價于rs.getInt("flowid");rs.getString(5)//等價于rs.getInt("student_name");
}
input.nextInt();簡單使用講解
完整的寫法是 先導入 輸入流 類 Scanner
import java.util.Scanner;
然后使用輸入流 , 按照你的問題中的 寫法和名稱, 應該這樣使用 Scanner 這個類
Scanner input = new Scanner(System.in); // 創建輸入流對象 input
int userNum = input.nextInt(); // 使用輸入流對象 調用nextInt() 方法輸入一個整數到userNum中
其意思是 使用 Scanner 類中的 nextInt() 方法 輸入一個整數, 該方法只是接受一個 整型的數據,如果輸入的是非整數數據, 將會 拋出 InputMismatchException
異常,其實就是專門為在命令式界面中 提供的一種輸入類, Scanner 類位于 java.util 包中, 其中還有更多常用的其他方法。
例如:
nextLine() // 輸入一行數據,一般會將你輸入的數據當做 字符串處理
nextDouble() // 輸入一個 雙精度實型的 數據
nextFloat() // 輸入一個 單精度實型的 數據
nextByte() // 輸入一個字節的 數據
nextLong() // 輸入一個long型的 數據,
等等, 如果輸入錯誤的話, 或者輸入的東西和你 調用的方法不匹配, 都會拋出 InputMismatchException
異常
ResultSet和Statement
ResultSet:
查詢數據庫時,返回的是一個二維的結果集,我們需要用到ResultSet來遍歷結果集,獲取每一行的數據。
boolean next() 將光標從當前位置向前移一行。
String getString(int columnIndex) 以java編程語言中String的形式獲取此ResultSet對象的當前行中指定列的值
String getString(String columnLabel) 以java編程語言中String的形式獲取此ResultSet對象的當前行中指定列的值
while(rs.next()) {int id = rs.getInt(1);// 獲取第一個列的值 編號idString bookName = rs.getString(2);// 獲取第二個列的值 圖書名稱 bookNameString author = rs.getString(3);// 獲取第三列的值 圖書作者 authorfloat price = rs.getFloat(4);// 獲取第四列的值 圖書價格 priceSystem.out.println("id="+id+" bookName="+bookName+" author="+author+" price="+price);System.out.println("................................................");
Statement :
(1)建立了到特定數據庫的連接之后,就可用該連接發送 SQL 語句。
(2)Statement 接口提供了三種執行 SQL 語句的方法:executeQuery、executeUpdate 和execute
1.方法 executeQuery 用于產生單個結果集的語句,例如 SELECT 語句
2.方法 executeUpdate 用于執行 INSERT、UPDATE 或 DELETE 語句以及 SQLDDL(數據定義語言)語句,例如 CREATE TABLE 和 DROP TABLE。 INSERT、UPDATE 或
DELETE語句的效果是修改表中零行或多行中的一列或多列。executeUpdate 的返回值是一個整數,指示受影響的行數(即更新計數)。
對于CREATE TABLE 或 DROP TABLE 等不操作行的語句,executeUpdate 的返回值總為零。
3.方法 execute用于執行返回多個結果集、多個更新計數或二者組合的語句。
PreparedStatement的用法
java.sql.statement要求開發者付出大量的時間和精力。
在使用statement獲取jdbc訪問時所具有的一個共通的問題是輸入適當格式的日期和時間戳:2002-02-05 20:56 或者 02/05/02 8:56 pm。
通過使用java.sql.preparedstatement,可以自動解決這個問題。
一個preparedstatement是從java.sql.connection對象和所提供的sql字符串得到的,sql字符串中包含問號(?),這些問號標明變量的位置,然后提供變量的值,最后執行語句,例如:
string sql = "select * from people p where p.id = ? and p.name = ?";
preparedstatement ps = connection.preparestatement(sql);
ps.setint(1,id);
ps.setstring(2,name);
resultset rs = ps.executequery();
使用preparedstatement的另一個優點是字符串不是動態創建的。
下面是一個動態創建字符串的例子:
string sql = "select * from people p where p.i = "+id;
這允許jvm(java virtual machine)和驅動/數據庫緩存語句和字符串并提高性能。
preparedstatement也提供數據庫無關性。當顯示聲明的sql越少,那么潛在的sql語句的數據庫依賴性就越小。
由于preparedstatement具備很多優點,開發者可能通常都使用它,只有在完全是因為性能原因或者是在一行sql語句中沒有變量的時候才使用通常的statement。
import java.sql.*;
public class mypreparedstatement {private final string db_driver="com.microsoft.jdbc.sqlserver.sqlserverdriver";private final string url = "jdbc:microsoft:sqlserver://127.0.0.1:1433;databasename=pubs";public mypreparedstatement() {}public void query() throws sqlexception {connection conn = this.getconnection();string strsql = "select emp_id from employee where emp_id = ?";preparedstatement pstmt = conn.preparestatement(strsql);pstmt.setstring(1,"pma42628m");resultset rs = pstmt.executequery();while(rs.next()) {string fname = rs.getstring("emp_id");system.out.println("the fname is " + fname);}rs.close();pstmt.close();conn.close();}private connection getconnection() throws sqlexception {
// class.connection conn = null;try {class.forname(db_driver);conn = drivermanager.getconnection(url,"sa","sa");} catch (classnotfoundexception ex) {}return conn;}
//mainpublic static void main(string[] args) throws sqlexception {mypreparedstatement jdbctest1 = new mypreparedstatement();jdbctest1.query();}
}
為什么要始終使用PreparedStatement代替Statement?為什么要始終使用PreparedStatement代替Statement?
在JDBC應用中,應該始終以PreparedStatement代替Statement.也就是說,在任何時候都不要使用Statement。
基于以下的原因:
一.、代碼的可讀性和可維護性.
雖然用PreparedStatement來代替Statement會使代碼多出幾行,但這樣的代碼無論從可讀性還是可維護性上來說.都比直接用Statement的代碼高很多檔次:
stmt.executeUpdate("insert into tb_name (col1,col2,col2,col4) values ('"+var1+"','"+var2+"',"+var3+",'"+var4+"')");perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");
perstmt.setString(1,var1);
perstmt.setString(2,var2);
perstmt.setString(3,var3);
perstmt.setString(4,var4);
perstmt.executeUpdate();
對于第一種方法.別說其他人去讀你的代碼,就是你自己過一段時間再去讀,都會覺得傷心。
二、PreparedStatement盡最大可能提高性能
每一種數據庫都會盡最大努力對預編譯語句提供最大的性能優化.因為預編譯語句有可能被重復調用.
所以語句在被DB的編譯器編譯后的執行代碼被緩存下來,那么下次調用時只要是相同的預編譯語句就不需要編譯,只要將參數直接傳入編譯過的語句執行代碼中(相當于一個涵數)就會得到執行.這并不是說只有一個Connection中多次執行的預編譯語句被緩存,而是對于整個DB中,只要預編譯的語句語法和緩存中匹配.那么在任何時候就可以不需要再次編譯而可以直接執行。
而statement的語句中,即使是相同一操作,而由于每次操作的數據不同所以使整個語句相匹配的機會極小,幾乎不太可能匹配.比如:
insert into tb_name (col1,col2) values (‘11’,‘22’);
insert into tb_name (col1,col2) values (‘11’,‘23’);
即使是相同操作但因為數據內容不一樣,所以整個個語句本身不能匹配,沒有緩存語句的意義。事實是沒有數據庫會對普通語句編譯后的執行代碼緩存.
當然并不是所以預編譯語句都一定會被緩存,數據庫本身會用一種策略,比如使用頻度等因素來決定什么時候不再緩存已有的預編譯結果,以保存有更多的空間存儲新的預編譯語句。
三、最重要的一點是極大地提高了安全性.
常見的SQL注入:
String sql = "select * from tb_name where name= '"+varname+"' and passwd='"+varpasswd+"'";
如果我們把[’ or ‘1’ = '1]作為passwd變量傳入進來。
select * from tb_name = '隨意' and passwd = '' or '1' = '1';
因為’1’='1’肯定成立,所以可以任何通過驗證.
更有甚者:
把[';drop table tb_name;]
作為varpasswd傳入進來,有
select * from tb_name = '隨意' and passwd = '';drop table tb_name;
有些數據庫是不會讓你成功。.
而如果你使用預編譯語句.你傳入的任何內容就不會和原來的語句發生任何匹配的關系.只要全使用預編譯語句,你就用不著對傳入的數據做任何過慮.而如果使用普通的statement,有可能要對drop,;等做費盡心機的判斷和過慮。
JDBC連接代碼
import java.io.FileInputStream;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;public class JDBCUtil {static String driverClass=null;static String url=null;static String name=null;static String password=null;static {try{//1.創建一個屬性對象Properties properties=new Properties();InputStream is=JDBCUtil.class.getClassLoader().getResourceAsStream("jdbc.properties");//導入輸入流properties.load(is);//讀取屬性driverClass= properties.getProperty("driverClass");url= properties.getProperty("url");name= properties.getProperty("name");password= properties.getProperty("password");} catch(Exception e) {e.printStackTrace();}}public static Connection getConn() {Connection conn=null;try {Class.forName(driverClass);//1.注冊驅動 DriverManager.registerDriver(new com.mysql.jdbc.Driver());// 2.建立連接 參數一:協議+訪問的數據庫 參數二: 用戶名 參數三:密碼//conn=DriverManager.getConnection("jdbc:mysql://localhost/test?useSSL=false","root","1234");conn=DriverManager.getConnection(url,name,password);} catch(Exception e) {e.printStackTrace();}return conn;}
// 釋放資源public static void release(Connection conn,Statement st,ResultSet rs) {closeRs(rs);closeSt(st);closeConn(conn);}private static void closeRs(ResultSet rs) {try {if(rs!=null) {rs.close();}} catch (SQLException e) {e.printStackTrace();}finally {rs=null;}}private static void closeSt(Statement st) {try {if(st!=null) {st.close();}} catch (SQLException e) {e.printStackTrace();}finally {st=null;}}private static void closeConn(Connection conn) {try {if(conn!=null) {conn.close();}} catch (SQLException e) {e.printStackTrace();}finally {conn=null;}}}
更多樣例
class DBConnection{// 驅動類名String driver="com.mysql.jdbc.Driver";
// URL格式,最后為數據庫名String url="jdbc:mysql://localhost:3306/javaTest?useUnicode=true&characterEncoding=UTF8"; //JavaTest為你的數據庫名稱String user="root";String password="123456";Connection coon=null;public DBConnection(){try{
// 加載驅動程序Class.forName(driver);coon=(Connection)DriverManager.getConnection(url,user,password);if(!coon.isClosed()){System.out.println("成功連接數據庫!");}}catch (Exception e){e.printStackTrace();}}public void close(){try{this.coon.close();}catch(Exception e){e.printStackTrace();}}
// 增加數據public void add(String name,int age,String gender){
// String sql="insert into usrInfo(username,gender,age) values(?,?,?)"; //向usrInfo表中插入數據String sql="insert into usrInfo(age,gender,username) values('"+age+"','"+gender+"','"+name+"')";try{PreparedStatement preStmt=(PreparedStatement)this.coon.prepareStatement(sql);
// preStmt.setString(1, name);
// preStmt.setInt(3, age);
// preStmt.setString(2, gender); //和上面的注釋的一塊組成另外一種插入方法preStmt.executeUpdate();System.out.println("插入數據成功!");preStmt.close();}catch(Exception e){e.printStackTrace();}}// 查詢public void select(){String sql="select * from usrInfo"; //查詢usrInfo表中的信息try{Statement stmt=(Statement)this.coon.createStatement();ResultSet rs=(ResultSet)stmt.executeQuery(sql); //得到的是結果的集合System.out.println("--------------------------------");System.out.println("姓名"+"\t"+"年齡"+"\t"+"性別");System.out.println("--------------------------------");while(rs.next()){String name=rs.getString("username");int age=rs.getInt("age");String gender=rs.getString("gender");System.out.println(name+"\t"+age+"\t"+gender);}stmt.close();}catch(Exception e){e.printStackTrace();}}// 更改數據public void update(String name,int age){String sql="update usrInfo set age=? where username=?"; //推薦使用這種方式,下面的那種注釋方式不知道為啥有時候不好使
// String sql="update usrInfo set age="+age+" where username='"+name+"'";try{PreparedStatement prestmt=(PreparedStatement)this.coon.prepareStatement(sql);prestmt.setInt(1, age);prestmt.setString(2,name);prestmt.executeUpdate();// Statement stmt=(Statement)this.coon.createStatement();
// stmt.executeUpdate(sql);System.out.println("更改數據成功!");prestmt.close();}catch(Exception e){e.printStackTrace();}}// 刪除數據public void del(String name){String sql="delete from usrInfo where username=?";try{PreparedStatement prestmt=(PreparedStatement)this.coon.prepareStatement(sql);prestmt.setString(1, name);prestmt.executeUpdate();System.out.println("刪除數據成功!");prestmt.close();}catch(Exception e){e.printStackTrace();}}
}
在主類中對其創建實例,實例中構造方法完成數據庫的連接操作,實例調用增刪改查方法進行對數據庫信息的操作
public class mysqlTest {public static void main(String args[]){Scanner in=new Scanner(System.in);DBConnection db=new DBConnection();// 插入數據System.out.println("輸入姓名,年齡,性別:");String name=in.next();int age=in.nextInt();String gender=in.next();db.add(name, age, gender);// 查詢數據db.select();// 修改數據
// String name=in.next();
// int age=in.nextInt();
// db.update(name, age);// 刪除數據
// String name=in.next();
// db.del(name);
//
// db.close();}}