Junit是一個(gè)基于Java語言的單元測試框架。是白盒測試的一種技術(shù)。
①測試方法上必須使用@Test進(jìn)行修飾
? ? ? ②測試方法必須使用public void 進(jìn)行修飾,不能帶任何的參數(shù)
? ? ? ③新建一個(gè)源代碼目錄來存放我們的測試代碼,即將測試代碼和項(xiàng)目業(yè)務(wù)代碼分開
? ? ? ④測試類所在的包名應(yīng)該和被測試類所在的包名保持一致
? ? ? ⑤測試單元中的每個(gè)方法必須可以獨(dú)立測試,測試方法間不能有任何的依賴
? ? ? ⑥測試類使用Test作為類名的后綴(不是必須)
? ? ? ⑦測試方法使用test作為方法名的前綴(不是必須)
JDBC(Java DataBase Connectivity,java數(shù)據(jù)庫連接)是一種用于執(zhí)行SQL語句的Java API,可以為多種 關(guān)系數(shù)據(jù)庫提供統(tǒng)一訪問,它由一組用Java語言編寫的類和接口組成。JDBC提供了一種基準(zhǔn),據(jù)此可以 構(gòu)建更高級的工具和接口,使數(shù)據(jù)庫開發(fā)人員能夠編寫數(shù)據(jù)庫應(yīng)用程序。
JDBC可以在各種平臺上使用Java,如Windows,Mac OS和各種版本的UNIX。
構(gòu)建JDBC應(yīng)用程序涉及以下六個(gè)步驟:
導(dǎo)入JDBC驅(qū)動(dòng)包:需要下載包含數(shù)據(jù)庫編程所需的JDBC的jar包。
?注冊JDBC驅(qū)動(dòng)程序:要求您初始化驅(qū)動(dòng)程序,以便您可以打開與數(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)建一個(gè)Connection對象,該對象表示 與數(shù)據(jù)庫的物理連接。
?執(zhí)行查詢:需要使用類型為Statement的對象來構(gòu)建和提交SQL語句到數(shù)據(jù)庫。?
從結(jié)果集中提取數(shù)據(jù):需要使用相應(yīng)的 R e s ult S e t .g e t X X X () 方法從結(jié)果集中檢索數(shù)據(jù)。?
釋放資源:需要明確地關(guān)閉所有數(shù)據(jù)庫資源,而不依賴于JVM的垃圾收集。
public class JdbcDemo2 {?
?public static void main(String[] args) {?
?Connection connection=null;
?Statement stat=null;
?ResultSet rs=null; //2注冊驅(qū)動(dòng)?
?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處理結(jié)果? ? ? ? ? ?
?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(yáng) r e p a r e d S t a t e m e n t 的 接口擴(kuò)展了Statement接口,它為您提供了一個(gè)通用的Statement對象有兩個(gè)優(yōu) 點(diǎn)附加功能。
作用:1預(yù)編譯,效率高? 2 安全,避免SQL注入
Connection con = null;
? ? ? ? Statement stmt = null;
? ? ? ? ResultSet resultSet = null;
? ? ? ? try {
? ? ? ? ? ? con = JDBCUtils.getConnection();
? ? ? ? ? ? //? 占位符
? ? ? ? ? ? //預(yù)制型的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 注冊驅(qū)動(dòng)獲取連接 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設(shè)置為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設(shè)置為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();
事務(wù)的四大特點(diǎn)?
Atomicity(原子性)? ? 表示一個(gè)事務(wù)內(nèi)的所有操作是一個(gè)整體,要么全部成功,要么全部失敗
Consistency(一致性)? ? 表示一個(gè)事務(wù)內(nèi)有一個(gè)操作失敗時(shí),所有的更改過的數(shù)據(jù)都必須回滾到修改前狀態(tài)
Isolation(隔離性)? 事務(wù)查看數(shù)據(jù)時(shí)數(shù)據(jù)所處的狀態(tài),要么是另一并發(fā)事務(wù)修改它之前的狀態(tài),要么是另一事務(wù)修改它 之后的狀態(tài),事務(wù)不會(huì)查看中間狀態(tài)的數(shù)據(jù)。
Durability(持久性)
? 持久性事務(wù)完成之后,它對于系統(tǒng)的影響是永久性的。
#開啟事務(wù) START TRANSACTION;??
? ?# connection.setAutoCommit(false);?
UPDATE account SET money=money-1000 WHERE id=1;?
UPDATE account SET money=money+1000 WHERE id=2;
?#提交事務(wù) COMMIT;#connection.commit();
?#connection.rollback();
事務(wù)隔離級別
? SQL標(biāo)準(zhǔn)定義了4類隔離級別,包括了一些具體規(guī)則,用來限定事務(wù)內(nèi)外的哪些改變是可見的,哪些 是不可見的。低級別的隔離級一般支持更高的并發(fā)處理,并擁有更低的系統(tǒng)開銷。
Read Uncommitted(讀取未提交內(nèi)容)
? ? ? 在該隔離級別,所有事務(wù)都可以看到其他未提交事務(wù)的執(zhí)行結(jié)果。本隔離級別很少用于實(shí)際應(yīng)用, 因?yàn)樗男阅芤膊槐绕渌墑e好多少。讀取未提交的數(shù)據(jù),也被稱之為臟讀(Dirty Read)。
Read Committed(讀取提交內(nèi)容)
? ? ? 這是大多數(shù)數(shù)據(jù)庫系統(tǒng)的默認(rèn)隔離級別(但不是MySQL默認(rèn)的)。它滿足了隔離的簡單定義:一個(gè) 事務(wù)只能看見已經(jīng)提交事務(wù)所做的改變。這種隔離級別出現(xiàn)不可重復(fù)讀(Nonrepeatable Read)問題, 因?yàn)橥皇聞?wù)的其他實(shí)例在該實(shí)例處理其間可能會(huì)有新的commit,所以同一select可能返回不同結(jié)果。
? ? ? ? ? ? ? ? // 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();? ? ? ? ? ? ? ? }? ? ? ? ? ? }? ? ? ? }? ? }
#開啟事務(wù) START TRANSACTION; ? ? # connection.setAutoCommit(false); UPDATE account SET money=money-1000 WHERE id=1; UPDATE account SET money=money+1000 WHERE id=2; #提交事務(wù) COMMIT;#connection.commit(); #回滾 ROLLBACK; #connection.rollback();
Repeatable Read 可重讀
? ? ? 這是MySQL的默認(rèn)事務(wù)隔離級別,它確保同一事務(wù)的多個(gè)實(shí)例在并發(fā)讀取數(shù)據(jù)時(shí),會(huì)看到同樣的數(shù) 據(jù)行。不過理論上,這會(huì)導(dǎo)致另一個(gè)棘手的問題:幻讀(Phantom Read)。簡單的說,幻讀指當(dāng)用戶讀 取某一范圍的數(shù)據(jù)行時(shí),另一個(gè)事務(wù)又在該范圍內(nèi)插入了新行,當(dāng)用戶再讀取該范圍的數(shù)據(jù)行時(shí),會(huì)發(fā) 現(xiàn)有新的“幻讀” 行。InnoDB和Falcon存儲(chǔ)引擎通過多版本并發(fā)控制(MVCC,Multiversion Concurrency Control)機(jī)制解決了該問題。
Serializable 可串行化
? ? ? ? 這是最高的隔離級別,它通過強(qiáng)制事務(wù)排序,使之不可能相互沖突,從而解決幻讀問題。簡言之, 它是在每個(gè)讀的數(shù)據(jù)行上加上共享鎖。在這個(gè)級別,可能導(dǎo)致大量的超時(shí)現(xiàn)象和鎖競爭。效率最低的。
? ? ? 這四種隔離級別采取不同的鎖類型來實(shí)現(xiàn),若讀取的是同一個(gè)數(shù)據(jù)的話,就容易發(fā)生問題。
總結(jié)
1 批處理
Statement實(shí)現(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();
? 二進(jìn)制tinyblob? blob? mediunblob? longblob
? setBinaryStream();
3 事務(wù):一組要么同時(shí)執(zhí)行成功,要么同時(shí)失敗的SQL語句。是數(shù)據(jù)庫操作的一個(gè)不能分割執(zhí)行單元。
四個(gè)特性:
原子性? A: 不能分割
一致性 C:事務(wù)執(zhí)行前后保持一致
隔離型 I: 事務(wù)與事務(wù)之間對數(shù)據(jù)的讀取控制
持久性 D:事務(wù)提交或回滾之后,永久保存數(shù)據(jù)庫。
4? 修改隔離級別
java代碼更改隔離級別
5 保存點(diǎn)
SavePoint
? ? ? ? ? ? ? ? e.printStackTrace();? ? ? ? ? ? }? ? ? ? }? ? }
#修改事務(wù)的隔離級別: SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE] #查看事務(wù)隔離級別 SELECT @@tx_isolation;
conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
IO流
定義
IO流用來處理設(shè)備之間的數(shù)據(jù)傳輸
Java對數(shù)據(jù)的操作是通過流的方式
Java用于操作流的類都在IO包中
流按流向分為兩種:輸入流,輸出流。I/O
流按操作類型分為兩種:
字節(jié)流 : 字節(jié)流可以操作任何數(shù)據(jù),因?yàn)樵谟?jì)算機(jī)中任何數(shù)據(jù)都是以字節(jié)的形式存儲(chǔ)的
字符流 : 字符流只能操作純字符數(shù)據(jù),比較方便。
IO流常用父類
字節(jié)流的抽象父類:
InputStream
OutputStream
字符流的抽象父類:
Reader
Writer
每次讀取一個(gè)字節(jié)的速度實(shí)在是太慢了,實(shí)際開發(fā)中根本無法使用
所以,java為我們提供了一次獲取多個(gè)字節(jié)的方法, read(byte[] b), 允許一次獲取一個(gè)數(shù)組長度的字節(jié)
available()方法
這個(gè)方法可以幫我們獲取資源中剩余的長度
public static void main(String[] args) throws Exception {
FileInputStream fis = new FileInputStream("d:\\騎在銀龍的背上.mp3");
FileOutputStream fos = new FileOutputStream("d:\\音樂副本.mp3");
//創(chuàng)建一個(gè)和資源文件大小相同的字節(jié)數(shù)組
//byte[] bs = new byte[fis.available()];
//fis.read(bs);
//fos.write(bs);
? ? byte[] bs = new byte[1024];
? ? int len;
? ? //數(shù)據(jù)傳輸消耗的時(shí)間遠(yuǎn)遠(yuǎn)大于java內(nèi)部數(shù)據(jù)處理的時(shí)間
? ? 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)建一個(gè)和資源文件大小相等長度小數(shù)組來裝載數(shù)據(jù)
字節(jié)輸入緩沖流(BufferedInputStream)
定義
我們都知道單個(gè)字節(jié)的讀取是效率非常低下的, 所以我們使用了小數(shù)組的方法進(jìn)行流的讀取和寫入
java中已經(jīng)幫我們實(shí)現(xiàn)了, 這就是緩沖區(qū)的概念, 也是一次性讀取一個(gè)數(shù)組,然后將這個(gè)數(shù)組放入內(nèi)存中供我們使用
緩沖流只是一個(gè)殼,實(shí)際還是字節(jié)流在工作
構(gòu)造方法
BufferedInputStream(InputStream in)
創(chuàng)建一個(gè)BufferedInputStream 并保存其參數(shù), 即輸入in ,一遍將來使用
BuffferedInputStream(InputStream in , int size)
創(chuàng)建一個(gè)具有指定緩沖區(qū)大小的BufferedInputStream并保存其參數(shù), 即輸入流in,以便將來使用
常用方法
read() : 一次讀取一個(gè)字節(jié)
read(byte[] b, int off, int len) : 從此字節(jié)輸入流中給定偏移量處開始各字節(jié)讀取到指定的byte數(shù)組中
close() : 關(guān)閉并釋放資源,實(shí)際關(guān)閉的是內(nèi)部真正工作的字節(jié)流
注意事項(xiàng)
BufferedInputStream內(nèi)部建立一個(gè)緩沖區(qū)域,在讀取文件的時(shí)候, 一次性讀取大量的字節(jié), 緩沖到緩沖區(qū)當(dāng)中, 然后再反給我們, 看著沒有變化, 區(qū)別在于一個(gè)直接操作硬盤, 一個(gè)是操作內(nèi)存, 效率不可相提并論
字節(jié)輸出緩沖流(BufferedOutputStream)
定義
單個(gè)字節(jié)的寫入是效率及其低下的, 所以我們使用了小數(shù)組的形式進(jìn)行寫入, 一次寫入一個(gè)數(shù)組的數(shù)據(jù)
java中給我們提供了輸出緩沖區(qū)流,將我們寫的字節(jié)先存放到一個(gè)小數(shù)組中,等數(shù)組滿了之后再寫入到本地去
在流關(guān)閉之前, 會(huì)有一次寫入動(dòng)作, 這樣就避免了最后一次讀取時(shí), 緩沖區(qū)沒有滿不能寫入的問題
構(gòu)造方法
BufferedOutputStream(OutputStram out)
創(chuàng)建一個(gè)新的緩沖輸出流,以將數(shù)據(jù)寫入指定的底層輸出流
BufferedOutputStream(OutputStream out, int size)
創(chuàng)建一個(gè)新的緩沖輸出流,以將具有指定緩沖區(qū)大小的數(shù)據(jù)寫入指定的底層輸出流
常用方法
write(int b) : 將指定的字節(jié)寫入此緩沖流的輸出流
write(byte[] b, int off, int len) : 將指定byte數(shù)組中從偏移量off開始的len個(gè)字節(jié)吸入此緩沖流的輸入流
flush() : 刷新此緩沖流的輸出流
close() : 關(guān)閉流,并釋放資源
演示
publicstaticvoidmain(String[]args)throwsException{
? ? FileOutputStreamfos=newFileOutputStream("d:\\ddd.txt");
? ? BufferedOutputStreambos=newBufferedOutputStream(fos);
? ? for(inti=0;i<10000;i++) {
? ? ? ? bos.write(97);
? ? }
? ? bos.close();
}
注意事項(xiàng)
緩沖流就一個(gè)殼, 他不能實(shí)際和本地文件建立連接, 本質(zhì)還是通過InputStream和OutputStream來工作
將一個(gè)文件夾復(fù)制到另一個(gè)地方
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());
}
}
}
}