Java学习-JDBC练习

 JDBC总结

1.导入驱动包、加载具体驱动: Class.forName("具体的驱动类  比如  com.mysql.jdbc.Driver  ");

2.与数据库建立连接:Connection c = DriverManager.getConnection("......")

3.通过connection,获取操作数据库的对象【statement、preparedStatement【更推荐】、callableStatement】:Statement s=c.createStatement();

4.处理结果集【ResultSet rs = s.getResultSet()】【while(rs.next()){ rs.getXXX(...)}】

基本异常:【 Class.forName抛出:ClassNotFoundException】【其余的都抛出:SQLException】

5.关闭顺序【finally{ 打开顺序与关闭顺序相反:先打开的  后关闭;后打开的  先关闭 }】

关闭前先确定是否为空,排除空指针异常】【if( !=null ){ 关闭xxx }】

 

 

练习1

借助循环,向数据库中插入100条数据,并在mysql-front中观察查询结果

 1 package jdbc;
 2 
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 
 8 public class TestJDBC {
 9     public static void main(String[] args) {
10         // 初始化驱动
11         try {
12             Class.forName("com.mysql.jdbc.Driver");
13         } catch (ClassNotFoundException e) {
14             // TODO Auto-generated catch block
15             e.printStackTrace();
16         }
17         // 使用try-with-resource的方式自动关闭连接,因为Connection和Statement都实现了AutoCloseable接口
18         try (
19                 Connection c = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8",
20                 "root", "admin"); 
21                 Statement s = c.createStatement();) {
22             s.execute("truncate table hero");
23             String name = null;
24             float hp = 100.0f;
25             int damage = 100;
26             for (int i = 0; i < 100; i++) {
27                 name = "\'" + "Hero-" + String.valueOf(i + 1) + "\'";    //注意格式,必须单引号'
28                 String sql = "insert into hero values(null," + name + "," + (hp++) + "," + (damage++) + ")";
29                 s.execute(sql);
30             }
31         } catch (SQLException e) {
32             // TODO Auto-generated catch block
33             e.printStackTrace();
34         }
35 
36     }
37 }

效果图:

 练习二

向数据库中插入100条数据,比较传统方式和数据库连接池方式的性能差异

1. 使用传统方式创建100个线程,每个线程都会创建新的连接,通过这个连接向数据库插入1条数据,然后关闭这个连接。

2. 使用数据库连接池的方式,创建一个有10条连接的连接池,然后创建100个线程,每个线程都会向连接池借用连接,借用到后,向数据库插入1条数据,然后归还这个连接。

通过时间统计,比较这两种方式的性能表现差异。

  1 package jdbc;
  2 
  3 import java.sql.Connection;
  4 import java.sql.DriverManager;
  5 import java.sql.SQLException;
  6 import java.sql.PreparedStatement;
  7 import java.util.ArrayList;
  8 import java.util.List;
  9 
 10 /*
 11  * 向数据库中插入100条数据,比较传统方式和数据库连接池方式的性能差异
 12 
 13 1. 使用传统方式创建100个线程,每个线程都会创建新的连接,通过这个连接向数据库插入1条数据,然后关闭这个连接。
 14 
 15 2. 使用数据库连接池的方式,创建一个有10条连接的连接池,然后创建100个线程,每个线程都会向连接池借用连接,借用到后,向数据库插入1条数据,然后归还这个连接。
 16 
 17 通过时间统计,比较这两种方式的性能表现差异。 
 18  */
 19 public class Test6 {
 20     public static void traditionalWay() {
 21         List<Thread> list = new ArrayList<>();
 22         for (int i = 0; i < 100; i++) {
 23             Thread t = new Thread() {
 24                 public void run() {
 25                     // 初始化驱动
 26                     try {
 27                         Class.forName("com.mysql.jdbc.Driver");
 28                     } catch (ClassNotFoundException e) {
 29                         e.printStackTrace();
 30                     }
 31                     // 建立连接
 32                     try (Connection c = DriverManager.getConnection(
 33                             "jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8", "root", "admin");){
 34                         String sql = "insert into hero values(null,?,?,?)";
 35                         PreparedStatement ps = c.prepareStatement(sql);
 36                         ps.setString(1, "Hero-traditional" );
 37                         ps.setFloat(2, 500f);
 38                         ps.setInt(3, 200);
 39                         ps.execute();
 40                     } catch (SQLException e) {
 41                         // TODO Auto-generated catch block
 42                         e.printStackTrace();
 43                     }
 44                     
 45                 }
 46             };
 47 //            t.start();    //不知为何在for循环里开始多线程总是出错(too many connections),改为在下面统一开始多线程就没问题
 48             list.add(t);
 49         }
 50         for (Thread x : list) {
 51             try {
 52                 x.start();    //统一开始多线程
 53                 x.join();
 54             } catch (InterruptedException e) {
 55                 // TODO Auto-generated catch block
 56                 e.printStackTrace();
 57             }
 58         }
 59 
 60     }
 61 
 62 
 63     public static void ConnectionPoolWay() {
 64         List<Thread> list = new ArrayList<>();
 65         ConnectionPool cp = new ConnectionPool(10);
 66         for (int i = 0; i < 100; i++) {
 67             Thread t = new Thread() {
 68                 public void run() {
 69                     Connection c = cp.getConnection();
 70                     String sql = "insert into hero values(null,?,?,?)";
 71                     try (PreparedStatement ps = c.prepareStatement(sql)) {
 72                         ps.setString(1, "Hero-ConnectionPool");
 73                         ps.setFloat(2, 500f);
 74                         ps.setInt(3, 200);
 75                         ps.execute();
 76                     } catch (SQLException e) {
 77                         // TODO Auto-generated catch block
 78                         e.printStackTrace();
 79                     }
 80                     cp.returnConnection(c);
 81                 }
 82             };
 83             t.start();
 84             list.add(t);
 85         }
 86         for (Thread x : list) {
 87             try {
 88                 x.join();
 89             } catch (InterruptedException e) {
 90                 // TODO Auto-generated catch block
 91                 e.printStackTrace();
 92             }
 93         }
 94     }
 95 
 96 
 97     public static class ConnectionPool {
 98         List<Connection> cs = new ArrayList<>();
 99         int size;
100 
101         public ConnectionPool(int size) {    //连接池大小
102             this.size = size;
103             init();
104         }
105         public void init() {
106 
107             // 这里恰恰不能使用try-with-resource的方式,因为这些连接都需要是"活"的,不要被自动关闭了
108             try {
109                 Class.forName("com.mysql.jdbc.Driver");
110                 for (int i = 0; i < size; i++) {
111                     Connection c = DriverManager.getConnection(
112                             "jdbc:mysql://127.0.0.1:3306/how2java?characterEncoding=UTF-8", "root", "admin");
113                     cs.add(c);
114 
115                 }
116             } catch (ClassNotFoundException e) {
117                 // TODO Auto-generated catch block
118                 e.printStackTrace();
119             } catch (SQLException e) {
120                 // TODO Auto-generated catch block
121                 e.printStackTrace();
122             }
123         }
124 
125         public synchronized Connection getConnection() {
126             while (cs.isEmpty()) {
127                 try {
128                     this.wait();
129                 } catch (InterruptedException e) {
130                     // TODO Auto-generated catch block
131                     e.printStackTrace();
132                 }
133             }
134             Connection c = cs.remove(0);
135             return c;
136         }
137 
138         public synchronized void returnConnection(Connection c) {
139             cs.add(c);
140             this.notifyAll();
141         }
142     }
143     public static void main(String[] args) {
144 
145 
146          long s1 = System.currentTimeMillis();
147          traditionalWay();
148          long e1 = System.currentTimeMillis();
149         
150          long s2 = System.currentTimeMillis();
151          ConnectionPoolWay();
152          long e2= System.currentTimeMillis();
153         
154          System.out.println("传统方式下,耗时"+(e1-s1)+" ms");
155          System.out.println("连接池方式下,耗时"+(e2-s2)+" ms");
156     }
157 }

效果图:

 

 

 

 练习3

测试数据库存取大文本数据:CLOB方式
测试数据库存取二进制数据:BLOB方式
  1 import java.io.File;
  2 import java.io.FileInputStream;
  3 import java.io.FileNotFoundException;
  4 import java.io.FileWriter;
  5 import java.io.IOException;
  6 import java.io.InputStream;
  7 import java.io.InputStreamReader;
  8 import java.io.Reader;
  9 import java.io.UnsupportedEncodingException;
 10 import java.sql.Connection;
 11 import java.sql.DriverManager;
 12 import java.sql.SQLException;
 13 
 14 import java.sql.PreparedStatement;
 15 import java.sql.ResultSet;
 16 
 17 public class JDBC_CLOB_Demo {
 18     // 连接字符串:数据库名:IP端口 定位数据库所在计算机的位置
 19     // 通过用户名密码 访问具体的数据库
 20     private static final String URL = "jdbc:oracle:thin:@localhost:1521:ORCL";
 21     private static final String USERNAME = "scott";
 22     private static final String PWD = "tiger";
 23 
 24 //    存放小说
 25     public static void demo() throws IOException {
 26         // 需要mynovel表:create table mynovel(id number primary key,novel clob);
 27         // 怎么创建CLOB对象?
 28         // 推荐使用setCharacterStream()
 29         PreparedStatement pstmt = null;
 30         try {
 31             Class.forName("oracle.jdbc.OracleDriver");
 32         } catch (ClassNotFoundException e) {
 33             // TODO Auto-generated catch block
 34             e.printStackTrace();
 35         }
 36 
 37         try (Connection connection = DriverManager.getConnection(URL, USERNAME, PWD);) {
 38             String sql = "insert into mynovel values(?,?)";
 39             pstmt = connection.prepareStatement(sql);
 40             pstmt.setInt(1, 1);
 41 
 42             // new InputReader()不推荐,不能设置编码
 43             // 推荐使用InputStreamReader(inputStream,编码)【转换流】,可以设置编码
 44 //            一句代码搞定
 45 //            pstmt.setCharacterStream(2,
 46 //                    new InputStreamReader(new FileInputStream("F:\\世界名著\\追忆似水年华_马赛尔·普鲁斯特_TXT小说天堂.txt"), "UTF-8"));
 47 //            拆分成多行代码便于分析
 48             File file = new File("F:\\世界名著\\追忆似水年华_马赛尔·普鲁斯特_TXT小说天堂.txt");
 49             InputStream in = new FileInputStream(file);
 50             Reader reader = new InputStreamReader(in, "UTF-8");
 51 //            设置file.length()是为了把整本小说都放进去,所以前面也要设置File对象,方便调用length()
 52 //            放入数据库中的是Reader对象,到时候读取时也是取出Reader对象
 53             pstmt.setCharacterStream(2, reader, file.length());
 54             // pstmt.setCharacterStream(2, reader, (int)file.length());有可能要转成int才不会报错
 55             
 56             int count = pstmt.executeUpdate();
 57             if (count > 0)
 58                 System.out.println("操作成功!");
 59 //            记得关闭流操作
 60             reader.close();
 61         } catch (SQLException e) {
 62             // TODO Auto-generated catch block
 63             e.printStackTrace();
 64         }
 65 
 66     }
 67 
 68 //    读取小说
 69     public static void readDemo() throws IOException {
 70         PreparedStatement pstmt = null;
 71         ResultSet rs = null;
 72         try {
 73             Class.forName("oracle.jdbc.OracleDriver");
 74         } catch (ClassNotFoundException e) {
 75             // TODO Auto-generated catch block
 76             e.printStackTrace();
 77         }
 78 
 79         try (Connection connection = DriverManager.getConnection(URL, USERNAME, PWD);) {
 80             String sql = "select novel from mynovel where id=?";
 81             pstmt = connection.prepareStatement(sql);
 82 //            取id=1的小说
 83             pstmt.setInt(1, 1);
 84 //            开始读取
 85             rs = pstmt.executeQuery();
 86 //            就查询 一本小说,不用while
 87             if (rs.next()) {
 88 //                从数据库取出小说,放在内存的reader对象中
 89                 Reader reader = rs.getCharacterStream("novel");
 90 //                reader与writer对应,用writer输出即可,这里输出到项目的src目录下
 91                 FileWriter writer = new FileWriter("src/小说.txt");
 92 
 93 //                设置缓冲区chs,形成:内存---缓冲区---硬盘的输出路径
 94                 char[] chs = new char[100];
 95                 int len = -1;
 96                 while ((len = reader.read(chs)) != -1) {
 97                     writer.write(chs,0, len);
 98                 }
 99                 writer.close();
100                 reader.close();
101             }
102         } catch (SQLException e) {
103             // TODO Auto-generated catch block
104             e.printStackTrace();
105         }
106     }
107 
108     public static void main(String[] args) throws IOException {
109 //        demo();
110         readDemo();
111     }
112 }

 

直接通过数据库是不能查看整本小说的~

 测试成功!

 

从数据库读取小说  测试成功!

 

  1 import java.io.File;
  2 import java.io.FileInputStream;
  3 import java.io.FileNotFoundException;
  4 import java.io.FileOutputStream;
  5 import java.io.FileWriter;
  6 import java.io.IOException;
  7 import java.io.InputStream;
  8 import java.io.InputStreamReader;
  9 import java.io.OutputStream;
 10 import java.io.OutputStreamWriter;
 11 import java.io.Reader;
 12 import java.io.UnsupportedEncodingException;
 13 import java.sql.Connection;
 14 import java.sql.DriverManager;
 15 import java.sql.SQLException;
 16 
 17 import java.sql.PreparedStatement;
 18 import java.sql.ResultSet;
 19 
 20 public class JDBC_BLOB_Demo {
 21     // 连接字符串:数据库名:IP端口 定位数据库所在计算机的位置
 22     // 通过用户名密码 访问具体的数据库
 23     private static final String URL = "jdbc:oracle:thin:@localhost:1521:ORCL";
 24     private static final String USERNAME = "scott";
 25     private static final String PWD = "tiger";
 26 
 27 //    在数据库中存放二进制类型
 28     public static void demo() throws IOException {
 29         PreparedStatement pstmt = null;
 30         try {
 31             Class.forName("oracle.jdbc.OracleDriver");
 32         } catch (ClassNotFoundException e) {
 33             // TODO Auto-generated catch block
 34             e.printStackTrace();
 35         }
 36 
 37         try (Connection connection = DriverManager.getConnection(URL, USERNAME, PWD);) {
 38             String sql = "insert into mymusic values(?,?)";
 39             pstmt = connection.prepareStatement(sql);
 40             pstmt.setInt(1, 1);
 41 
 42             File file = new File("C:\\Users\\Administrator\\Downloads\\Compressed\\Music\\滨崎步My All.mp3");
 43             InputStream in = new FileInputStream(file);
 44             pstmt.setBinaryStream(2, in, (int) file.length());
 45 
 46             int count = pstmt.executeUpdate();
 47             if (count > 0)
 48                 System.out.println("操作成功!");
 49 //            关闭流
 50             in.close();
 51         } catch (SQLException e) {
 52             // TODO Auto-generated catch block
 53             e.printStackTrace();
 54         }
 55 
 56     }
 57 
 58 //    读取数据库中的二进制数据
 59     public static void readDemo() throws IOException {
 60         PreparedStatement pstmt = null;
 61         ResultSet rs = null;
 62         try {
 63             Class.forName("oracle.jdbc.OracleDriver");
 64         } catch (ClassNotFoundException e) {
 65             // TODO Auto-generated catch block
 66             e.printStackTrace();
 67         }
 68 
 69         try (Connection connection = DriverManager.getConnection(URL, USERNAME, PWD);) {
 70             String sql = "select music from mymusic where id=?";
 71             pstmt = connection.prepareStatement(sql);
 72             pstmt.setInt(1, 1);
 73 
 74             rs = pstmt.executeQuery();
 75 
 76             if (rs.next()) {
 77                 
 78 //                读取数据库中的二进制数据,放在内存的InputStream对象
 79                 InputStream in = rs.getBinaryStream("music");
 80                 
 81                 OutputStream out = new FileOutputStream("src/music.mp3");
 82 
 83 //                设置缓冲区chs,形成:内存->in.read->缓冲区->out.write->硬盘
 84                 byte[] chs = new byte[100];
 85                 int len = -1;
 86                 while ((len = in.read(chs)) != -1) {
 87                     out.write(chs, 0, len);
 88                 }
 89                 out.close();
 90                 in.close();
 91             }
 92         } catch (SQLException e) {
 93             // TODO Auto-generated catch block
 94             e.printStackTrace();
 95         }
 96     }
 97 
 98     public static void main(String[] args) throws IOException {
 99 //        demo();
100         readDemo();
101     }
102 }

 

 

 测试成功!

 

 

 
 
 
 
 
 
 
posted @ 2020-01-29 15:36  细雨轻风  阅读(512)  评论(0编辑  收藏  举报