Java数据持久化->JDBC数据库
JDBC(Java Data Base Connectivity, Java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问接口,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
JDBC(Java Data Base Connectivity, Java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问接口,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。
1.安装Xampp 1.6.8版本并创建数据库和表。实验目的
2.掌握Java利用JDBC操作数据库的基本过程。
3.掌握JDBC针对数据库的增删改查的操作。
4.熟悉SQL语句和PreparedStatement等用法。
1.安装并启动Xampp实验流程
(1)下载XAMPP1.6.8版本,地址为:https://sourceforge.net/projects/xampp/files/,选择“XAMPP Windows“目录,进入后选择1.6.8的版本即可。也可以直接通过搜索引擎搜索该版本并完成下载。由于XAMPP版本更新较快,而很多Web系统无法兼容较新的XAMPP版本,所以请务必下载此版本。
(2)安装XAMPP,保持默认安装即可,安装过程不用勾选任何选项。
(3)安装完成后,启动XAMPP控制面板,或进入XAMPP安装目录,运行xampp-control.exe,并启动Apache和MySQL即可,如图。

(4)打开浏览器,输入网址:http://localhost,如果出现如下页面,说明XAMPP安装成功。

(5)如果无法启动Apache或MySQL,最可能的原因就是端口被占用。默认情况下,Apache的HTTP服务器会占用80端口,而HTTPS服务会战胜443端口,MySQL占用3306端口。我们可以运行XAMPP安装目录下的xampp-portcheck.exe对端口的占用情况进行检查确认,只有Status栏为free表示端口未被占用,如图。

(6) 解决端口被占用的方法主要有两种,一种是停止占用端口的进程,一种是修改Apache和MySQL对应的端口号。建议大家使用第一种解决方案,这样可以保持与本书各章节内容的一致性。通常情况下,如果电脑上安装了其它Web服务器,如IIS,Tomcat之类的,那么80端口很有可能被占用,SVN和LoadRunner的代理进程很有可能占用443端口。另外电脑上如果之前已经安装了MySQL,那么3306端口也会被占用。
(7) 如果都无法解决问题,实在没有办法的情况下,我们可以选择修改XAMPP的端口号,现将各端口号对应的配置文件列出如下,供各位读者朋友参考:
a) Apache的80端口:Xampp\apache\conf\httpd.conf文件中的Listen 80。
b) Apache的443端口:Xampp\apache\conf\extra\httpd-ssl.conf文件中的Listen 443。
c) MySQL的3306端口:Xampp\mysql\bin\my.cnf文件中的port = 3306。
2.创建MySQL数据库和表
(1)打开网址:http://localhost/phpmyadmin 进入MySQL数据库管理后台。
(2)创建数据库,名称为:learn,排序规则选择:utf8-general-ci。

(3)为该数据库创建一张表,命名为:user,共5个列:

(4)为该表设置列及类型,属性等。

(5)为该表添加两行或多行记录。

在上述操作中,我们为密码栏使用“MD5”函数,这样就可以将密码按MD5加密格式存储。
(6) 最终表格的数据如下:

3.准备JDBC驱动程序
在Java中,要使用JDBC来操作数据库,我们需要首先将对应的数据库的驱动程序导入到项目中。针对MySQL数据库,也有专门的jar包来负责,我们将包:mysql-connector-java-5.1.16.jar导入进来。
4.利用JDBC操作MySQL
package com.woniuxy.java.io; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class JDBCReadWrite { // 声明数据库驱动程序类 private static String driverClassName = "com.mysql.jdbc.Driver"; // 定义数据库连接字符串 private static String url = "jdbc:mysql://localhost:3306/learn?" + "user=root&password=&useUnicode=true&characterEncoding=UTF8"; public static void main(String[] args) throws Exception { JDBCReadWrite jdbc = new JDBCReadWrite(); // jdbc.insert(); // jdbc.getCount(); // jdbc.update(); // jdbc.delete(); // jdbc.select(); // 从二维数组中遍历整个数据集的记录 String[][] data = jdbc.getAllData(); for (int i=0; i<data.length; i++) { for (int j=0; j<data[i].length; j++) { System.out.println(data[i][j]); } System.out.println("==================="); } } // 建议与数据库之间的连接 public Connection getConnection() throws Exception { Connection conn = null; Class.forName(driverClassName).newInstance(); // new com.mysql.jdbc.Driver(); 也可以直接这样来实例化 conn = DriverManager.getConnection(url); return conn; } // 执行简单的SQL查询语句,了解其运行过程 public void getCount() throws Exception { Statement stmt = this.getConnection().createStatement(); String sql = "select count(*) from user"; ResultSet rs = stmt.executeQuery(sql); rs.next(); // 让结果集定位到第一行 System.out.println(rs.getInt(1)); // 获取第1列的结果 } // 往数据库中插入一条新的记录 public void insert() throws Exception { Statement stmt = this.getConnection().createStatement(); String sql = "insert into user values(0,'qiang'," + "'e10adc3949ba59abbe56e057f20f883e','18812345678','qiang@woniuxy.com')"; stmt.executeUpdate(sql); } // 遍历整个表的数据 public void select() throws Exception { String sql = "select * from user"; Statement stmt = this.getConnection().createStatement(); ResultSet rs = stmt.executeQuery(sql); while(rs.next()) { System.out.print(rs.getInt("id") + "\t"); System.out.print(rs.getString("username") + "\t"); System.out.println(rs.getString("phone")); } } // 执行update语句实现更新 public void update() throws Exception { String sql = "update user set phone='18509876543' where id=3"; Statement stmt = this.getConnection().createStatement(); stmt.executeUpdate(sql); } // 执行delete语句实现删除 public void delete() throws Exception { String sql = "delete from user where id=3"; Statement stmt = this.getConnection().createStatement(); stmt.executeUpdate(sql); } // 将整个数组表的内容保存到二维数组中 public String[][] getAllData() throws Exception { String sql = "select * from user"; PreparedStatement ps = this.getConnection().prepareStatement(sql); ResultSet rs = ps.executeQuery(); // 定义元数据对象以获得数据库中的列,以此来定义二维数组的长度 ResultSetMetaData metaData = ps.getMetaData(); int columnCount = metaData.getColumnCount(); int rowCount = 0; // 循环遍历该结果集,以此来获取表的行数量,用以定义二维数组的长度 while(rs.next()) { rowCount ++; } rs.first(); // 将当前记录游标移动到第一行 String[][] data = new String[rowCount][columnCount]; int row = 0; // 遍历整个结果集,将将每一条数据保存到二维数组中 // 由于游标已经在第一行,所以此处使用do...while循环,否则会路过第一行内容 do { for (int col=0; col<columnCount; col++) { // 从结果集中取值的下标从1开始,而不是0 data[row][col] = rs.getString(col+1); } row++; } while (rs.next()); return data; } } |
5.使用PreparedStatement对象
上述演示代码中,我们使用了一个新的对象:PreparedStatement,PreparedStatement接口继承至Statement, PreparedStatement实例包含已编译的 SQL 语句,所以其执行速度要快于 Statement 对象,并且使代码的可读性,可维护性更强。同时,由于使用了预编译的处理方式,所以对于恶意攻击的SQL语句,利用PreparedStatement可以更好地预防,最大限度地避免安全性漏洞。
另外,作为 Statement 的子类,PreparedStatement 继承了 Statement 的所有功能。三个方法execute、 executeQuery和executeUpdate已被更改以使之不再需要参数。请看如下示例:
// 使用PreparedStatement public void psInsert() throws Exception { String sql = "insert into user(username,password,phone,email) values(?,?,?,?)"; PreparedStatement ps = this.getConnection().prepareStatement(sql); ps.setString(1, "denny"); ps.setString(2, "c33367701511b4f6020ec61ded352059"); ps.setString(3, "15501018089"); ps.setString(4, "denn@woniuxy.com"); ps.executeUpdate(); } |
思考练习
1.请查阅资料完成对其它数据库管理系统的连接字符串设置。
2.利用JDBC提供的API完成数据库的增删改查操作。
3.尝试利用JDBC完成WoniuATM的用户信息管理。