JDBC、IO流

Junit是一个基于Java语言的单元测试框架。是白盒测试的一种技术。

①测试方法上必须使用@Test进行修饰

      ②测试方法必须使用public void 进行修饰,不能带任何的参数

      ③新建一个源代码目录来存放我们的测试代码,即将测试代码和项目业务代码分开

      ④测试类所在的包名应该和被测试类所在的包名保持一致

      ⑤测试单元中的每个方法必须可以独立测试,测试方法间不能有任何的依赖

      ⑥测试类使用Test作为类名的后缀(不是必须)

      ⑦测试方法使用test作为方法名的前缀(不是必须)

JDBC(Java DataBase Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种 关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以 构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。

JDBC可以在各种平台上使用Java,如Windows,Mac OS和各种版本的UNIX。

构建JDBC应用程序涉及以下六个步骤:

导入JDBC驱动包:需要下载包含数据库编程所需的JDBC的jar包。

 注册JDBC驱动程序:要求您初始化驱动程序,以便您可以打开与数据库的通信通道。

 创建连接:需要使用 D riv e r M a n a g e r.g e t C o n n e c tio n () 方法创建一个Connection对象,该对象表示 与数据库的物理连接。

 执行查询:需要使用类型为Statement的对象来构建和提交SQL语句到数据库。 

从结果集中提取数据:需要使用相应的 R e s ult S e t .g e t X X X () 方法从结果集中检索数据。 

释放资源:需要明确地关闭所有数据库资源,而不依赖于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创建命令(语句)对象           

 stat=connection.createStatement();        

    //执行命令查询      

      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对象有两个优 点附加功能。

作用: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(); //执行

            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 () 方法创建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 () 方法在创建的语句对象上添加您喜欢的SQL语句到批处理中。 5 在创建的语句对象上使用 e x e c u t e B a t c h () 方法执行所有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. 使用占位符创建SQL语句。 2. 使用 p r e p a r e S t a t e m e n t () 方法创建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 () 方法在创建的语句对象上添加您喜欢的SQL语句到批处理中。 5. 在创建的语句对象上使用 e x e c u t e B a t c h () 方法执行所有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(一致性)    表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改前状态

Isolation(隔离性)  事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它 之后的状态,事务不会查看中间状态的数据。

Durability(持久性)

  持久性事务完成之后,它对于系统的影响是永久性的。

#开启事务 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类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些 是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。

Read Uncommitted(读取未提交内容)

      在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用, 因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。

Read Committed(读取提交内容)

      这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个 事务只能看见已经提交事务所做的改变。这种隔离级别出现不可重复读(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的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数 据行。不过理论上,这会导致另一个棘手的问题:幻读(Phantom Read)。简单的说,幻读指当用户读 取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发 现有新的“幻读” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。

Serializable 可串行化

        这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之, 它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。效率最低的。

      这四种隔离级别采取不同的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。

总结

1 批处理

Statement实现批处理

  stat.addBatch(sql);// insert  update  delete

  stat.executeBatch();

PreparetedStatement

  pstat.addBatch();

  pstat.executeBatch();

  pstat.clearBatch();

2 jdbc操作大数据

  大文本 tinytext  text  mediumtext  longtext

  setAsciiStream();

  setCharacterStream();

  setBinaryStream();

  二进制tinyblob  blob  mediunblob  longblob

  setBinaryStream();

3 事务:一组要么同时执行成功,要么同时失败的SQL语句。是数据库操作的一个不能分割执行单元。

四个特性:

原子性  A: 不能分割

一致性 C:事务执行前后保持一致

隔离型 I: 事务与事务之间对数据的读取控制

持久性 D:事务提交或回滚之后,永久保存数据库。

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流用来处理设备之间的数据传输

Java对数据的操作是通过流的方式

Java用于操作流的类都在IO包中

流按流向分为两种:输入流,输出流。I/O

流按操作类型分为两种:

字节流 : 字节流可以操作任何数据,因为在计算机中任何数据都是以字节的形式存储的

字符流 : 字符流只能操作纯字符数据,比较方便。

IO流常用父类

字节流的抽象父类:

InputStream

OutputStream

字符流的抽象父类:

Reader

Writer

每次读取一个字节的速度实在是太慢了,实际开发中根本无法使用

所以,java为我们提供了一次获取多个字节的方法, read(byte[] b), 允许一次获取一个数组长度的字节

available()方法

这个方法可以帮我们获取资源中剩余的长度

public static void main(String[] args) throws Exception {


FileInputStream fis = new FileInputStream("d:\\骑在银龙的背上.mp3");

FileOutputStream fos = new FileOutputStream("d:\\音乐副本.mp3");

//创建一个和资源文件大小相同的字节数组

//byte[] bs = new byte[fis.available()];

//fis.read(bs);

//fos.write(bs);

    byte[] bs = new byte[1024];

    int len;

    //数据传输消耗的时间远远大于java内部数据处理的时间

    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();

}

所有我们可以创建一个和资源文件大小相等长度小数组来装载数据

字节输入缓冲流(BufferedInputStream)

定义

我们都知道单个字节的读取是效率非常低下的, 所以我们使用了小数组的方法进行流的读取和写入

java中已经帮我们实现了, 这就是缓冲区的概念, 也是一次性读取一个数组,然后将这个数组放入内存中供我们使用

缓冲流只是一个壳,实际还是字节流在工作

构造方法

BufferedInputStream(InputStream in)

创建一个BufferedInputStream 并保存其参数, 即输入in ,一遍将来使用

BuffferedInputStream(InputStream in , int size)

创建一个具有指定缓冲区大小的BufferedInputStream并保存其参数, 即输入流in,以便将来使用

常用方法

read() : 一次读取一个字节

read(byte[] b, int off, int len) : 从此字节输入流中给定偏移量处开始各字节读取到指定的byte数组中

close() : 关闭并释放资源,实际关闭的是内部真正工作的字节流

注意事项

BufferedInputStream内部建立一个缓冲区域,在读取文件的时候, 一次性读取大量的字节, 缓冲到缓冲区当中, 然后再反给我们, 看着没有变化, 区别在于一个直接操作硬盘, 一个是操作内存, 效率不可相提并论

字节输出缓冲流(BufferedOutputStream)

定义

单个字节的写入是效率及其低下的, 所以我们使用了小数组的形式进行写入, 一次写入一个数组的数据

java中给我们提供了输出缓冲区流,将我们写的字节先存放到一个小数组中,等数组满了之后再写入到本地去

在流关闭之前, 会有一次写入动作, 这样就避免了最后一次读取时, 缓冲区没有满不能写入的问题

构造方法

BufferedOutputStream(OutputStram out)

创建一个新的缓冲输出流,以将数据写入指定的底层输出流

BufferedOutputStream(OutputStream out, int size)

创建一个新的缓冲输出流,以将具有指定缓冲区大小的数据写入指定的底层输出流

常用方法

write(int b) : 将指定的字节写入此缓冲流的输出流

write(byte[] b, int off, int len) : 将指定byte数组中从偏移量off开始的len个字节吸入此缓冲流的输入流

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());

}

}

}

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容