码迷,mamicode.com
首页 > 数据库 > 详细

JDBC学习小结

时间:2015-06-28 22:55:42      阅读:363      评论:0      收藏:0      [点我收藏+]

标签:

一、JDBC基础

连接数据的步骤:

1.注册驱动 :Class.forName(“com.mysql.jdbc.Driver”) 推荐这种方式,不会对具体的驱动类产生依赖;DriverManager.registerDriver(com.mysql.jdbc.Driver)
 会造成DriverManager中产生两个一样的驱动,并会对具体的驱动类产生依赖;System.setProperty(“jdbc.drivers”, “driver1:driver2”) 虽然不会对具体的驱动类产生依赖;但注册不太方便,所以很少使用。
2.建立连接(Connection) :Connection conn = DriverManager.getConnection(url, user, password);url格式: JDBC:子协议:子名称//主机名:端口/数据库名?属性名=属性值&...;User,password可以用“属性名=属性值”方式告诉数据库;其他参数如:useUnicode=true&characterEncoding=GBK。
3.创建执行SQL的语句(Statement):
4.执行语句
5.处理执行结果(ResultSet)
6.释放资源

1、注册数据库驱动的方式:

1)加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名;

技术分享
 1 @Test
 2 public void testDriverManager() throws Exception{
 3     //1. 准备连接数据库的 4 个字符串. 
 4     //驱动的全类名.
 5     String driverClass = "com.mysql.jdbc.Driver";
 6     //JDBC URL
 7     String jdbcUrl = "jdbc:mysql://localhost:3306/test";
 8     //user
 9     String user = "root";
10     //password
11     String password = "123456";
12         
13     //2. 加载数据库驱动程序(对应的 Driver 实现类中有注册驱动的静态代码块.)
14     Class.forName(driverClass);
15         
16     //3. 通过 DriverManager 的 getConnection() 方法获取数据库连接. 
17     Connection connection = 
18             DriverManager.getConnection(jdbcUrl, user, password);
19     System.out.println(connection); 
20         
21 }
View Code

2)Driver 是一个接口: 数据库厂商必须提供实现的接口. 能从其中获取数据库连接.可以通过 Driver 的实现类对象获取数据库连接.

技术分享
 1 @Test
 2 public void testDriver() throws SQLException {
 3     //1. 创建一个 Driver 实现类的对象
 4     Driver driver = new com.mysql.jdbc.Driver();
 5 
 6     //2. 准备连接数据库的基本信息: url, user, password
 7     String url = "jdbc:mysql://localhost:3306/test";
 8     Properties info = new Properties();
 9     info.put("user", "root");
10     info.put("password", "123456");
11         
12     //3. 调用 Driver 接口的 connect(url, info) 获取数据库连接
13     Connection connection = driver.connect(url, info);
14     System.out.println(connection);
15 }
View Code

2、获取数据库连接的方式:
1)DriverManager 是驱动的管理类:1). 可以通过重载的 getConnection() 方法获取数据库连接. 较为方便,2). 可以同时管理多个驱动程序: 若注册了多个数据库连接, 则调用 getConnection(),3)方法时传入的参数不同, 即返回不同的数据库连接。

例:Connection connection = DriverManager.getConnection(jdbcUrl, user, password);

2)Driver 是一个接口: 数据库厂商必须提供实现的接口. 能从其中获取数据库连接.可以通过 Driver 的实现类对象获取数据库连接.

例:Connection connection = driver.connect(url, info);

3.创建执行SQL的语句(statement、preparedstatement):

通过 JDBC 向指定的数据表中插入一条记录. 
  a. Statement: 用于执行 SQL 语句的对象
  1). 通过 Connection 的 createStatement() 方法来获取
  2). 通过 executeUpdate(sql) 可以执行 SQL 语句.
  3). 传入的 SQL 可以是 INSRET, UPDATE 或 DELETE. 但不能是 SELECT
 
  b. Connection、Statement 都是应用程序和数据库服务器的连接资源. 使用后一定要关闭.
   需要在 finally 中关闭 Connection 和 Statement 对象. 
   
  c. 关闭的顺序是: 先关闭后获取的. 即先关闭 Statement 后关闭 Connection

示例代码如下:

技术分享
 1 @Test
 2 public void testStatement() throws Exception{
 3     //1. 获取数据库连接
 4     Connection conn = null;
 5     Statement statement = null;
 6         
 7     try {
 8         conn = JDBCTools.getConnection();
 9         
10         //3. 准备插入的 SQL 语句
11         String sql = null;
12         
13                //sql = "INSERT INTO customers (NAME, EMAIL, BIRTH) " +
14                    //"VALUES(‘XYZ‘, ‘xyz@atguigu.com‘, ‘1990-12-12‘)";
15               //sql = "DELETE FROM customers WHERE id = 1";
16         sql = "UPDATE customers SET name = ‘TOM‘ " +
17                 "WHERE id = 4";
18         System.out.println(sql);
19             
20           //4. 执行插入. 
21           //1). 获取操作 SQL 语句的 Statement 对象: 
22          //调用 Connection 的 createStatement() 方法来获取
23           statement = conn.createStatement();
24             
25          //2). 调用 Statement 对象的 executeUpdate(sql) 执行 SQL 语句进行插入
26           statement.executeUpdate(sql);
27     } catch (Exception e) {
28         e.printStackTrace();
29     } finally{
30         JDBCTools.release(statement,conn);
31     }     
View Code

4.处理执行结果(ResultSet):
ResultSet: 结果集. 封装了使用 JDBC 进行查询的结果. 
   a. 调用 Statement 对象的 executeQuery(sql) 可以得到结果集.
   b. ResultSet 返回的实际上就是一张数据表. 有一个指针指向数据表的第一样的前面.可以调用 next() 方法检测下一行是否有效. 若有效该方法返回 true, 且指针下移. 相当于Iterator 对象的 hasNext() 和 next() 方法的结合体
   c. 当指针对位到一行时, 可以通过调用 getXxx(index) 或 getXxx(columnName),获取每一列的值. 例如: getInt(1), getString("name")
   d. ResultSet 当然也需要进行关闭.

示例代码如下:

技术分享
 1 @Test
 2 public void testResultSet(){
 3     //获取 id=4 的 customers 数据表的记录, 并打印
 4         
 5     Connection conn = null;
 6     Statement statement = null;
 7     ResultSet rs = null;
 8         
 9     try {
10         //1. 获取 Connection
11         conn = JDBCTools.getConnection();
12         System.out.println(conn);
13             
14         //2. 获取 Statement
15         statement = conn.createStatement();
16         System.out.println(statement);
17             
18         //3. 准备 SQL
19         String sql = "SELECT id, name, email, birth " +
20                     "FROM customers";
21             
22         //4. 执行查询, 得到 ResultSet
23         rs = statement.executeQuery(sql);
24         System.out.println(rs);
25             
26         //5. 处理 ResultSet
27         while(rs.next()){
28             int id = rs.getInt(1);
29             String name = rs.getString("name");
30             String email = rs.getString(3);
31             Date birth = rs.getDate(4);
32                 
33             System.out.println(id);
34             System.out.println(name);
35             System.out.println(email);
36             System.out.println(birth);
37         }
38             
39     } catch (Exception e) {
40         e.printStackTrace();
41     } finally{
42         //6. 关闭数据库资源. 
43         JDBCTools.release(rs, statement, conn);
44     }
45         
46 }
View Code

JDBC工具模板(JDBCTools)配置如下:

技术分享
 1 import java.io.InputStream;
 2 import java.sql.Connection;
 3 import java.sql.DriverManager;
 4 import java.sql.ResultSet;
 5 import java.sql.SQLException;
 6 import java.sql.Statement;
 7 import java.util.Properties;
 8 
 9 /**
10  * 操作 JDBC 的工具类. 其中封装了一些工具方法 Version 1
11  */
12 public class JDBCTools {
13 
14     public static void release(ResultSet rs, 
15             Statement statement, Connection conn) {
16         if(rs != null){
17             try {
18                 rs.close();
19             } catch (SQLException e) {
20                 e.printStackTrace();
21             }
22         }
23         
24         
25         if (statement != null) {
26             try {
27                 statement.close();
28             } catch (Exception e2) {
29                 e2.printStackTrace();
30             }
31         }
32 
33         if (conn != null) {
34             try {
35                 conn.close();
36             } catch (Exception e2) {
37                 e2.printStackTrace();
38             }
39         }
40     }
41     
42     /**
43      * 关闭 Statement 和 Connection
44      * @param statement
45      * @param conn
46      */
47     public static void release(Statement statement, Connection conn) {
48         if (statement != null) {
49             try {
50                 statement.close();
51             } catch (Exception e2) {
52                 e2.printStackTrace();
53             }
54         }
55 
56         if (conn != null) {
57             try {
58                 conn.close();
59             } catch (Exception e2) {
60                 e2.printStackTrace();
61             }
62         }
63     }
64 
65     /**
66      * 1. 获取连接的方法. 通过读取配置文件从数据库服务器获取一个连接.
67      * 
68      * @return
69      * @throws Exception
70      */
71     public static Connection getConnection() throws Exception {
72         // 1. 准备连接数据库的 4 个字符串.
73         // 1). 创建 Properties 对象
74         Properties properties = new Properties();
75 
76         // 2). 获取 jdbc.properties 对应的输入流
77         InputStream in = JDBCTools.class.getClassLoader().getResourceAsStream(
78                 "jdbc.properties");
79 
80         // 3). 加载 2) 对应的输入流
81         properties.load(in);
82 
83         // 4). 具体决定 user, password 等4 个字符串.
84         String user = properties.getProperty("user");
85         String password = properties.getProperty("password");
86         String jdbcUrl = properties.getProperty("jdbcUrl");
87         String driver = properties.getProperty("driver");
88 
89         // 2. 加载数据库驱动程序(对应的 Driver 实现类中有注册驱动的静态代码块.)
90         Class.forName(driver);
91 
92         // 3. 通过 DriverManager 的 getConnection() 方法获取数据库连接.
93         return DriverManager.getConnection(jdbcUrl, user, password);
94     }
95 
96 }
View Code

 

技术分享
1 driver=com.mysql.jdbc.Driver
2 jdbcUrl=jdbc:mysql://localhost:3306/test
3 user=root
4 password=123456
View Code

 

二、实现数据库增删改查

1.创立数据库表 examstudent;

技术分享
 1 /*
 2 Navicat MySQL Data Transfer
 3 
 4 Source Server         : localhost
 5 Source Server Version : 50524
 6 Source Host           : localhost:3306
 7 Source Database       : examstudent
 8 
 9 Target Server Type    : MYSQL
10 Target Server Version : 50524
11 File Encoding         : 65001
12 
13 Date: 2015-06-27 15:49:22
14 */
15 
16 SET FOREIGN_KEY_CHECKS=0;
17 
18 -- ----------------------------
19 -- Table structure for examstudent
20 -- ----------------------------
21 DROP TABLE IF EXISTS `examstudent`;
22 CREATE TABLE `examstudent` (
23   `flowid` int(11) NOT NULL,
24   `type` int(11) DEFAULT NULL,
25   `idcard` varchar(18) DEFAULT NULL,
26   `examcard` varchar(15) DEFAULT NULL,
27   `studentname` varchar(20) DEFAULT NULL,
28   `location` varchar(20) DEFAULT NULL,
29   `grade` int(11) DEFAULT NULL,
30   PRIMARY KEY (`flowid`)
31 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
View Code

2.向数据库中添加如下数据

技术分享

3. 在 eclipse 中建立 java 程序:输入身份证号或准考证号可以查询到学生的基本信息。

4.完成学生信息的删除功能

示例代码如下:

 jdbc.properties

技术分享
1 user=root
2 password=123456
3 driverClass=com.mysql.jdbc.Driver
4 url=jdbc:mysql://localhost:3306/examstudent
View Code

student.java

技术分享
  1 package com.atguigu.jdbc;
  2 
  3 public class Student {
  4 
  5     // 流水号
  6     private int flowId;
  7     // 考试的类型
  8     private int type;
  9     // 身份证号
 10     private String idCard;
 11     // 准考证号
 12     private String examCard;
 13     // 学生名
 14     private String studentName;
 15     // 学生地址
 16     private String location;
 17     // 考试分数.
 18     private int grade;
 19 
 20     public int getFlowId() {
 21         return flowId;
 22     }
 23 
 24     public void setFlowId(int flowId) {
 25         this.flowId = flowId;
 26     }
 27 
 28     public int getType() {
 29         return type;
 30     }
 31 
 32     public void setType(int type) {
 33         this.type = type;
 34     }
 35 
 36     public String getIdCard() {
 37         return idCard;
 38     }
 39 
 40     public void setIdCard(String idCard) {
 41         this.idCard = idCard;
 42     }
 43 
 44     public String getExamCard() {
 45         return examCard;
 46     }
 47 
 48     public void setExamCard(String examCard) {
 49         this.examCard = examCard;
 50     }
 51 
 52     public String getStudentName() {
 53         return studentName;
 54     }
 55 
 56     public void setStudentName(String studentName) {
 57         this.studentName = studentName;
 58     }
 59 
 60     public String getLocation() {
 61         return location;
 62     }
 63 
 64     public void setLocation(String location) {
 65         this.location = location;
 66     }
 67 
 68     public int getGrade() {
 69         return grade;
 70     }
 71 
 72     public void setGrade(int grade) {
 73         this.grade = grade;
 74     }
 75 
 76     public Student(int flowId, int type, String idCard, String examCard,
 77             String studentName, String location, int grade) {
 78         super();
 79         this.flowId = flowId;
 80         this.type = type;
 81         this.idCard = idCard;
 82         this.examCard = examCard;
 83         this.studentName = studentName;
 84         this.location = location;
 85         this.grade = grade;
 86     }
 87 
 88     public Student() {
 89         // TODO Auto-generated constructor stub
 90     }
 91 
 92     @Override
 93     public String toString() {
 94         return "Student [flowId=" + flowId + ", type=" + type + ", idCard="
 95                 + idCard + ", examCard=" + examCard + ", studentName="
 96                 + studentName + ", location=" + location + ", grade=" + grade
 97                 + "]";
 98     }
 99 
100 }
View Code

JDBCTools.java

技术分享
  1 package cky.test;
  2 
  3 import java.io.IOException;
  4 import java.io.InputStream;
  5 import java.sql.Connection;
  6 import java.sql.DriverManager;
  7 import java.sql.PreparedStatement;
  8 import java.sql.ResultSet;
  9 import java.sql.SQLException;
 10 import java.sql.Statement;
 11 import java.util.Properties;
 12 
 13 public class JDBCTools {
 14 
 15     /**
 16      * 执行 SQL 语句, 使用 PreparedStatement
 17      * @param sql
 18      * @param args: 填写 SQL 占位符的可变参数
 19      */
 20     public static void update(String sql, Object ... args){
 21         Connection connection = null;
 22         PreparedStatement preparedStatement = null;
 23         
 24         try {
 25             connection = JDBCTools.getConnection();
 26             preparedStatement = connection.prepareStatement(sql);
 27             
 28             for(int i = 0; i < args.length; i++){
 29                 preparedStatement.setObject(i + 1, args[i]);
 30             }
 31             
 32             preparedStatement.executeUpdate();
 33             
 34         } catch (Exception e) {
 35             e.printStackTrace();
 36         } finally{
 37             JDBCTools.releaseDB(null, preparedStatement, connection);
 38         }
 39     }
 40     
 41     /**
 42      * 执行 SQL 的方法
 43      * 
 44      * @param sql: insert, update 或 delete。 而不包含 select
 45      */
 46     public static void update(String sql) {
 47         Connection connection = null;
 48         Statement statement = null;
 49 
 50         try {
 51             // 1. 获取数据库连接
 52             connection = getConnection();
 53 
 54             // 2. 调用 Connection 对象的 createStatement() 方法获取 Statement 对象
 55             statement = connection.createStatement();
 56 
 57             // 4. 发送 SQL 语句: 调用 Statement 对象的 executeUpdate(sql) 方法
 58             statement.executeUpdate(sql);
 59 
 60         } catch (Exception e) {
 61             e.printStackTrace();
 62         } finally {
 63             // 5. 关闭数据库资源: 由里向外关闭.
 64             releaseDB(null, statement, connection);
 65         }
 66     }
 67 
 68     /**
 69      * 释放数据库资源的方法
 70      * 
 71      * @param resultSet
 72      * @param statement
 73      * @param connection
 74      */
 75     public static void releaseDB(ResultSet resultSet, Statement statement,
 76             Connection connection) {
 77 
 78         if (resultSet != null) {
 79             try {
 80                 resultSet.close();
 81             } catch (SQLException e) {
 82                 e.printStackTrace();
 83             }
 84         }
 85 
 86         if (statement != null) {
 87             try {
 88                 statement.close();
 89             } catch (SQLException e) {
 90                 e.printStackTrace();
 91             }
 92         }
 93 
 94         if (connection != null) {
 95             try {
 96                 connection.close();
 97             } catch (SQLException e) {
 98                 e.printStackTrace();
 99             }
100         }
101 
102     }
103 
104     /**
105      * 获取数据库连接的方法
106      */
107     public static Connection getConnection() throws IOException,
108             ClassNotFoundException, SQLException {
109         // 0. 读取 jdbc.properties
110         /**
111          * 1). 属性文件对应 Java 中的 Properties 类 2). 可以使用类加载器加载 bin 目录(类路径下)的文件
112          */
113         Properties properties = new Properties();
114         InputStream inStream = JDBCTools.class.getClassLoader()
115                 .getResourceAsStream("jdbc.properties");
116         properties.load(inStream);
117 
118         // 1. 准备获取连接的 4 个字符串: user, password, jdbcUrl, driverClass
119         String user = properties.getProperty("user");
120         String password = properties.getProperty("password");
121         String jdbcUrl = properties.getProperty("url");
122         String driverClass = properties.getProperty("driverClass");
123 
124         // 2. 加载驱动: Class.forName(driverClass)
125         Class.forName(driverClass);
126 
127         // 3. 调用
128         // DriverManager.getConnection(jdbcUrl, user, password)
129         // 获取数据库连接
130         Connection connection = DriverManager.getConnection(jdbcUrl, user,
131                 password);
132         return connection;
133     }
134 
135 }
View Code

JDBCTest.java

技术分享
  1 package cky.test;
  2 
  3 import java.sql.Connection;
  4 
  5 import java.sql.PreparedStatement;
  6 import java.sql.ResultSet;
  7 
  8 import java.util.Scanner;
  9 
 10 import org.junit.Test;
 11 
 12 public class JDBCTest {
 13 
 14     //得到学生的信息集
 15     public Student getStudent(String sql, Object... args) {
 16         Student stu = null;
 17 
 18         Connection connection = null;
 19         PreparedStatement preparedStatement = null;
 20         ResultSet resultSet = null;
 21 
 22         try {
 23             connection = JDBCTools.getConnection();
 24             preparedStatement = connection.prepareStatement(sql);
 25             for (int i = 0; i < args.length; i++) {
 26                 preparedStatement.setObject(i + 1, args[i]);
 27             }
 28             resultSet = preparedStatement.executeQuery();
 29 
 30             if (resultSet.next()) {
 31                 stu = new Student();
 32                 stu.setFlowId(resultSet.getInt(1));
 33                 stu.setType(resultSet.getInt(2));
 34                 stu.setIdCard(resultSet.getString(3));
 35                 
 36             }
 37 
 38         } catch (Exception e) {
 39             e.printStackTrace();
 40         } finally {
 41             JDBCTools.releaseDB(resultSet, preparedStatement, connection);
 42         }
 43 
 44         return stu;
 45     }
 46 
 47 
 48     /*
 49     private Student getStudent(String sql) {
 50 
 51         Student stu = null;
 52 
 53         Connection connection = null;
 54         Statement statement = null;
 55         ResultSet resultSet = null;
 56 
 57         try {
 58             connection = JDBCTools.getConnection();
 59             statement = connection.createStatement();
 60             resultSet = statement.executeQuery(sql);
 61 
 62             if (resultSet.next()) {
 63                 stu = new Student(resultSet.getInt(1), resultSet.getInt(2),
 64                         resultSet.getString(3), resultSet.getString(4),
 65                         resultSet.getString(5), resultSet.getString(6),
 66                         resultSet.getInt(7));
 67             }
 68 
 69         } catch (Exception e) {
 70             e.printStackTrace();
 71         } finally {
 72             JDBCTools.releaseDB(resultSet, statement, connection);
 73         }
 74 
 75         return stu;
 76     }
 77     */
 78     
 79     //打印学生信息: 若学生存在则打印其具体信息. 若不存在: 打印查无此人
 80     private void printStudent(Student student) {
 81         if (student != null) {
 82             System.out.println(student);
 83         } else {
 84             System.out.println("查无此人!");
 85         }
 86     }
 87     
 88     // 从控制台读入一个整数, 确定要查询的类型; @return: 1. 用身份证查询. 2. 用准考证号查询 其他的无效. 并提示请用户重新输入.
 89     private int getSearchTypeFromConsole() {
 90 
 91         System.out.print("请输入查询类型: 1. 用身份证查询. 2. 用准考证号查询 ");
 92 
 93         Scanner scanner = new Scanner(System.in);
 94         int type = scanner.nextInt();
 95 
 96         if (type != 1 && type != 2) {
 97             System.out.println("输入有误请重新输入!");
 98             throw new RuntimeException();
 99         }
100 
101         return type;
102     }
103 
104     //从控制台输入学生的信息
105     private Student getStudentFromConsole() {
106 
107         Scanner scanner = new Scanner(System.in);
108 
109         Student student = new Student();
110 
111         System.out.print("FlowId:");
112         student.setFlowId(scanner.nextInt());
113 
114         System.out.print("Type: ");
115         student.setType(scanner.nextInt());
116 
117         System.out.print("IdCard:");
118         student.setIdCard(scanner.next());
119 
120         System.out.print("ExamCard:");
121         student.setExamCard(scanner.next());
122 
123         System.out.print("StudentName:");
124         student.setStudentName(scanner.next());
125 
126         System.out.print("Location:");
127         student.setLocation(scanner.next());
128 
129         System.out.print("Grade:");
130         student.setGrade(scanner.nextInt());
131 
132         return student;
133     }
134     
135     public void addNewStudent2(Student student) {
136         String sql = "INSERT INTO examstudent(flowid, type, idcard, "
137                 + "examcard, studentname, location, grade) "
138                 + "VALUES(?,?,?,?,?,?,?)";
139 
140         JDBCTools.update(sql, student.getFlowId(), student.getType(),
141                 student.getIdCard(), student.getExamCard(),
142                 student.getStudentName(), student.getLocation(),
143                 student.getGrade());
144     }
145 
146     /*
147     public void addNewStudent(Student student) {
148         // 1. 准备一条 SQL 语句:
149         String sql = "INSERT INTO examstudent VALUES(" + student.getFlowId()
150                 + "," + student.getType() + ",‘" + student.getIdCard() + "‘,‘"
151                 + student.getExamCard() + "‘,‘" + student.getStudentName()
152                 + "‘,‘" + student.getLocation() + "‘," + student.getGrade()
153                 + ")";
154 
155         System.out.println(sql);
156 
157         // 2. 调用 JDBCTools 类的 update(sql) 方法执行插入操作.
158         JDBCTools.update(sql);
159     }
160     */
161     
162     //具体查询学生信息的. 返回一个 Student 对象. 若不存在, 则返回 null
163     private Student searchStudent(int searchType) {
164         
165         String sql = "SELECT flowid, type, idcard, examcard,"
166                 + "studentname, location, grade " + "FROM examstudent "
167                 + "WHERE ";
168 
169         Scanner scanner = new Scanner(System.in);
170 
171         // 1. 根据输入的 searchType, 提示用户输入信息:
172         // 1.1 若 searchType 为 1, 提示: 请输入身份证号. 若为 2 提示: 请输入准考证号
173         // 2. 根据 searchType 确定 SQL
174         if (searchType == 1) {
175             System.out.print("请输入准考证号:");
176             String examCard = scanner.next();
177             sql = sql + "examcard = ‘" + examCard + "‘";
178         } else {
179             System.out.print("请输入身份证号:");
180             String examCard = scanner.next();
181             sql = sql + "idcard = ‘" + examCard + "‘";
182         }
183 
184         // 3. 执行查询
185         Student student = getStudent(sql);
186 
187         // 4. 若存在查询结果, 把查询结果封装为一个 Student 对象
188 
189         return student;
190     }
191 
192     
193     //测试打印查询到的学生信息
194     @Test
195     public void testGetStudent() {
196         // 1. 得到查询的类型
197         int searchType = getSearchTypeFromConsole();
198 
199         // 2. 具体查询学生信息
200         Student student = searchStudent(searchType);
201 
202         // 3. 打印学生信息
203         printStudent(student);
204     }
205     
206     
207     @Test
208     public void testAddNewStudent() {
209         Student student = getStudentFromConsole();
210         addNewStudent2(student);
211     }
212 
213 }
View Code

 

三、Statement 与 ResultSet
1.通过调用 Connection 对象的 createStatement 方法创建该对象
? Statement st = conn.createStatement();
2.该对象用于执行静态的 SQL 语句,并且返回执行结果
3.Statement 接口中定义了下列方法用于执行 SQL 语句:
? ResultSet excuteQuery(String sql)
? int excuteUpdate(String sql)

通用的INSERT、UPDATA、DELETE方法

技术分享
 1 //通用的 INSSERT UPDATE DELETE 方法(version 1.0)
 2 public void update(String sql){
 3     //1.获取数据库的连接
 4     Connection conn = null;
 5     Statement st = null;
 6     try{
 7         conn = JDBCUtils.getConnection();
 8         //2.提供一个 Statement 对象,将 sql 传递给数据库中执行
 9         st = conn.createStatement();
10         st.execute(sql);
11     }catch(Exception e){
12         e.printStackTrace();
13     }finally{
14         //3.关闭 Statement 对象及连接
15         JDBCUtils.close(null, st, conn);
16     } 
17 }
View Code

通用的查询方法,返回一个对象

技术分享
 1 public <T> T get(String sql, Class<T> clazz) {
 2     Connection conn = null;
 3     Statement st = null;
 4     ResultSet rs = null;
 5     T t = null;
 6     try {
 7         t = clazz.newInstance();
 8         conn = JDBCUtils.getConnection();
 9         st = conn.createStatement();
10         rs = st.executeQuery(sql);
11         /*
12         * 通过 ResultSet 调用 getMetaData()返回一个结果集的元数据:ResultSetMetaData
13         *
14         * 1.getColumnCount():返回结果集的列数
15         * 2.getColumnLabel():返回列的别名
16         */
17         ResultSetMetaData rsmd = rs.getMetaData();
18         int columnCount = rsmd.getColumnCount();
19         if (rs.next()) {
20             for (int i = 0; i < columnCount; i++) {
21                 Object columnVal = rs.getObject(i + 1);// 相应列的值
22                 //String columnName = rsmd.getColumnName(i + 1);
23                 String columnName = rsmd.getColumnLabel(i + 1);
24                 //使用 PropertyUtils 将指定对象 t 的指定属性 columnName 设置为指定的值 columnVal
25                 PropertyUtils.setProperty(t, columnName, columnVal);
26             } 
27         }
28     } catch (Exception e) {
29         e.printStackTrace();
30     } finally {
31         JDBCUtils.close(rs, st, conn);
32     }
33     return t;
34 }
View Code

//通用的返回多个对象的查询操作

技术分享
 1 public <T> List<T> getInstances(String sql,Class<T> clazz){
 2     Connection conn = null;
 3     Statement st = null;
 4     ResultSet rs = null;
 5     List<T> list = new ArrayList<T>();
 6     try {
 7         conn = JDBCUtils.getConnection();
 8         st = conn.createStatement();
 9         rs = st.executeQuery(sql);
10         /*
11         * 通过 ResultSet 调用 getMetaData()返回一个结果集的元数据:ResultSetMetaData
12         *
13         * 1.getColumnCount():返回结果集的列数
14         * 2.getColumnLabel():返回列的别名
15         */
16         ResultSetMetaData rsmd = rs.getMetaData();
17         int columnCount = rsmd.getColumnCount();
18         while (rs.next()) {
19             T t = clazz.newInstance();
20             for (int i = 0; i < columnCount; i++) {
21                 Object columnVal = rs.getObject(i + 1);// 相应列的值
22                 //String columnName = rsmd.getColumnName(i + 1);
23                 String columnName = rsmd.getColumnLabel(i + 1);
24                 //使用 PropertyUtils 将指定对象 t 的指定属性 columnName 设置为指定的值 columnVal
25                 PropertyUtils.setProperty(t, columnName, columnVal);
26             }
27             list.add(t);
28         }
29     } catch (Exception e) {
30         e.printStackTrace();
31     } finally {
32         JDBCUtils.close(rs, st, conn);
33     }
34     return list;
35 }
View Code

或者采用这个方法(个人比较喜欢)

技术分享
 1 public List<Map<String, Object>> read(String sql) throws SQLException {
 2         Connection conn = null;
 3         PreparedStatement ps = null;
 4         ResultSet rs = null;
 5         try {
 6             conn = JdbcUtils.getConnection();
 7             ps = conn.prepareStatement(sql);
 8             rs = ps.executeQuery();
 9             ResultSetMetaData rsmd = rs.getMetaData();
10             int count = rsmd.getColumnCount();
11             String[] colNames = new String[count];
12             System.out.println(count);
13             for (int i = 1; i <= count; i++) {
14                 //Object val = rs.getObject(i);
15                 //System.out.println(val);
16                 //System.out.print(rsmd.getColumnClassName(i) + "\t");
17                 //System.out.print(rsmd.getColumnName(i) + "\t");
18                 //System.out.println(rsmd.getColumnLabel(i));
19                 colNames[i - 1] = rsmd.getColumnLabel(i);
20             }
21             List<Map<String, Object>> datas = new ArrayList<Map<String, Object>>();
22 
23             while (rs.next()) {
24                 Map<String, Object> data = new HashMap<String, Object>();
25                 for (int i = 0; i < colNames.length; i++) {
26                     data.put(colNames[i], rs.getObject(colNames[i]));
27                 }
28                 datas.add(data);
29             }
30             return datas;
31         } finally {
32             JdbcUtils.free(rs, ps, conn);
33         }
34     }
View Code

 

两种思想:
1.面向接口编程的思想;
2.ORM 思想:ORM:Object Relational Mapping
数据库中的表与 java 中的一个类对应(如: customers 表与 Customer 类对应);数据库中表的一个列与 java 类的一个属性对应(如:表中的 id 列与 Customer类的 id 属性对应);数据库中表的一行(一条数据)与 java 类的一个对象对应

技术分享
  1 package cn.itcast.jdbc;
  2 
  3 import java.lang.reflect.InvocationTargetException;
  4 import java.lang.reflect.Method;
  5 import java.sql.Connection;
  6 import java.sql.PreparedStatement;
  7 import java.sql.ResultSet;
  8 import java.sql.ResultSetMetaData;
  9 import java.sql.SQLException;
 10 import java.util.ArrayList;
 11 import java.util.HashMap;
 12 import java.util.List;
 13 import java.util.Map;
 14 
 15 import cn.itcast.jdbc.domain.User;
 16 
 17 /**
 18  * 
 19  * 2008-12-7
 20  * 
 21  * @author <a href="mailto:liyongibm@gmail.com">liyong</a>
 22  * 
 23  */
 24 public class ORMTest {
 25 
 26     /**
 27      * @param args
 28      * @throws Exception
 29      * @throws InvocationTargetException
 30      * @throws IllegalAccessException
 31      * @throws SQLException
 32      */
 33     public static void main(String[] args) throws SQLException,
 34             IllegalAccessException, InvocationTargetException, Exception {
 35         User user = (User) getObject(
 36                 "select id as Id, name as Name, birthday as Birthday, money as Money  from user where id=1",
 37                 User.class);
 38         System.out.println(user);
 39 
 40         Bean b = (Bean) getObject(
 41                 "select id as Id, name as Name, birthday as Birthday, money as Money from user where id=1",
 42                 Bean.class);
 43         System.out.println(b);
 44     }
 45 
 46     static List<Object> getObjects(String sql, Class clazz)
 47             throws SQLException, Exception, IllegalAccessException,
 48             InvocationTargetException {
 49         Connection conn = null;
 50         PreparedStatement ps = null;
 51         ResultSet rs = null;
 52         try {
 53             conn = JdbcUtils.getConnection();
 54             ps = conn.prepareStatement(sql);
 55             rs = ps.executeQuery();
 56             String[] colNames = getColNames(rs);
 57 
 58             List<Object> objects = new ArrayList<Object>();
 59             Method[] ms = clazz.getMethods();
 60             while (rs.next()) {
 61                 Object object = clazz.newInstance();
 62                 for (int i = 0; i < colNames.length; i++) {
 63                     String colName = colNames[i];
 64                     String methodName = "set" + colName;
 65                     // Object value = rs.getObject(colName);
 66                     // try {
 67                     // Method m = clazz
 68                     // .getMethod(methodName, value.getClass());
 69                     // if (m != null)
 70                     // m.invoke(object, value);
 71                     // } catch (NoSuchMethodException e) {
 72                     // e.printStackTrace();
 73                     // //
 74                     // }
 75                     for (Method m : ms) {
 76                         if (methodName.equals(m.getName())) {
 77                             m.invoke(object, rs.getObject(colName));
 78                             break;
 79                         }
 80                     }
 81                     objects.add(object);
 82                 }
 83             }
 84             return objects;
 85         } finally {
 86             JdbcUtils.free(rs, ps, conn);
 87         }
 88     }
 89 
 90     private static String[] getColNames(ResultSet rs) throws SQLException {
 91         ResultSetMetaData rsmd = rs.getMetaData();
 92         int count = rsmd.getColumnCount();
 93         String[] colNames = new String[count];
 94         for (int i = 1; i <= count; i++) {
 95             colNames[i - 1] = rsmd.getColumnLabel(i);
 96         }
 97         return colNames;
 98     }
 99 
100     static Object getObject(String sql, Class clazz) throws SQLException,
101             Exception, IllegalAccessException, InvocationTargetException {
102         Connection conn = null;
103         PreparedStatement ps = null;
104         ResultSet rs = null;
105         try {
106             conn = JdbcUtils.getConnection();
107             ps = conn.prepareStatement(sql);
108             rs = ps.executeQuery();
109             String[] colNames = getColNames(rs);
110 
111             Object object = null;
112             Method[] ms = clazz.getMethods();
113             if (rs.next()) {
114                 object = clazz.newInstance();
115                 for (int i = 0; i < colNames.length; i++) {
116                     String colName = colNames[i];
117                     String methodName = "set" + colName;
118                     // Object value = rs.getObject(colName);
119                     // try {
120                     // Method m = clazz
121                     // .getMethod(methodName, value.getClass());
122                     // if (m != null)
123                     // m.invoke(object, value);
124                     // } catch (NoSuchMethodException e) {
125                     // e.printStackTrace();
126                     // //
127                     // }
128                     for (Method m : ms) {
129                         if (methodName.equals(m.getName())) {
130                             m.invoke(object, rs.getObject(colName));
131                             break;
132                         }
133                     }
134                 }
135             }
136             return object;
137         } finally {
138             JdbcUtils.free(rs, ps, conn);
139         }
140     }
141 }
View Code


两个技术:

1.结果集的元数据: ResultSetMetaData

可用于获取关于 ResultSet 对象中列的类型和属性信息的对象:
  —getColumnName(int column):获取指定列的名称
  —getColumnCount():返回当前 ResultSet 对象中的列数。
  —getColumnTypeName(int column):检索指定列的数据库特定的类型名称。
  —getColumnDisplaySize(int column):指示指定列的最大标准宽度,以字符为单位。   
  —isNullable(int column):指示指定列中的值是否可以为 null。
  —isAutoIncrement(int column):指示是否自动为指定列进行编号,这样这些列仍然是只读的。

技术分享
 1 public void testResultSetMetaData(){
 2     Connection conn = null;
 3     Statement st = null;
 4     ResultSet rs = null;
 5     String sql = "select order_id id,order_name name,order_date date from `order`";
 6     try{
 7         conn = JDBCUtils.getConnection();
 8         st = conn.createStatement();
 9         rs = st.executeQuery(sql);
10         ResultSetMetaData rsmd = rs.getMetaData();
11         int columnCount = rsmd.getColumnCount();
12         System.out.println(columnCount);
13         while(rs.next()){
14             for(int i = 0;i < columnCount;i++){
15                 System.out.print(rsmd.getColumnName(i + 1) + " ");
16                 System.out.print(rsmd.getColumnLabel(i + 1) + " ");
17                 System.out.println(rs.getObject(i + 1));
18             }
19             System.out.println();
20         }
21     }catch(Exception e){
22         e.printStackTrace();
23     }finally{
24         JDBCUtils.close(rs, st, conn);
25     } 
26 }
View Code

2.PropertyUtils:使用它的 setProperty(Object obj,String FieldName,Object FieldValue)

技术分享
1 public void testPropertyUtils() throws Exception{
2     Order order = new Order();
3     System.out.println(order);
4     PropertyUtils.setProperty(order, "id", 1001);
5     PropertyUtils.setProperty(order, "name", "AA");
6     PropertyUtils.setProperty(order, "date", new Date(new java.util.Date().getTime()));
7     System.out.println(order);
8 }
View Code


四、PreparedStatement

PreparedStatement 是 Statement 的子接口

a.需要预编译 SQL 语句: PreparedStatement ps = conn.preparedStatement(sql);
b.填充占位符: setObject(int index);//index 从 1 开始
c.execute() / executeUpdate() ; executeQuery(); 返回一个 ResultSet

1.替换原来的 Statement,实现增删改和查的操作
-->Statement 的问题:①拼串 不方便,容易出错 ②存在 sql 注入的问题,可以对数据库进行恶意攻击。

// 实现一个通用的 UPDATE INSERT DELETE 的操作的方法

技术分享
 1 public void update(String sql, Object... args) {
 2     Connection conn = null;
 3     PreparedStatement ps = null;
 4     try {
 5         // 1.获取连接
 6         conn = JDBCUtils.getConnection();
 7         // 2.返回 PreparedSt 对象,预编译 sql 语句
 8         ps = conn.prepareStatement(sql);
 9         // 3.填充占位符
10         for (int i = 0; i < args.length; i++) {
11             ps.setObject(i + 1, args[i]);
12         }
13         ps.execute();
14     } catch (Exception e) {
15         e.printStackTrace();
16     } finally {
17         JDBCUtils.close(null, ps, conn);
18     } 
19 }
View Code

// 实现一个通用的查询操作,返回一个对象

技术分享
 1 public <T> T getInstance(String sql, Class<T> clazz, Object... args) {
 2     Connection conn = null;
 3     PreparedStatement ps = null;
 4     ResultSet rs = null;
 5     try {
 6         // 1.获取连接
 7         conn = JDBCUtils.getConnection();
 8         // 2.预编译 sql 语句,返回 PreparedStatement 对象
 9         ps = conn.prepareStatement(sql);
10         // 3.填充占位符
11         for (int i = 0; i < args.length; i++) {
12             ps.setObject(i + 1, args[i]);
13         }
14         // 4.执行并返回 ResultSet 的对象
15         rs = ps.executeQuery();
16         if (rs.next()) {
17             // 5.创建 T 的对象
18             T t = clazz.newInstance();
19             // 6.将结果集中的列值作为 T 的对象的属性,给予赋值
20             ResultSetMetaData rsmd = rs.getMetaData();
21             int columnCount = rsmd.getColumnCount();
22             for (int i = 0; i < columnCount; i++) {
23                 Object columnVal = rs.getObject(i + 1);
24                 String columnLabel = rsmd.getColumnLabel(i + 1);
25                 PropertyUtils.setProperty(t, columnLabel, columnVal);
26             }
27             return t;
28         }
29     } catch (Exception e) {
30         e.printStackTrace();
31     } finally {
32         // 7.关闭相应的操作
33         JDBCUtils.close(rs, ps, conn);
34     }
35     return null;
36 }
View Code

// 实现一个通用的查询操作,返回一个对象的集合

技术分享
 1 public <T> List<T> getForList(String sql,Class<T> clazz,Object ... args){
 2     Connection conn = null;
 3     PreparedStatement ps = null;
 4     ResultSet rs = null;
 5     List<T> list = new ArrayList<T>();
 6     try{
 7         conn = JDBCUtils.getConnection();
 8         ps = conn.prepareStatement(sql);
 9         for(int i = 0;i < args.length;i++){
10             ps.setObject(i + 1, args[i]);
11         }
12         rs = ps.executeQuery();
13         ResultSetMetaData rsmd = rs.getMetaData();
14         int columnCount = rsmd.getColumnCount();
15         while(rs.next()){
16             T t = clazz.newInstance();
17             for(int i = 0;i < columnCount;i++){
18                 Object columnVal = rs.getObject(i + 1);
19                 String columnLabel = rsmd.getColumnLabel(i + 1);
20                 PropertyUtils.setProperty(t, columnLabel, columnVal);
21             }
22             list.add(t);
23         }
24     }catch(Exception e){
25         e.printStackTrace();
26     }finally{
27         JDBCUtils.close(rs, ps, conn);
28     }
29     return list;
30 }
View Code

2.使用 PreparedStatement 的其他优点
-->1.实现大数据类型的数据的插入、修改、查询的操作.
setBlob() getBlob();

// 从数据表中将大数据类型的数据取出

技术分享
 1 @Test
 2 public void testBlob3(){
 3     Connection conn = null;
 4     PreparedStatement ps = null;
 5     String sql = "select id,name,email,birth,photo from customers where id = ?";
 6     ResultSet rs = null;
 7     InputStream is = null;
 8     FileOutputStream fos = null;
 9     try{
10         conn = JDBCUtils.getConnection();
11         ps = conn.prepareStatement(sql);
12         fos = new FileOutputStream("ym1.jpg");
13         ps.setInt(1, 21);
14         rs = ps.executeQuery();
15         if(rs.next()){
16             int id = rs.getInt("id");
17             String name = rs.getString("name");
18             Date birth = rs.getDate("birth");
19             String email = rs.getString("email");
20             Customer cust = new Customer(id,name,email,birth);
21             System.out.println(cust);
22         }
23         Blob photo = rs.getBlob(5);//获取此 ResultSet 对象的当前行中指定列的值
24         is = photo.getBinaryStream();//获取用于写入此 Blob 对象表示的 BLOB 值的流,输入流
25 
26         byte[] b = new byte[1024];
27         int len;
28         while((len = is.read(b)) != -1){
29             fos.write(b, 0, len);//文件输出流,保存大数据文件到ym1.jpg中。
30         }
31     }catch (Exception e) {
32         e.printStackTrace();
33     } finally {
34         JDBCUtils.close(rs, ps, conn);
35         if(fos != null){
36             try {
37                 fos.close();
38             } catch (IOException e) {
39                 // TODO Auto-generated catch block
40                 e.printStackTrace();
41             }
42         }
43         if(is != null){
44             try {
45                 is.close();
46             } catch (IOException e) {
47                 // TODO Auto-generated catch block
48                 e.printStackTrace();
49             } 
50         }
51     } 
52 }
View Code

// 向数据表中修改现有的大数据类型的数据

技术分享
 1 @Test
 2 public void testBlob2() {
 3     Connection conn = null;
 4     PreparedStatement ps = null;
 5     String sql = "update customers set photo = ? where id = ?";
 6     try {
 7         conn = JDBCUtils.getConnection();
 8         ps = conn.prepareStatement(sql);
 9         ps.setBlob(1, new FileInputStream("ym.jpg"));
10         ps.setInt(2, 21);
11         ps.execute();
12     } catch (Exception e) {
13         e.printStackTrace();
14     } finally {
15         JDBCUtils.close(null, ps, conn);
16     } 
17 }
View Code

// 向数据库的表中写入大数据类型的数据

技术分享
 1 @Test
 2 public void testBlob1() {
 3     Connection conn = null;
 4     PreparedStatement ps = null;
 5     String sql = "insert into customers(name,email,birth,photo)values(?,?,?,?)";
 6     try {
 7         conn = JDBCUtils.getConnection();
 8         ps = conn.prepareStatement(sql);
 9         ps.setString(1, "杨幂 1");
10         ps.setString(2, "yang@126.com");
11         ps.setDate(3, new Date(new java.util.Date().getTime()));
12         ps.setBlob(4, new FileInputStream("1.jpg"));
13         ps.execute();
14     } catch (Exception e) {
15         e.printStackTrace();
16     } finally {
17         JDBCUtils.close(null, ps, conn);
18     }
19 }
View Code

-->2.使用 PreparedStatement 进行批量操作时,效率优于 Statement.
oracle 是支持批量插入的。
如何实现最优? ①使用 PreparedStatement ②addBatch() executeBatch() clearBatch()
//批量操作,主要指的是批量插入

技术分享
 1 public void test4() {
 2     Connection conn = null;
 3     PreparedStatement ps = null;
 4     long start = System.currentTimeMillis();
 5     String sql = "insert into dept values(?,?)";
 6     try {
 7         conn = JDBCUtils.getConnection();
 8         ps = conn.prepareStatement(sql);
 9         for (int i = 0; i < 100000; i++) {
10             ps.setInt(1, i + 1);
11             ps.setString(2, "dept_" + (i + 1) + "_name");
12             //1.“攒” SQL
13             ps.addBatch();
14             if( (i + 1) % 250 == 0){
15                 //2.执行 sql
16                 ps.executeBatch();
17                 //3.清空 sql
18                 ps.clearBatch();
19             }     
20         }
21     } catch (Exception e) {
22         e.printStackTrace();
23     } finally {
24         JDBCUtils.close(null, ps, conn);
25     }
26     long end = System.currentTimeMillis();
27     System.out.println("花费时间: " + (end - start));//2427
28 }
View Code

 

五、数据库的元数据: DataBaseMetaData(了解)
“元”数据: String name = "AA";
ResutSet :结果集
ResultSetMetaData:结果集的元数据


DatabaseMetaData:数据库的元数据

技术分享
public class TestDataBaseMetaData {
    public static void main(String[] args) {
        Connection conn = null;
        DatabaseMetaData dbmd = null;
        ResultSet rs = null;
        try{
            conn = JDBCUtils.getConnection();
            //获取数据库的元数据
            dbmd = conn.getMetaData();
            //以字符串的形式返回数据库的名字
            System.out.println(dbmd.getDatabaseProductName());
            //返回数据库的版本号
            System.out.println(dbmd.getDatabaseProductVersion());
            rs = dbmd.getCatalogs();
            //返回含有的各个数据库的名字
            while(rs.next()){
                String databaseName = rs.getString(1);
                System.out.println(databaseName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JDBCUtils.close(rs, null, conn);
        }
    }
}
View Code

 

六、数据库事务(重点)
1.事务:指构成单个逻辑工作单元的操作集合
2.事务处理:保证所有事务都作为一个工作单元来执行,即使出现了故障,都不能改变这种执行方式。当在一个事务中执行多个操作时,要么所有的事务都被提交(commit),要么整个事务回滚(rollback)到最初状态
2当一个连接对象被创建时,默认情况下是自动提交事务:每次执行一个 SQL 语句时,如果执行成功,就会向数据库自动提交,而不能回滚,为了让多个 SQL 语句作为一个事务执行:
a.调用 Connection 对象的 setAutoCommit(false); 以取消自动提交事务
b.在所有的 SQL 语句都成功执行后,调用 commit(); 方法提交事务
c.在出现异常时,调用 rollback(); 方法回滚事务
d.若此时 Connection 没有被关闭, 则需要恢复其自动提交状态

// 以下的两个操作共同构成一个数据库事务。但是在两个操作之间可能出现异常问题。
// 原则上,一旦出现问题,就需要将之前的操作“回滚”!需要对如下的操作进行完善。

技术分享
1 @Test
2 public void testUpdate() {
3     String sql1 = "update user_table set balance = balance - 100 where user = ?";
4     update(sql1, "AA");
5     System.out.println(10 / 0);
6     String sql2 = "update user_table set balance = balance + 100 where user = ?";
7     update(sql2, "BB");
8 }
View Code

3.考虑到数据库事务的话,我们又将原来使用 PreparedStatement 重构的
Statement 的增删改和查的操作,再升级。

// 实现一个通用的 UPDATE INSERT DELETE 的操作的方法(version 3.0)

技术分享
 1 public void update(Connection conn,String sql, Object... args) {
 2     PreparedStatement ps = null;
 3     try {
 4         ps = conn.prepareStatement(sql);
 5         for (int i = 0; i < args.length; i++) {
 6             ps.setObject(i + 1, args[i]);
 7         }
 8         ps.execute();
 9     } catch (Exception e) {
10         e.printStackTrace();
11     } finally {
12         JDBCUtils.close(null, ps, null);
13     }
14 }
View Code

// 实现一个通用的查询操作,返回一个对象(version 3.0)

技术分享
 1 public <T> T getInstance(Connection conn,String sql, Class<T> clazz, Object... args) {
 2     PreparedStatement ps = null;
 3     ResultSet rs = null;
 4     try {
 5         ps = conn.prepareStatement(sql);
 6         // 填充占位符
 7         for (int i = 0; i < args.length; i++) {
 8             ps.setObject(i + 1, args[i]);
 9         }
10         // 4.执行并返回 ResultSet 的对象
11         rs = ps.executeQuery();
12         if (rs.next()) {
13             // 5.创建 T 的对象
14             T t = clazz.newInstance();
15             // 6.将结果集中的列值作为 T 的对象的属性,给予赋值
16             ResultSetMetaData rsmd = rs.getMetaData();
17             int columnCount = rsmd.getColumnCount();
18             for (int i = 0; i < columnCount; i++) {
19                 Object columnVal = rs.getObject(i + 1);
20                 String columnLabel = rsmd.getColumnLabel(i + 1);
21                 PropertyUtils.setProperty(t, columnLabel, columnVal);
22             }
23             return t;
24         }
25     } catch (Exception e) {
26         e.printStackTrace();
27     } finally {
28         // 7.关闭相应的操作
29         JDBCUtils.close(rs, ps, null);
30     }
31     return null;
32 }
View Code

// 实现一个通用的查询操作,返回一个对象的集合(version 3.0)

技术分享
 1 public <T> List<T> getForList(Connection conn,String sql,Class<T> clazz,Object ...args){
 2     PreparedStatement ps = null;
 3     ResultSet rs = null;
 4     List<T> list = new ArrayList<T>();
 5     try{
 6         ps = conn.prepareStatement(sql);
 7         for(int i = 0;i < args.length;i++){
 8             ps.setObject(i + 1, args[i]);
 9         }
10         rs = ps.executeQuery();
11         ResultSetMetaData rsmd = rs.getMetaData();
12         int columnCount = rsmd.getColumnCount();
13         while(rs.next()){
14             T t = clazz.newInstance();
15             for(int i = 0;i < columnCount;i++){
16                 Object columnVal = rs.getObject(i + 1);
17                 String columnLabel = rsmd.getColumnLabel(i + 1);
18                 PropertyUtils.setProperty(t, columnLabel, columnVal);
19             }
20             list.add(t);
21         }
22     }catch(Exception e){
23         e.printStackTrace();
24     }finally{
25         JDBCUtils.close(rs, ps, null);
26     }
27     return list;
28 }
View Code

//考虑到数据库事务,通过 java 程序对数据库中表的操作的模板(掌握)

技术分享
 1 public void method(){
 2     Connection conn = null;
 3     try{
 4         //1.获取数据库的连接(①conn = JDBCUtils.getConnection(); ②数据库连接池(开发者选择此))
 5         //2.开启事务
 6         conn.setAutoCommit(false);
 7         //3.对数据库中表进行相应的操作(增、删、改、查)(①version 3.0 ②DBUtils 工具类: update() 和 query()方法)
 8         //4.提交事务
 9         conn.commit();
10     }catch(Exception e){
11         e.printStackTrace();
12         try{
13             //5.回滚事务
14             conn.rollback();
15         }catch(Exception e1){
16             e1.printStackTrace();
17         }
18     }finally{
19         //6.关闭数据库的连接(①自己实现数据库相应资源的关闭JDBCUtils.close(null,null,conn); ②使用 DBUtils 工具类的 close()方法)
20     }
21 }
View Code

事务的ACID(acid)属性:

1. 原子性(Atomicity) 原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。 
2. 一致性(Consistency) 事务必须使数据库从一个一致性状态变换到另外一个一致性状态。
3. 隔离性(Isolation) 事务的隔离性是指一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
4. 持久性(Durability) 持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响

数据库的隔离级别:

1.对于同时运行的多个事务, 当这些事务访问数据库中相同的数据时, 如果没有采取必要的隔离机制, 就会导致各种并发问题:
a.脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的.
b.不可重复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了.
c.幻读: 对于两个事物 T1, T2, T1 从一个表中读取了一个字段, 然后 T2 在该表中插入了一些新的行. 之后, 如果 T1 再次读取同一个表, 就会多出几行.
2.数据库事务的隔离性: 数据库系统必须具有隔离并发运行各个事务的能力, 使它们不会相互影响, 避免各种并发问题.
3.一个事务与其他事务隔离的程度称为隔离级别. 数据库规定了多种事务隔离级别, 不同隔离级别对应不同的干扰程度, 隔离级别越高, 数据一致性就越好, 但并发性越弱

技术分享

 

七、实现 DAO 及其实现类 CustomerDAO 的代码

 

DAO.java

技术分享
  1 //DAO: database access object
  2 class ReflectionUtils{
  3     //获取 clazz 对象对应的运行时类的父类的泛型
  4     public static Class getSuperGeneric(Class clazz){
  5         Type type = clazz.getGenericSuperclass();
  6         ParameterizedType p = (ParameterizedType)type;
  7         Type[] ts = p.getActualTypeArguments();
  8         return (Class)ts[0];
  9     }
 10 }
 11 
 12 public class DAO<T> {
 13     private Class<T> clazz = null;
 14     //this.getClass()在这个问题中,就是 CustomerDAO
 15     public DAO(){
 16     clazz = ReflectionUtils.getSuperGeneric(this.getClass());
 17     }
 18 
 19     //获取数据库的标准的特定含义的值
 20     public <E> E getValue(Connection conn,String sql,Object...args){
 21         PreparedStatement ps = null;
 22         ResultSet rs = null;
 23         try{
 24             ps = conn.prepareStatement(sql);
 25             for(int i = 0;i < args.length;i++){
 26                 ps.setObject(i + 1, args[i]);
 27             }
 28             rs = ps.executeQuery();
 29             if(rs.next()){
 30             return (E)rs.getObject(1);
 31             }
 32         }catch(Exception e){
 33             e.printStackTrace();
 34         }finally{
 35             JDBCUtils.close(rs, ps, null);
 36         }
 37         return null;
 38     }
 39 
 40     //返回多个对象,以集合的形式返回
 41     public List<T> getForList(Connection conn,String sql,Object ...args){
 42         PreparedStatement ps = null;
 43         ResultSet rs = null;
 44         List<T> list = new ArrayList<>();
 45         try{
 46             //1.预编译 sql 语句,获取 PreparedStatement 对象
 47             ps = conn.prepareStatement(sql);
 48             //2.填充占位符
 49             for(int i = 0;i < args.length;i++){
 50                 ps.setObject(i + 1, args[i]);
 51             }
 52             //3.返回一个结果集
 53             rs = ps.executeQuery();
 54             ResultSetMetaData rsmd = rs.getMetaData();
 55             int columnCount = rsmd.getColumnCount();
 56             while(rs.next()){
 57                 T t = clazz.newInstance();
 58                 //给 t 对象的相应属性赋值
 59                 for(int i = 0;i < columnCount;i++){
 60                     Object columnVal = rs.getObject(i + 1);
 61                     String columnLabel = rsmd.getColumnLabel(i + 1);
 62                     PropertyUtils.setProperty(t, columnLabel, columnVal);
 63                 }
 64                 list.add(t);
 65             }
 66         }catch(Exception e){
 67             e.printStackTrace();
 68         }finally{
 69             JDBCUtils.close(rs, ps, null);
 70         }
 71         //System.out.println(clazz);
 72         return list;
 73     }
 74 
 75     //返回一个对象
 76     public T get(Connection conn,String sql,Object ...args){
 77         PreparedStatement ps = null;
 78         ResultSet rs = null;
 79         try{
 80             //1.预编译 sql 语句,获取 PreparedStatement 对象
 81             ps = conn.prepareStatement(sql);
 82             //2.填充占位符
 83             for(int i = 0;i < args.length;i++){
 84                 ps.setObject(i + 1, args[i]);
 85             }
 86             //3.返回一个结果集
 87             rs = ps.executeQuery();
 88             ResultSetMetaData rsmd = rs.getMetaData();
 89             int columnCount = rsmd.getColumnCount();
 90             if(rs.next()){
 91                 T t = clazz.newInstance();
 92                 //给 t 对象的相应属性赋值
 93                 for(int i = 0;i < columnCount;i++){
 94                     Object columnVal = rs.getObject(i + 1);
 95                     String columnLabel = rsmd.getColumnLabel(i + 1);
 96                     PropertyUtils.setProperty(t, columnLabel, columnVal);
 97                 }
 98                 return t;
 99             }
100         }catch(Exception e){
101             e.printStackTrace();
102         }finally{
103             JDBCUtils.close(rs, ps, null);
104         }
105         //System.out.println(clazz);
106         return null;
107     }
108 
109     //通用的增删改的操作
110     public void update(Connection conn,String sql,Object ... args){
111         PreparedStatement ps = null;
112         try{
113             ps = conn.prepareStatement(sql);
114             for(int i = 0;i < args.length;i++){
115                 ps.setObject(i + 1, args[i]);
116             }
117             ps.executeUpdate();
118         }catch(Exception e){
119             e.printStackTrace();
120         }finally{
121             JDBCUtils.close(null, ps, null);
122         }
123     }
124 }
View Code

Customer.java

技术分享
 1 //CustomerDAO 类是用来操作 Customer 类的
 2 public class CustomerDAO extends DAO<Customer>{
 3 
 4     // @Test
 5     // public void testGeneric(){
 6         // Class clazz = CustomerDAO.class;
 7         // Type type = clazz.getGenericSuperclass();
 8         // ParameterizedType p = (ParameterizedType)type;
 9         // Type[] ts = p.getActualTypeArguments();
10         // System.out.println(ts[0]);
11     // }
12 
13     /**
14     * 获取对应的表中的记录的个数
15     */
16     public long getCount(Connection conn){
17         String sql = "select count(*) from customers";
18         return (long)getValue(conn, sql);
19     }
20 
21     /**
22     * 返回 customers 表中的所有数据
23     * @param conn
24     * @return
25     */
26     public List<Customer> getAll(Connection conn){
27         String sql = "select id,name,email,birth from customers";
28         return getForList(conn, sql);
29     }
30 
31     /**
32     * 根据指定的 id 返回相应的对象
33     * @param conn
34     * @param customerId
35     */
36     public Customer getInstance(Connection conn,int customerId){
37         String sql = "select id,name,email,birth from customers where id = ?";
38         return get(conn, sql, customerId);
39     }
40 
41     /**
42     * 删除指定 customerId 的数据表中的记录
43     * @param conn
44     * @param customerId
45     */
46     public void delete(Connection conn,int customerId){
47         String sql = "delete from customers where id = ?";
48         update(conn, sql, customerId);
49     }
50 
51     /**
52     * 向数据表中修改指定 id 的信息为 Customer 对象的信息
53     * @param conn
54     * @param cust
55     */
56     public void update(Connection conn,Customer cust){
57         String sql = "update customers set name = ?,email = ?,birth = ? where id = ?";
58         update(conn, sql,cust.getName(),cust.getEmail(),cust.getBirth(),cust.getId());
59     }
60 
61     /**
62     * 向数据表中插入一条数据
63     * @param conn 数据库的连接
64     * @param cust 要插入的 Customer 对象
65     */
66     public void insert(Connection conn,Customer cust){
67         String sql = "insert into customers(name,email,birth)values(?,?,?)";
68         update(conn, sql, cust.getName(),cust.getEmail(),cust.getBirth());
69     }
70 }
View Code

TestCustomer.java

技术分享
 1 public class TestCustomerDAO {
 2     CustomerDAO customerDAO = new CustomerDAO();
 3 
 4     @Test
 5     public void testGetCount(){
 6         Connection conn = null;
 7         try{
 8             conn = JDBCUtils.getConnection();
 9             long count = customerDAO.getCount(conn);
10             System.out.println(count);
11         }catch(Exception e){
12             e.printStackTrace();
13         }finally{
14             JDBCUtils.close(null, null, conn);
15         }
16     }
17 
18     @Test
19     public void testGetAll(){
20         Connection conn = null;
21         try{
22             conn = JDBCUtils.getConnection();
23             List<Customer> list = customerDAO.getAll(conn);
24             //System.out.println(list);
25             Iterator<Customer> iterator = list.iterator();
26             while(iterator.hasNext()){
27                 System.out.println(iterator.next());
28             }
29         }catch(Exception e){
30             e.printStackTrace();
31         }finally{
32             JDBCUtils.close(null, null, conn);
33         }
34     }
35 
36     @Test
37     public void testQuery(){
38         Connection conn = null;
39         try{
40             conn = JDBCUtils.getConnection();
41             Customer cust = customerDAO.getInstance(conn, 13);
42             System.out.println(cust);
43         }catch(Exception e){
44             e.printStackTrace();
45         }finally{
46             JDBCUtils.close(null, null, conn);
47         }
48     }
49 
50     @Test
51     public void testDelete(){
52         Connection conn = null;
53         try{
54             conn = JDBCUtils.getConnection();
55             customerDAO.delete(conn, 10);
56         }catch(Exception e){
57             e.printStackTrace();
58         }finally{
59             JDBCUtils.close(null, null, conn);
60         }
61     }
62 
63     @Test
64     public void testUpdate(){
65         Connection conn = null;
66         try{
67             conn = JDBCUtils.getConnection();
68             Customer cust = new Customer(10, "张卫健", "zwj@gmail.com",new
69             Date(new java.util.Date().getTime()));
70             customerDAO.update(conn, cust);
71         }catch(Exception e){
72             e.printStackTrace();
73         }finally{
74             JDBCUtils.close(null, null, conn);
75         }
76     }
77 
78     @Test
79     public void testInsert(){
80         Connection conn = null;
81         try{
82             conn = JDBCUtils.getConnection();
83             Customer cust = new Customer(10, "张卫健", "zwj@gmail.com",new
84             Date(new java.util.Date().getTime()));
85             customerDAO.insert(conn, cust);
86         }catch(Exception e){
87             e.printStackTrace();
88         }finally{
89             JDBCUtils.close(null, null, conn);
90         }
91     }
92 }
View Code

 

 八、数据库连接池

C3P0 数据库连接池

技术分享
 1 // 保证在所有的通过 C3P0 获取的连接中,只有一个 DataSource 的对象。(推荐)
 2 private static DataSource source = null;
 3 
 4 static {
 5     source = new ComboPooledDataSource("helloc3p0");
 6 }
 7 // 获取数据库的连接方式 3:使用 c3p0 数据库连接池获取数据库的连接,使用配置文件
 8 public static Connection getConnection3() throws Exception {
 9     return source.getConnection();
10 }
View Code

 

对应的配置文件: c3p0-config.xml

 

技术分享
 1 <c3p0-config>
 2 <named-config name="helloc3p0">
 3 <!-- 提供数据库连接的 4 个基本信息 -->
 4 <property name="jdbcUrl">jdbc:mysql:///test</property>
 5 <property name="driverClass">com.mysql.jdbc.Driver</property>
 6 <property name="user">root</property>
 7 <property name="password">123456</property>
 8 <!-- 当连接池中的数量不足时, c3p0 连接一次性向数据库服务器申请的
 9 连接数 -->
10 <property name="acquireIncrement">5</property>
11 <!-- 初始化数据库连接池时,池中存在的连接数 -->
12 <property name="initialPoolSize">10</property>
13 <!-- 数据库连接池中最少容纳的连接数 -->
14 <property name="minPoolSize">5</property>
15 <!-- 数据库连接池中最大容纳的连接数 -->
16 <property name="maxPoolSize">100</property>
17 <!-- 连接池中,最多允许存在的 Statement 的数量 -->
18 <property name="maxStatements">10</property>
19 <!-- 一次连接中,最多容纳的 Statement 的个数 -->
20 <property name="maxStatementsPerConnection">5</property>
21 </named-config>
22 </c3p0-config>
View Code

 

DBCP 数据库连接池

技术分享
 1 //随着类的加载,使用 BasicDataSourceFactory 的静态方法 createDataSource()返回一个
 2 //DataSource 的对象
 3 private static DataSource source1 = null;
 4 static {
 5     Properties info = new Properties();
 6     // info.load(new FileInputStream("dbcp.properties"));
 7     InputStream is = JDBCUtils.class.getClassLoader().getResourceAsStream(
 8     "com/atguigu/java/dbcp.properties");
 9     try {
10         info.load(is);
11         source1 = BasicDataSourceFactory.createDataSource(info);
12     } catch (Exception e) {
13         e.printStackTrace();
14     }
15 }
16 // 获取数据库的连接方式 4:使用 DBCP 数据库连接池获取数据库的连接(推荐)
17 public static Connection getConnection5() throws Exception {
18     return source1.getConnection();
19 }
View Code

 

配置文件 dbcp.properties:

技术分享
1 username=root
2 password=123456
3 url=jdbc:mysql://127.0.0.1:3306/test
4 driverClassName=com.mysql.jdbc.Driver
5 initialSize=10
6 maxActive=100
View Code

 

九、 DBUtils
提供了 QueryRunner 类,类中有诸多重载 update() 和 query()方法,供使用,用于堆数据库实现操作:增删改查

 一些细节问题:

1.设计数据库时候,要考虑编码问题,要主要,创建数据库编码方式和创建表的方式以及java程序运行的编码方式一致,不然会报错,或者导致数据存入到数据库中出现乱码。

2.关于JDBC实现数据库连接时,对日期对象的处理方式:

技术分享
 1 public class DateTest {
 2 
 3     /**
 4      * @param args
 5      * @throws SQLException
 6      */
 7     public static void main(String[] args) throws SQLException {
 8         // create("name2", new Date(), 500.0f);
 9         Date d = read(7);
10         System.out.println(d);
11     }
12 
13     static Date read(int id) throws SQLException {
14         Connection conn = null;
15         Statement st = null;
16         ResultSet rs = null;
17         Date birthday = null;
18         try {
19             // 2.建立连接
20             conn = JdbcUtils.getConnection();
21             // conn = JdbcUtilsSing.getInstance().getConnection();
22             // 3.创建语句
23             st = conn.createStatement();
24 
25             // 4.执行语句
26             rs = st.executeQuery("select birthday  from user where id=" + id);
27 
28             // 5.处理结果
29             while (rs.next()) {
30                 //birthday = new Date(rs.getDate("birthday").getTime());
31                 birthday = rs.getDate("birthday");
32             }
33         } finally {
34             JdbcUtils.free(rs, st, conn);
35         }
36         return birthday;
37     }
38 
39     static void create(String name, Date birthday, float money)
40             throws SQLException {
41         Connection conn = null;
42         PreparedStatement ps = null;
43         ResultSet rs = null;
44         try {
45             // 2.建立连接
46             conn = JdbcUtils.getConnection();
47             // conn = JdbcUtilsSing.getInstance().getConnection();
48             // 3.创建语句
49             String sql = "insert into user(name,birthday, money) values (?, ?, ?) ";
50             ps = conn.prepareStatement(sql);
51             ps.setString(1, name);
52             ps.setDate(2, new java.sql.Date(birthday.getTime()));
53             ps.setFloat(3, money);
54 
55             // 4.执行语句
56             int i = ps.executeUpdate();
57 
58             System.out.println("i=" + i);
59         } finally {
60             JdbcUtils.free(rs, ps, conn);
61         }
62     }
63 }
View Code

 

JDBC学习小结

标签:

原文地址:http://www.cnblogs.com/ckysea/p/4603753.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!