测试方向基础——JDBC数据库连接技术浅析
DBC数据库连接技术浅析
数据库简介
没有文件以前,数据的存储方式以内存为主,无法长期保存。文件系统的产生,数据可以长期保存在文件中。常见的文件类型:
(1)纯文本:没有格式要求
(2)数据传输格式:html,xml,json,规定一定的规范的纯文本文件
(3)制定公司特定格式:excel,csv等
(4)专门做数据存储的公司:mysql,,,DB2等
关于数据库:
数据库服务器:硬件
数据库服务、数据库客户端:软件
命令行:sql语句; 客户端软件:不唯一;数据库的名字:一般代表某一个应用程序
数据库的主要职能:保存大量数据、检索数据、数据维护(备份、压缩等)
常见数据库:MySql, , ,,通用语言都是SQL
SQL是 Query (结构化查询语言)的缩写,SQL是专为数据库而建立的操作命令集,是一种功能齐全的数据库语言
SQL对数据库的操作:
(1)数据定义:称为“SQL DDL”,定义数据库的逻辑结构,包括定义数据库、基本表、视图和索引
(2)数据操纵:称为“SQL DML”,其中包括数据查询和数据更新两大类操作,其中数据更新又包括插入、删除和更新
(3)数据控制:称为“DCL”,对用户访问数据的控制有基本表和视图的授权、完整性规则的描述,事务控制语句等
(4)其他要素:规定SQL语句在宿主语言的程序中使用的规则
数据控制:
(1)安全性控制:授权—>GRANT, 回收---->…
(2)完整性控制:数据库的完整性是指数据的正确性和相容性,主要防止语义上不正确的数据进入数据库。
(3)事务控制:事务提交:; 事务撤销:…
(4)并发控制:数据库作为共享资源,允许多个用户程序并行地存取数据**。当多个用户并行地操作数据库时,需要通过并发控制对它们加以协调、控制,以保证并发操作的正确执行,并保证数据库的一致性**,LOCK TABLE 表名(或表名集合)IN ……
Java中JDBC的基本操作
JDBC的概念:是由一组Java语言编写的类和接口组成,是一种用于执行SQL语句的规范 官网链接
JDBC API(API: 应用程序编程接口)提供两类主要接口:
(1)面向开发人员的java.sql程序包,使得Java程序员能够进行数据库连接,执行SQL查询,并得到结果集合
(2)面向底层数据库厂商的JDBC
创建JDBC应用的步骤:
(1)加载数据库的驱动程序(首先引入数据库驱动的jar包)
下载地址
Class.("com.mysql.jdbc.");
(2)建立数据库连接
(3)执行数据库操作SQL
stmt = conn.();
rs = stmt.(sql);
(4)得到进行结果处理
(5)关闭数据库连接。
:是JDBC的管理层,管理一组JDBC驱动程序的基本服务。类的主要作用:追踪可用的驱动程序,并在数据库和相应驱动程序之间建立连接。调用.()方法将建立与数据库的连接,得到与数据库连接的对象
(1) 类是JDBC规范中最核心的类,对象和对象等都直接或者间接的来源于它
(2)对象表示与特定数据库的连接(会话)。
1)得到对象的方法:
();
( sql); 【该方法返回一个对象,并能把sql语句提交到数据库进行预编译】
( sql)
2)为了保证数据库事务的原子性,可以设置手动提交事务
补充该类的两个方法:
()进行当前业务开始以来的所有变化;
()放弃当前业务开始以来的所有改变。
是向数据库提交SQL语句并返回相应结果的工具。语句可以是SQL查询、修改、插入或者删除
(1)接口:防止SQL注入攻击(使用占位符“?”); 提高SQL的执行性能(在执行之前有预处理); 避免使用SQL方言; 提高JDBC中有关SQL代码的可读性。
(2)接口用于执行SQL存储过程的接口
(3)常用方法:
* :执行给定SQL语句,可能返回多条结果
* :执行给定的 SQL 语句,该语句返回单个 对象
* 执行,该语句可能为 、 或 DELET给定 SQL 语句
* :获取生成此 对象的 对象
* close:立即释放此 对象的数据库和 JDBC 资源,而不是等待该对象自动关闭时发生此操作
* :获取结果集合的行数
* :获取驱动程序等待 对象执行的秒数
类:是的子接口。用类效率会更高。
实例要通过对象调用( sql)方法获得。
常用方法:
用于执行 SQL 存储过程的接口
继承了接口,所以也继承了的方法(很少用)
:表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
其对象具有指向其当前数据行的光标
常用方法: (int ):以 Java 编程语言中 的形式获取此 对象的当前行中指定列的值
while (rs.next()) {System.out.println(rs.getString("name"));
}
常用方法:
关于关闭数据库的连接,一共有三处:
检测是否关闭,否则关闭
检测是否关闭,否则关闭
检测是否关闭,否则关闭
if(rs!=null)try{rs.close();}catch(Exception e){e.printStackTrace();}
if(stmt!=null)try{stmt.close();}catch(Exception e){e.printStackTrace();}
if(conn!=null)try{conn.close();}catch(Exception e){e.printStackTrace();}
数据库造作的完整封装(DAO) 所以我们对于一张表的所有操作,在Java程序中体现到了一个实体类的所有的操作。
一般标准工程中一个实体类会有一个对应的DAO类(Data ),来进行这个类的所有的操作。
下面也都是代码的栗子了:
创建一个数据库
package xxx.www.xhx;import java.net.CookieHandler;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;//创建数据库
public class Demo1 {public static void main(String[] args) {String connUrl = "jdbc:mysql://127.0.0.1:3306";String driverStr = "com.mysql.jdbc.Driver";Statement stmt = null;Connection con = null;try {// 1.加载驱动Class.forName(driverStr);// 2.建立数据库的连接con = DriverManager.getConnection(connUrl, "root", "123456");if (!con.isClosed()) {System.out.println("数据库连接成功");// 3.使用statement执行SQL语句stmt = con.createStatement();boolean flag = stmt.execute("create database demo1112");// 创建一个数据库// 4.对执行结果进行处理if (flag) {System.out.println("数据库创建成功");} else {System.out.println("数据库创建失败");}}} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {try {// 5.关闭数据库的连接if (stmt != null) {stmt.close();}if (con != null) {con.close();}} catch (Exception e) {// TODO: handle exception}}}
}
查询
在创建的数据库中,可以加入一个表,我这里命名为, 下面代码用来查询表中的信息。
提示,URL后的?=true&=utf-8&=true或者仅加上?=true是因为警告:在没有SSL连接的情况下建立ssl连接不建议使用服务器的身份验证。此用此方法,仅仅是初学,不同太在意。
package xxx.www.xhx;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;//查询
public class Demo2 {public static void main(String[] args) throws ClassNotFoundException, SQLException {String connUrl = "jdbc:mysql://127.0.0.1:3306/test0509?useUnicode=true&characterEncoding=utf-8&useSSL=true";String driverStr = "com.mysql.jdbc.Driver";String querySql = "select id,name as username,password,age from user";Class.forName(driverStr);Connection conn = DriverManager.getConnection(connUrl, "root", "123456");Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(querySql);// 执行sql语句while (rs.next()) {int id = rs.getInt(1);// 对应的查询结果的第几列String name = rs.getString("username");// 形参是字段名String password = rs.getString("password");System.out.println("---" + id + "---" + name + "----" + password);}rs.close();stmt.close();conn.close();}
}
打印出来的效果如下:
下面基于此运行结果,示例几个常用的方法。
package xxx.www.xhx;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;//查询
public class Demo2 {public static void main(String[] args) throws ClassNotFoundException, SQLException {String connUrl = "jdbc:mysql://127.0.0.1:3306/test0509?useSSL=true";String driverStr = "com.mysql.jdbc.Driver";String querySql = "select id,name as username,password,age from user";Class.forName(driverStr);Connection conn = DriverManager.getConnection(connUrl, "root", "123456");Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(querySql);// 执行sql语句// ResultSet 指针初始值在第一行之前rs.absolute(3);// 指针定位到第三行System.out.println(rs.getString("username")); // 第三行打印出tom3rs.beforeFirst(); // 指针定位到第一行之前rs.next();// 指针定位到下一行,即第一行,应该为tom1System.out.println(rs.getString("username"));rs.afterLast();// 指针定位到最后一行之后rs.previous();// 指针向前移动一行,即tomSystem.out.println(rs.getString("username"));rs.close();stmt.close();conn.close();}
}
结果如下:
查询结果的列名获取。
package xxx.www.xhx;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;//查询
public class Demo2 {public static void main(String[] args) throws ClassNotFoundException, SQLException {String connUrl = "jdbc:mysql://127.0.0.1:3306/test0509?useSSL=true";String driverStr = "com.mysql.jdbc.Driver";String querySql = "select id,name as username,password,age from user";Class.forName(driverStr);Connection conn = DriverManager.getConnection(connUrl, "root", "123456");Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(querySql);// 执行sql语句ResultSetMetaData metaData = rs.getMetaData(); //返回结果的列名int count = metaData.getColumnCount();System.out.println(count);System.out.println(metaData.getColumnLabel(2));// as之后的别名System.out.println(metaData.getColumnName(2));// as之前的原列名rs.close();stmt.close();conn.close();}
}
结果如下:
在此,我们需要了解一个问题:SQL注入问题。在此就浅浅的了解一下吧。举个例子:
插入or 1 = 1 --后,所有信息都会被查出。
上面那一大堆类中,有浅浅的一个细节,hh,你品,你慢慢品,就是得到对象,他会把sql语句提交到数据库进行预编译。效率更高一点,更安全些。
package xxx.www.xhx;import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;import javax.naming.spi.DirStateFactory.Result;public class Demo4 {public static void main(String[] args) throws SQLException {String sql = "select count(*) from user where name = ? and password = ?";// 这个问号就相当于一个占位符Connection conn = DBUtils.openConnection();PreparedStatement pStatement = conn.prepareStatement(sql);// 普通的一个查询pStatement.setString(1, "tom1");// 1表示第一个占位符pStatement.setString(2, "123");// 2表示第二个占位符ResultSet rSet = pStatement.executeQuery();// 返回结果// 因为只有一行,我们用if即可。超过一行就得用循环rSet.next(); // 移动到第一行System.out.println(rSet.getInt(1));// SQL注入查询pStatement.setString(1, "'or 1=1 -- '");// 1表示第一个占位符pStatement.setString(2, "123");// 2表示第二个占位符rSet = pStatement.executeQuery();// 返回结果// 因为只有一行,我们用if即可。超过一行就得用循环rSet.next(); // 移动到第一行System.out.println(rSet.getInt(1));//关闭连接}
}
效果如下:
插入
封装的意识:我们不妨把建立连接,关闭连接的代码装在一个类里。
package xxx.www.xhx;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;public class DBUtils {static String connUrl = "jdbc:mysql://127.0.0.1:3306/test0509?useSSL=true";static String driverStr = "com.mysql.jdbc.Driver";static {try {Class.forName(driverStr);} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public static Connection openConnection() {Connection conn = null;try {conn = DriverManager.getConnection(connUrl, "root", "123456");} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}return conn;}public static void closeCoonection(Connection conn) {if (conn != null) {try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
}
插入一条数据
package xxx.www.xhx;import java.lang.Thread.State;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;//插入
public class Demo3 {public static void main(String[] args) throws SQLException {String insert_sql="INSERT INTO user(name, password, age) "+ "VALUES ('tom13', '123', '20')";Connection conn = DBUtils.openConnection();Statement stmt = conn.createStatement();int count = stmt.executeUpdate(insert_sql);//影响了多少行System.out.println(count);stmt.close();DBUtils.closeCoonection(conn);}
}
输出为1.
用实现插入:
package xxx.www.xhx;import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;import com.mysql.jdbc.Driver;public class Demo5 {public static void main(String[] args) throws ClassNotFoundException, SQLException {Class.forName("com.mysql.jdbc.Driver");String connStr = "jdbc:mysql://127.0.0.1:3306/test0509?useSSL=true";String sql = "INSERT INTO user (name,password,age) VALUES (?, ?, ?)";Connection connection = DriverManager.getConnection(connStr, "root", "123456");PreparedStatement pstmt = connection.prepareStatement(sql);for (int i = 15; i < 29; i++) {pstmt.setString(1, "tom" + i);pstmt.setString(2, "11112333");pstmt.setInt(3, 33);int count = pstmt.executeUpdate();// 不放循环里,只插入一次}pstmt.close();connection.close();}
}
查看表,可以发现插入成功:
更新操作,只需要修改sql语句即可
user set age =?
更新操作封装时,可能出现参数个数不确定的问题,浅浅给出一个代码,不想看就别看了。
public static int update(String sql, Object...objects) {return 0;}