Junit是一個基于Java語言的單元測試框架。是白盒測試的一種技術秉剑。
①測試方法上必須使用@Test進行修飾
? ? ? ②測試方法必須使用public void 進行修飾泛豪,不能帶任何的參數(shù)
? ? ? ③新建一個源代碼目錄來存放我們的測試代碼,即將測試代碼和項目業(yè)務代碼分開
? ? ? ④測試類所在的包名應該和被測試類所在的包名保持一致
? ? ? ⑤測試單元中的每個方法必須可以獨立測試侦鹏,測試方法間不能有任何的依賴
? ? ? ⑥測試類使用Test作為類名的后綴(不是必須)
? ? ? ⑦測試方法使用test作為方法名的前綴(不是必須)
JDBC(Java DataBase Connectivity,java數(shù)據(jù)庫連接)是一種用于執(zhí)行SQL語句的Java API诡曙,可以為多種 關系數(shù)據(jù)庫提供統(tǒng)一訪問,它由一組用Java語言編寫的類和接口組成种柑。JDBC提供了一種基準岗仑,據(jù)此可以 構建更高級的工具和接口,使數(shù)據(jù)庫開發(fā)人員能夠編寫數(shù)據(jù)庫應用程序聚请。
JDBC可以在各種平臺上使用Java荠雕,如Windows,Mac OS和各種版本的UNIX驶赏。
構建JDBC應用程序涉及以下六個步驟:
導入JDBC驅動包:需要下載包含數(shù)據(jù)庫編程所需的JDBC的jar包炸卑。
?注冊JDBC驅動程序:要求您初始化驅動程序,以便您可以打開與數(shù)據(jù)庫的通信通道煤傍。
?創(chuàng)建連接:需要使用 D riv e r M a n a g e r.g e t C o n n e c tio n () 方法創(chuàng)建一個Connection對象盖文,該對象表示 與數(shù)據(jù)庫的物理連接。
?執(zhí)行查詢:需要使用類型為Statement的對象來構建和提交SQL語句到數(shù)據(jù)庫蚯姆。?
從結果集中提取數(shù)據(jù):需要使用相應的 R e s ult S e t .g e t X X X () 方法從結果集中檢索數(shù)據(jù)五续。?
釋放資源:需要明確地關閉所有數(shù)據(jù)庫資源,而不依賴于JVM的垃圾收集龄恋。
public class JdbcDemo2 {?
?public static void main(String[] args) {?
?Connection connection=null;
?Statement stat=null;
?ResultSet rs=null; //2注冊驅動?
?try {? ?
?? ? ? ? Class.forName("com.mysql.jdbc.Driver");? ? ??
? ? ? //3獲取連接? ? ? ? ? ??
connection=DriverManager.getConnection("jdbc:mysql://localhost:3306/school", "root", "root");? ? ? ? ??
? //4創(chuàng)建命令(語句)對象? ? ? ? ? ?
?stat=connection.createStatement();? ? ? ??
? ? //執(zhí)行命令查詢? ? ??
? ? ? rs=stat.executeQuery("select ename,empno from emp");? ? ??
? ? ? //5處理結果? ? ? ? ? ?
?while(rs.next()){ //? ? ?
?? ? ? ? int empno=rs.getInt(1); //? ? ? ? ? ?
?? String empname=rs.getString(2);? ? ? ? ? ?
?? ? int empno=rs.getInt("empno");? ? ? ??
? ? ? ? String empname=rs.getString("ename");? ? ? ? ?
?? ? ? System.out.println(empno+"...."+empname);? ? ? ? ? ? }
PreparedStatement
該P r e p a r e d S t a t e m e n t 的 接口擴展了Statement接口疙驾,它為您提供了一個通用的Statement對象有兩個優(yōu) 點附加功能。
作用:1預編譯郭毕,效率高? 2 安全它碎,避免SQL注入
Connection con = null;
? ? ? ? Statement stmt = null;
? ? ? ? ResultSet resultSet = null;
? ? ? ? try {
? ? ? ? ? ? con = JDBCUtils.getConnection();
? ? ? ? ? ? //? 占位符
? ? ? ? ? ? //預制型的sql語句 好處: 防止sql注入, 語法清晰
? ? ? ? ? ? PreparedStatement ps = con.prepareStatement("select * from users where user_name=?");
? ? ? ? ? ? ps.setString(1,userName);
? ? ? ? ? ? resultSet = ps.executeQuery(); //執(zhí)行
? ? ? ? ? ? while (resultSet.next()) {
? ? ? ? ? ? ? ? int id = resultSet.getInt("id");
? ? ? ? ? ? ? ? String name = resultSet.getString("user_name");
? ? ? ? ? ? ? ? String passsword = resultSet.getString("password");
? ? ? ? ? ? ? ? System.out.println("id:" + id + ",userName:" + name + ",password:" + passsword);
? ? ? ? ? ? }
? ? ? ? } catch (Exception e) {
? ? ? ? ? ? e.printStackTrace();
? ? ? ? }finally {
? ? ? ? ? ? JDBCUtils.close(resultSet,stmt,con);
? ? ? ? }
JDBC批處理
1 Statement批處理
以下是使用語句對象的批處理的典型步驟
1 注冊驅動獲取連接 2 使用 c r e a t e S t a t e m e n t () 方法創(chuàng)建Statement對象。 3 使用 s e t A u t o C o m mit () 將auto-commit設置為false 。 4 使用 a d d B a t c h () 方法在創(chuàng)建的語句對象上添加您喜歡的SQL語句到批處理中扳肛。 5 在創(chuàng)建的語句對象上使用 e x e c u t e B a t c h () 方法執(zhí)行所有SQL語句傻挂。 6 使用 c o m mit () 方法提交所有更改。 7 釋放資源
Statement stmt = conn.createStatement();
conn.setAutoCommit(false);
String SQL = "INSERT INTO Employees (id, first, last, age) " + ? ? ? ? ? ? "VALUES(200,'Zia', 'Ali', 30)";? stmt.addBatch(SQL);
String SQL = "INSERT INTO Employees (id, first, last, age) " + ? ? ? ? ? ? "VALUES(201,'Raj', 'Kumar', 35)";
stmt.addBatch(SQL);?
String SQL = "UPDATE Employees SET age = 35 " + ? ? ? ? ? ? "WHER3;
sstmt.addBatch(SQL);
?int[] count = stmt.executeBatch();
conn.commit();
1.2 PrepareStatement批處理
1. 使用占位符創(chuàng)建SQL語句挖息。 2. 使用 p r e p a r e S t a t e m e n t () 方法創(chuàng)建PrepareStatement對象金拒。 3. 使用 s e t A u t o C o m mit () 將auto-commit設置為false 。 4. 使用 a d d B a t c h () 方法在創(chuàng)建的語句對象上添加您喜歡的SQL語句到批處理中旋讹。 5. 在創(chuàng)建的語句對象上使用 e x e c u t e B a t c h () 方法執(zhí)行所有SQL語句殖蚕。 6. 最后,使用 c o m mit () 方法提交所有更改沉迹。
String SQL = "INSERT INTO Employees (id, first, last, age) " + ? ? ? ? ? ? "VALUES(?, ?, ?, ?)";
PreparedStatemen pstmt = conn.prepareStatement(SQL);
?conn.setAutoCommit(false);
?pstmt.setInt( 1, 400 );?
pstmt.setString( 2, "Pappu" );?
pstmt.setString( 3, "Singh" );?
pstmt.setInt( 4, 33 );
?pstmt.addBatch();
pstmt.setInt( 1, 401 );
pstmt.setString( 2, "Pawan" );
?pstmt.setString( 3, "Singh" );
?pstmt.setInt( 4, 31 );?
?pstmt.addBatch();
事務的四大特點?
Atomicity(原子性)? ? 表示一個事務內的所有操作是一個整體,要么全部成功害驹,要么全部失敗
Consistency(一致性)? ? 表示一個事務內有一個操作失敗時鞭呕,所有的更改過的數(shù)據(jù)都必須回滾到修改前狀態(tài)
Isolation(隔離性)? 事務查看數(shù)據(jù)時數(shù)據(jù)所處的狀態(tài),要么是另一并發(fā)事務修改它之前的狀態(tài)宛官,要么是另一事務修改它 之后的狀態(tài)葫松,事務不會查看中間狀態(tài)的數(shù)據(jù)。
Durability(持久性)
? 持久性事務完成之后底洗,它對于系統(tǒng)的影響是永久性的腋么。
#開啟事務 START TRANSACTION;??
? ?# connection.setAutoCommit(false);?
UPDATE account SET money=money-1000 WHERE id=1;?
UPDATE account SET money=money+1000 WHERE id=2;
?#提交事務 COMMIT;#connection.commit();
?#connection.rollback();
事務隔離級別
? SQL標準定義了4類隔離級別,包括了一些具體規(guī)則亥揖,用來限定事務內外的哪些改變是可見的珊擂,哪些 是不可見的。低級別的隔離級一般支持更高的并發(fā)處理费变,并擁有更低的系統(tǒng)開銷摧扇。
Read Uncommitted(讀取未提交內容)
? ? ? 在該隔離級別,所有事務都可以看到其他未提交事務的執(zhí)行結果挚歧。本隔離級別很少用于實際應用扛稽, 因為它的性能也不比其他級別好多少。讀取未提交的數(shù)據(jù)滑负,也被稱之為臟讀(Dirty Read)在张。
Read Committed(讀取提交內容)
? ? ? 這是大多數(shù)數(shù)據(jù)庫系統(tǒng)的默認隔離級別(但不是MySQL默認的)。它滿足了隔離的簡單定義:一個 事務只能看見已經提交事務所做的改變矮慕。這種隔離級別出現(xiàn)不可重復讀(Nonrepeatable Read)問題帮匾, 因為同一事務的其他實例在該實例處理其間可能會有新的commit,所以同一select可能返回不同結果凡傅。
? ? ? ? ? ? ? ? // TODO Auto-generated catch block? ? ? ? ? ? ? ? e1.printStackTrace();? ? ? ? ? ? }? ? ? ? }finally {? ? ? ? ? ? if(pstat1!=null){? ? ? ? ? ? ? ? try {? ? ? ? ? ? ? ? ? ? pstat1.close();? ? ? ? ? ? ? ? } catch (SQLException e) {? ? ? ? ? ? ? ? ? ? // TODO Auto-generated catch block? ? ? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? ? ? if(pstat2!=null){? ? ? ? ? ? ? ? try {? ? ? ? ? ? ? ? ? ? pstat2.close();? ? ? ? ? ? ? ? } catch (SQLException e) {? ? ? ? ? ? ? ? ? ? // TODO Auto-generated catch block? ? ? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? ? ? if(connection!=null){? ? ? ? ? ? ? ? try {? ? ? ? ? ? ? ? ? ? connection.close();? ? ? ? ? ? ? ? } catch (SQLException e) {? ? ? ? ? ? ? ? ? ? // TODO Auto-generated catch block? ? ? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }? ? }
#開啟事務 START TRANSACTION; ? ? # connection.setAutoCommit(false); UPDATE account SET money=money-1000 WHERE id=1; UPDATE account SET money=money+1000 WHERE id=2; #提交事務 COMMIT;#connection.commit(); #回滾 ROLLBACK; #connection.rollback();
Repeatable Read 可重讀
? ? ? 這是MySQL的默認事務隔離級別辟狈,它確保同一事務的多個實例在并發(fā)讀取數(shù)據(jù)時,會看到同樣的數(shù) 據(jù)行。不過理論上哼转,這會導致另一個棘手的問題:幻讀(Phantom Read)明未。簡單的說,幻讀指當用戶讀 取某一范圍的數(shù)據(jù)行時壹蔓,另一個事務又在該范圍內插入了新行趟妥,當用戶再讀取該范圍的數(shù)據(jù)行時,會發(fā) 現(xiàn)有新的“幻讀” 行佣蓉。InnoDB和Falcon存儲引擎通過多版本并發(fā)控制(MVCC披摄,Multiversion Concurrency Control)機制解決了該問題。
Serializable 可串行化
? ? ? ? 這是最高的隔離級別勇凭,它通過強制事務排序疚膊,使之不可能相互沖突,從而解決幻讀問題虾标。簡言之寓盗, 它是在每個讀的數(shù)據(jù)行上加上共享鎖。在這個級別璧函,可能導致大量的超時現(xiàn)象和鎖競爭傀蚌。效率最低的。
? ? ? 這四種隔離級別采取不同的鎖類型來實現(xiàn)蘸吓,若讀取的是同一個數(shù)據(jù)的話善炫,就容易發(fā)生問題。
總結
1 批處理
Statement實現(xiàn)批處理
? stat.addBatch(sql);// insert? update? delete
? stat.executeBatch();
PreparetedStatement
? pstat.addBatch();
? pstat.executeBatch();
? pstat.clearBatch();
2 jdbc操作大數(shù)據(jù)
? 大文本 tinytext? text? mediumtext? longtext
? setAsciiStream();
? setCharacterStream();
? setBinaryStream();
? 二進制tinyblob? blob? mediunblob? longblob
? setBinaryStream();
3 事務:一組要么同時執(zhí)行成功,要么同時失敗的SQL語句。是數(shù)據(jù)庫操作的一個不能分割執(zhí)行單元误甚。
四個特性:
原子性? A: 不能分割
一致性 C:事務執(zhí)行前后保持一致
隔離型 I: 事務與事務之間對數(shù)據(jù)的讀取控制
持久性 D:事務提交或回滾之后,永久保存數(shù)據(jù)庫舅桩。
4? 修改隔離級別
java代碼更改隔離級別
5 保存點
SavePoint
? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? }? ? ? ? }? ? }
#修改事務的隔離級別: SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE] #查看事務隔離級別 SELECT @@tx_isolation;
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
IO流
定義
IO流用來處理設備之間的數(shù)據(jù)傳輸
Java對數(shù)據(jù)的操作是通過流的方式
Java用于操作流的類都在IO包中
流按流向分為兩種:輸入流,輸出流雨膨。I/O
流按操作類型分為兩種:
字節(jié)流 : 字節(jié)流可以操作任何數(shù)據(jù),因為在計算機中任何數(shù)據(jù)都是以字節(jié)的形式存儲的
字符流 : 字符流只能操作純字符數(shù)據(jù)擂涛,比較方便。
IO流常用父類
字節(jié)流的抽象父類:
InputStream
OutputStream
字符流的抽象父類:
Reader
Writer
每次讀取一個字節(jié)的速度實在是太慢了,實際開發(fā)中根本無法使用
所以,java為我們提供了一次獲取多個字節(jié)的方法, read(byte[] b), 允許一次獲取一個數(shù)組長度的字節(jié)
available()方法
這個方法可以幫我們獲取資源中剩余的長度
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:\\騎在銀龍的背上.mp3");
FileOutputStream fos = new FileOutputStream("d:\\音樂副本.mp3");
//創(chuàng)建一個和資源文件大小相同的字節(jié)數(shù)組
//byte[] bs = new byte[fis.available()];
//fis.read(bs);
//fos.write(bs);
? ? byte[] bs = new byte[1024];
? ? int len;
? ? //數(shù)據(jù)傳輸消耗的時間遠遠大于java內部數(shù)據(jù)處理的時間
? ? while((len=fis.read(bs))!=-1){
? ? ? ? for (int i = 0; i < len; i++) {
? ? ? ? ? ? bs[i] = (byte)(bs[i]^123);
? ? ? ? }
? ? ? ? fos.write(bs,0,len);
? ? }
fis.close();
fos.close();
}
所有我們可以創(chuàng)建一個和資源文件大小相等長度小數(shù)組來裝載數(shù)據(jù)
字節(jié)輸入緩沖流(BufferedInputStream)
定義
我們都知道單個字節(jié)的讀取是效率非常低下的, 所以我們使用了小數(shù)組的方法進行流的讀取和寫入
java中已經幫我們實現(xiàn)了, 這就是緩沖區(qū)的概念, 也是一次性讀取一個數(shù)組,然后將這個數(shù)組放入內存中供我們使用
緩沖流只是一個殼,實際還是字節(jié)流在工作
構造方法
BufferedInputStream(InputStream in)
創(chuàng)建一個BufferedInputStream 并保存其參數(shù), 即輸入in ,一遍將來使用
BuffferedInputStream(InputStream in , int size)
創(chuàng)建一個具有指定緩沖區(qū)大小的BufferedInputStream并保存其參數(shù), 即輸入流in,以便將來使用
常用方法
read() : 一次讀取一個字節(jié)
read(byte[] b, int off, int len) : 從此字節(jié)輸入流中給定偏移量處開始各字節(jié)讀取到指定的byte數(shù)組中
close() : 關閉并釋放資源,實際關閉的是內部真正工作的字節(jié)流
注意事項
BufferedInputStream內部建立一個緩沖區(qū)域,在讀取文件的時候, 一次性讀取大量的字節(jié), 緩沖到緩沖區(qū)當中, 然后再反給我們, 看著沒有變化, 區(qū)別在于一個直接操作硬盤, 一個是操作內存, 效率不可相提并論
字節(jié)輸出緩沖流(BufferedOutputStream)
定義
單個字節(jié)的寫入是效率及其低下的, 所以我們使用了小數(shù)組的形式進行寫入, 一次寫入一個數(shù)組的數(shù)據(jù)
java中給我們提供了輸出緩沖區(qū)流,將我們寫的字節(jié)先存放到一個小數(shù)組中,等數(shù)組滿了之后再寫入到本地去
在流關閉之前, 會有一次寫入動作, 這樣就避免了最后一次讀取時, 緩沖區(qū)沒有滿不能寫入的問題
構造方法
BufferedOutputStream(OutputStram out)
創(chuàng)建一個新的緩沖輸出流聊记,以將數(shù)據(jù)寫入指定的底層輸出流
BufferedOutputStream(OutputStream out, int size)
創(chuàng)建一個新的緩沖輸出流撒妈,以將具有指定緩沖區(qū)大小的數(shù)據(jù)寫入指定的底層輸出流
常用方法
write(int b) : 將指定的字節(jié)寫入此緩沖流的輸出流
write(byte[] b, int off, int len) : 將指定byte數(shù)組中從偏移量off開始的len個字節(jié)吸入此緩沖流的輸入流
flush() : 刷新此緩沖流的輸出流
close() : 關閉流,并釋放資源
演示
publicstaticvoidmain(String[]args)throwsException{
? ? FileOutputStreamfos=newFileOutputStream("d:\\ddd.txt");
? ? BufferedOutputStreambos=newBufferedOutputStream(fos);
? ? for(inti=0;i<10000;i++) {
? ? ? ? bos.write(97);
? ? }
? ? bos.close();
}
注意事項
緩沖流就一個殼, 他不能實際和本地文件建立連接, 本質還是通過InputStream和OutputStream來工作
將一個文件夾復制到另一個地方
public static void copy(String srcname,String target) throws Exception{
File srcFile = new File(srcname);
File targetFile = new File(new File(target),srcFile.getName());
targetFile.mkdir();
File[] files = srcFile.listFiles();
if(files!=null){
for (File file : files) {
if (file.isFile()) {
FileInputStream fis = new FileInputStream(file);
//targetFile+文件名
File file2 = new File(targetFile,file.getName());
FileOutputStream fos = new FileOutputStream(file2);
byte[] bs = new byte[1024*8];
int len ;
while((len=fis.read(bs))!=-1){
fos.write(bs,0,len);
}
fis.close();
fos.close();
}else{
copy(file.getAbsolutePath(),targetFile.getAbsolutePath());
}
}
}
}