JDBC(Java DataBase Connectivity)是Java與數據庫的接口規範,由Java 語言編寫的類和接口組成,大體分爲兩類:針對Java程序員的JDBC API和針對數據庫開發商的低層的JDBC driver API。而JDBC驅動程序由實施了這些接口的類組成。html
JDBC庫包括一般與數據庫使用相關的操做有:java
查看和修改結果記錄mysql
//1.加載驅動(開發推薦的方式) Class.forName("com.mysql.jdbc.Driver");
注意:若是鏈接的是SQL server程序員
//1.加載驅動 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver");
URL用於標識數據庫的位置,程序員經過URL地址告訴JDBC程序鏈接哪一個數據庫,URL的寫法爲:sql
jdbc:mysql:[]//localhost:3306/shen ?參數名:參數值數據庫
經常使用數據庫URL地址的寫法:apache
Oracle:jdbc:oracle:thin:@localhost:1521:shen編程
SqlServer:jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=shenbash
MySql:jdbc:mysql://localhost:3306/shen服務器
注意:若是是localhost:3306,mysql能夠簡寫爲jdbc:mysql:///sid(儘可能不這樣)
Jdbc程序中的Connection,它用於表明數據庫的連接,Collection是數據庫編程中最重要的一個對象,客戶端與數據庫全部交互都是經過connection對象完成的,建立方法爲:
Connection conn = DriverManager.getConnection(url,user,pass);
這個對象的經常使用方法:
方法 | 描述 |
---|---|
createStatement() | 建立向數據庫發送sql的statement對象。 |
prepareStatement(sql) | 建立向數據庫發送預編譯sql的PrepareSatement對象。 |
prepareCall(sql) | 建立執行存儲過程的callableStatement對象。 |
setAutoCommit(boolean autoCommit) | 設置事務是否自動提交。 |
commit() | 在連接上提交事務。 |
rollback() | 在此連接上回滾事務。 |
String url = "jdbc:mysql://localhost:3306/shen"; String username = "shen"; String password = "Anxin062039"; Connection conn = null; //2.獲取與數據庫的連接 conn = DriverManager.getConnection(url, username, password);
Jdbc程序中的Statement對象用於向數據庫發送SQL語句,建立方法爲:
Statement st = conn.createStatement();
Statement對象經常使用方法:
方法 | 含義 |
---|---|
executeQuery(String sql) | 用於向數據發送查詢語句。 |
executeUpdate(String sql) | 用於向數據庫發送insert、update或delete語句 |
execute(String sql) | 用於向數據庫發送任意sql語句 |
addBatch(String sql) | 把多條sql語句放到一個批處理中。 |
executeBatch() | 向數據庫發送一批sql語句執行。 |
Statement st = null; //3.獲取用於向數據庫發送sql語句的statement st = conn.createStatement(); //4.向數據庫發sql String sql = "select id,name,password,email,birthday from users"; st.executeQuery(sql);
PreperedStatement是Statement的孩子,它的實例對象能夠經過調用:
PreperedStatement st = conn.preparedStatement()
PreperedStatement st = null; String sql = "select * from users where name=? and password=?"; //3.獲取用於向數據庫發送sql語句的Preperedstatement st = conn.preparedStatement(sql);//在這次傳入,進行預編譯 st.setString(1, username); st.setString(2, password); //4.向數據庫發sql st.executeQuery();//在這裏不須要傳入sql
比較:相對於Statement對象而言
如:String sql="select * from admin where loginname='"+loginName+"' and loginpwd='"+loginPwd+"'";
在應用中:
-》請輸入帳號:
333
-》請輸入密碼:
wer'or'1'='1
實際上發送:select * from admin where loginname='333' and loginpwd='wer'or'1'='1',登陸成功!
Jdbc程序中的ResultSet用於表明Sql語句的執行結果。Resultset封裝執行結果時,採用的相似於表格的方式,ResultSet 對象維護了一個指向表格數據行的遊標,初始的時候,遊標在第一行以前,調用ResultSet.next() 方法,可使遊標指向具體的數據行,進行調用方法獲取該行的數據。
ResultSet提供了對結果集進行滾動的方法:
ResultSet既然用於封裝執行結果的,因此該對象提供的都是用於獲取數據的get方法:
getObject(int index)
getObject(string columnName)
getString(int index)
getString(String columnName)
附加:
經常使用數據類型轉換:
SQL類型 | Jdbc對應方法 | 返回類型 |
---|---|---|
bit(1),bit(n) | getBoolean,getBytes() | Boolean,byte[] |
tinyint | getByte() | Byte |
smallint | getShort() | Short |
int | getInt | Int |
bigint | getLong() | Long |
char,varchar,longvarchar | getString | String |
text(clob) blob | getClob(),getblob() | Clob,blob |
date | getDate() | java.sql.Date |
time | getTime() | java.sql.Time |
timestamp | getTimestamp | java.sql.Timestamp |
ResultSet rs = null; //4.向數據庫發sql,並獲取表明結果集的resultset String sql = "select id,name,password,email,birthday from users"; rs = st.executeQuery(sql); //5.取出結果集的數據 rs.afterLast(); rs.previous(); System.out.println("id=" + rs.getObject("id")); System.out.println("name=" + rs.getObject("name")); System.out.println("password=" + rs.getObject("password")); System.out.println("email=" + rs.getObject("email")); System.out.println("birthday=" + rs.getObject("birthday"));
或者:
//循環取出(id) while(rs.next()) { String id=rs.getString(1);//1表明數據庫中表的列數,id在第一列也能夠("id")!!! System.out.println(id+" "); }
Jdbc程序運行完後,切記要釋放程序在運行過程當中,建立的那些與數據庫進行交互的對象,這些對象一般是ResultSet, Statement和Connection對象。
注意:爲確保資源釋放代碼能運行,資源釋放代碼也必定要放在finally語句中。
//6.關閉連接,釋放資源 if(rs!=null){ try{ rs.close(); }catch (Exception e) { e.printStackTrace(); } rs = null; } if(st!=null){ try{ st.close(); }catch (Exception e) { e.printStackTrace(); } } if(conn!=null){ try{ conn.close(); }catch (Exception e) { e.printStackTrace(); } }
/** * 在java中使用ddl語句(credate,drop,backup...) */ package com.shen.study2; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; public class Test1 { public static void main(String[] args) { // TODO Auto-generated method stub Test1 test=new Test1(); } public Test1() { this.lianjie(); } public void lianjie() { //定義須要的對象 PreparedStatement ps=null; Connection ct=null; ResultSet rs=null; try { //初始化對象 //1.加載驅動 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); //2.獲得鏈接(1433表示sql server的默認端口) ct=DriverManager.getConnection("jdbc:microsoft:sqlserver://localhost:1433;databaseName=shen","sa","Anxin062039"); //3.建立Preparestatement,建立數據 ps=ct.prepareStatement("create database vvv"); // ps=ct.prepareStatement("create table xxx");//建立表 // ps=ct.prepareStatement("backup database shen to disk='F:/123.bak'");//備份數據庫 //若是執行的是ddl語句 boolean b=ps.execute(); if(b) { System.out.println("建立成功!"); }else { System.out.println("失敗"); } } catch (Exception e) { // TODO: handle exception }finally { //關閉資源 try { //爲了程序健壯 if(ps!=null) ps.close(); if(ct!=null) ct.close(); } catch (Exception e2) { // TODO: handle exception } } } }
實例:user
public class User { private int id; private String name; private String password; private String email; private Date birthday; //相關的get和set }
鏈接工具:JdbcUtils
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 JdbcUtils { private static String driver = null; private static String url = null; private static String username = null; private static String password = null; static{ try{ InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties"); Properties prop = new Properties(); prop.load(in); driver = prop.getProperty("driver"); url = prop.getProperty("url"); username = prop.getProperty("username"); password = prop.getProperty("password"); Class.forName(driver); }catch (Exception e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException{ return DriverManager.getConnection(url, username,password); } public static void release(Connection conn,Statement st,ResultSet rs){ if(rs!=null){ try{ rs.close(); }catch (Exception e) { e.printStackTrace(); } rs = null; } if(st!=null){ try{ st.close(); }catch (Exception e) { e.printStackTrace(); } } if(conn!=null){ try{ conn.close(); }catch (Exception e) { e.printStackTrace(); } } } }
資源文件:db.properties
#driver=com.mysql.jdbc.Driver #url=jdbc:mysql://localhost:3306/shen #username=shen #password=Anxin062039
注意:前面添加#,表示註釋。若是改爲SQL server直接更改這裏便可
功能實現:Demo
import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; import org.junit.Test; import cn.itcast.utils.JdbcUtils; //使用jdbc對數據庫增刪改查 public class Demo { @Test public void insert(){ Connection conn = null; Statement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); st = conn.createStatement(); String sql = "insert into users(id,name,password,email,birthday) values(4,'xxx','123','xx@sina.com',to_date('1980-09-09','YYYY-MM-DD'))"; int num = st.executeUpdate(sql); //update if(num>0){ System.out.println("插入成功!!"); } }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } @Test public void delete(){ Connection conn = null; Statement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "delete from users where id=4"; st = conn.createStatement(); int num = st.executeUpdate(sql); if(num>0){ System.out.println("刪除成功!!"); } }catch (Exception e) { }finally{ JdbcUtils.release(conn, st, rs); } } @Test public void update(){ Connection conn = null; Statement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "update users set name='wuwang',email='wuwang@sina.com' where id=3"; st = conn.createStatement(); int num = st.executeUpdate(sql); if(num>0){ System.out.println("更新成功!!"); } }catch (Exception e) { }finally{ JdbcUtils.release(conn, st, rs); } } @Test public void find(){ Connection conn = null; Statement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "select * from users where id=1"; st = conn.createStatement(); rs = st.executeQuery(sql); if(rs.next()){ System.out.println(rs.getString("name")); } }catch (Exception e) { }finally{ JdbcUtils.release(conn, st, rs); } } }
以下內容都藉助CRUD中的內容
clob用於存儲大文本(mysql中無clob,存儲大文本採用的是Text)
數據庫爲:
create table testclob ( id int primary key auto_increment, resume text ); public class Demo1 { @Test public void add() { Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "insert into testclob(resume) values(?)" st = conn.prepareStatement(sql); //Reader reader = new InputStreamReader(Demo1.class.getClassLoader().getResourceAsStream("1.txt")); String path = Demo1.class.getClassLoader().getResource("1.txt").getPath();//1.txt文件在src下 File file = new File(path); st.setCharacterStream(1, new FileReader(file), (int) file.length());//將該文件添加 int num = st.executeUpdate(); if(num>0){ System.out.println("插入成功!!"); } }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } @Test public void read(){ Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "select resume from testclob where id=1"; st = conn.prepareStatement(sql); rs = st.executeQuery(); if(rs.next()){ System.out.println("haha"); Reader reader = rs.getCharacterStream("resume"); char buffer[] = new char[1024]; int len = 0; FileWriter out = new FileWriter("c:\\1.txt"); while((len=reader.read(buffer))>0){ out.write(buffer, 0, len) } out.close(); reader.close(); } }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } }
數據庫:
create table testblob ( id int primary key auto_increment, image longblob ); public class Demo2 { @Test public void add(){ Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "insert into testblob(image) values(?)"; st = conn.prepareStatement(sql); String path = Demo2.class.getClassLoader().getResource("01.jpg").getPath(); st.setBinaryStream(1, new FileInputStream(path), (int) new File(path).length()); int num = st.executeUpdate(); if(num>0){ System.out.println("插入成功!!"); } }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } @Test public void read(){ Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "select image from testblob where id=?"; st = conn.prepareStatement(sql); st.setInt(1, 1); rs = st.executeQuery(); if(rs.next()){ InputStream in = rs.getBinaryStream("image"); int len = 0; byte buffer[] = new byte[1024]; FileOutputStream out = new FileOutputStream("c:\\1.jpg"); while((len=in.read(buffer))>0){ out.write(buffer,0, len); } in.close(); out.close(); } }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } }
數據庫:
create table testbatch ( id int primary key, name varchar2(20) );
@Test public void testbatch1(){ Connection conn = null; Statement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql1 = "insert into testbatch(id,name) values(1,'aaa')"; String sql2 = "insert into testbatch(id,name) values(2,'bbb')"; String sql3 = "delete from testbatch where id=1"; st = conn.createStatement(); st.addBatch(sql1); st.addBatch(sql2); st.addBatch(sql3); st.executeBatch(); st.clearBatch(); }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } }
@Test public void testbatch2(){ long starttime = System.currentTimeMillis(); Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "insert into testbatch(id,name) values(?,?)"; st = conn.prepareStatement(sql); for(int i=1;i<10000008;i++){ //i=1000 2000 st.setInt(1, i); st.setString(2, "aa" + i); st.addBatch(); if(i%1000==0){ st.executeBatch(); st.clearBatch(); } } st.executeBatch(); }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } long endtime = System.currentTimeMillis(); System.out.println("程序花費時間:" + (endtime-starttime)/1000 + "秒!!"); }
數據庫:
create table test1 ( id int primary key auto_increment,//id自動生成 name varchar(20) ); public class Demo4 { /** * 獲取自動生成的主鍵 */ public static void main(String[] args) { Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); String sql = "insert into test1(name) values(?)"; st = conn.prepareStatement(sql); st.setString(1, "aaa");//在插入name時數據庫會自動生成id st.executeUpdate(); rs = st.getGeneratedKeys();//獲取生成的主鍵 if(rs.next()){ System.out.println(rs.getInt(1)); } }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } } }
public class Demo5 { /* *jdbc調用存儲過程 create procedure p_course_insert @c_no nvarchar(50), @c_name nvarchar(50), @t_name nvarchar(50) as insert into t_course(c_no,c_name,t_name) values(@c_no,@c_name,@t_name) */ public static void main(String[] args) { Connection conn = null; CallableStatement cs = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); cs = conn.prepareCall("{call p_course_inser(?,?,?)}"); cs.setString(1, "xxxxx"); cs.registerOutParameter(2, Types.VARCHAR); cs.execute(); String result = cs.getString(2); System.out.println(result); }catch (Exception e) { e.printStackTrace(); }finally{ JdbcUtils.release(conn, cs, rs); } } }
/** * 模似轉賬 create table account( id int primary key auto_increment, name varchar(40), money float )character set utf8 collate utf8_general_ci; insert into account(name,money) values('aaa',1000); insert into account(name,money) values('bbb',1000); insert into account(name,money) values('ccc',1000); */ public static void main(String[] args) { Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try{ conn = JdbcUtils.getConnection(); conn.setAutoCommit(false); //start transaction,開啓事務 String sql1 = "update account set money=money-100 where name='aaa'"; st = conn.prepareStatement(sql1); st.executeUpdate(); String sql2 = "update account set money=money+100 where name='bbb'"; st = conn.prepareStatement(sql2); st.executeUpdate(); conn.commit();//提交 System.out.println("成功!!!"); //log4j }catch (Exception e) { e.printStackTrace();//若是程序出錯手動回滾 }finally{ JdbcUtils.release(conn, st, rs); } }
public static void main(String[] args) { Connection conn = null; PreparedStatement st = null; ResultSet rs = null; Savepoint sp = null; try{ conn = JdbcUtils.getConnection(); conn.setAutoCommit(false); //start transaction String sql1 = "update account set money=money-100 where name='aaa'"; st = conn.prepareStatement(sql1); st.executeUpdate(); sp = conn.setSavepoint();//在這裏設置事務回滾點 String sql2 = "update account set money=money+100 where name='bbb'"; st = conn.prepareStatement(sql2); st.executeUpdate(); int x = 1/0; String sql3 = "update account set money=money+100 where name='ccc'"; st = conn.prepareStatement(sql3); st.executeUpdate(); conn.commit(); }catch (Exception e) { try { conn.rollback(sp);//回滾到該事務點,即該點以前的會正常執行(sql1) conn.commit(); //回滾了要記得提交,若是沒有提交sql1將會自動回滾 } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } e.printStackTrace(); }finally{ JdbcUtils.release(conn, st, rs); } }
conn = JdbcUtils.getConnection(); conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);//避免髒讀 conn.setAutoCommit(false); /* Serializable:可避免髒讀、不可重複讀、虛讀狀況的發生。(串行化) Repeatable read:可避免髒讀、不可重複讀狀況的發生。(可重複讀) Read committed:可避免髒讀狀況發生(讀已提交)。 Read uncommitted:最低級別,以上狀況均沒法保證。(讀未提交) */
缺點:
用戶每次請求都須要向數據庫得到連接,而數據庫建立鏈接一般須要消耗相對較大的資源,建立時間也較長。假設網站一天10萬訪問量,數據庫服務器就須要建立10萬次鏈接,極大的浪費數據庫的資源,而且極易形成數據庫服務器內存溢出、拓機。
工具類以下:JdbcUtils_DBCP
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; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; public class JdbcUtils_DBCP { private static DataSource ds = null; static{ try{ InputStream in = JdbcUtils_DBCP.class.getClassLoader().getResourceAsStream("dbcpconfig.properties"); Properties prop = new Properties(); prop.load(in); BasicDataSourceFactory factory = new BasicDataSourceFactory(); ds = factory.createDataSource(prop); System.out.println(ds); }catch (Exception e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException{ return ds.getConnection(); } public static void release(Connection conn,Statement st,ResultSet rs){ if(rs!=null){ try{ rs.close(); }catch (Exception e) { e.printStackTrace(); } rs = null; } if(st!=null){ try{ st.close(); }catch (Exception e) { e.printStackTrace(); } } if(conn!=null){ try{ conn.close(); }catch (Exception e) { e.printStackTrace(); } } } }
鏈接工具類:JdbcUtils_C3p0(本身在這裏更改)
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; import javax.sql.DataSource; import org.apache.commons.dbcp.BasicDataSourceFactory; import com.mchange.v2.c3p0.ComboPooledDataSource; public class JdbcUtils_C3P0 { private static ComboPooledDataSource ds = null; static{ try{ ds = new ComboPooledDataSource(); ds.setDriverClass("com.mysql.jdbc.Driver"); ds.setJdbcUrl("jdbc:mysql://localhost:3306/day16"); ds.setUser("root"); ds.setPassword("root"); ds.setInitialPoolSize(10);//最初鏈接數 ds.setMinPoolSize(5);//最小鏈接數 ds.setMaxPoolSize(20);//最大鏈接數 }catch (Exception e) { throw new ExceptionInInitializerError(e); } } public static Connection getConnection() throws SQLException{ return ds.getConnection(); } public static void release(Connection conn,Statement st,ResultSet rs){ if(rs!=null){ try{ rs.close(); }catch (Exception e) { e.printStackTrace(); } rs = null; } if(st!=null){ try{ st.close(); }catch (Exception e) { e.printStackTrace(); } } if(conn!=null){ try{ conn.close(); }catch (Exception e) { e.printStackTrace(); } } } }
也能夠將配置信息放在xml文件中(src下):c3p0-config.xml
<?xml version="1.0" encoding="UTF-8"?> <c3p0-config> <default-config> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property> <property name="user">root</property> <property name="password">root</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> </default-config> <named-config name="mysql"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property> <property name="user">root</property> <property name="password">root</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> </named-config> <named-config name="oracle"> <property name="driverClass">com.mysql.jdbc.Driver</property> <property name="jdbcUrl">jdbc:mysql://localhost:3306/day16</property> <property name="user">root</property> <property name="password">root</property> <property name="acquireIncrement">5</property> <property name="initialPoolSize">10</property> <property name="minPoolSize">5</property> <property name="maxPoolSize">20</property> </named-config> </c3p0-config>
這樣JdbcUtils_C3p0能夠改成:
/* ds = new ComboPooledDataSource(); ds.setDriverClass("com.mysql.jdbc.Driver"); ds.setJdbcUrl("jdbc:mysql://localhost:3306/day16"); ds.setUser("root"); ds.setPassword("root"); ds.setInitialPoolSize(10);//最初鏈接數 ds.setMinPoolSize(5);//最小鏈接數 ds.setMaxPoolSize(20);//最大鏈接數 */ ds = new ComboPooledDataSource(""mysql"");//若是默認()