测试方向基础——JDBC数据库连接技术浅析

编程入门 行业动态 更新时间:2024-10-06 08:21:53

测试方向基础——JDBC<a href=https://www.elefans.com/category/jswz/34/1771108.html style=数据库连接技术浅析"/>

测试方向基础——JDBC数据库连接技术浅析

DBC数据库连接技术浅析

  • 数据库简介
  • Java中JDBC的基本操作
  • 数据库造作的完整封装(DAO)

数据库简介

  1. 没有文件以前,数据的存储方式以内存为主,无法长期保存。文件系统的产生,数据可以长期保存在文件中。常见的文件类型:
    (1)纯文本:没有格式要求
    (2)数据传输格式:html,xml,json,规定一定的规范的纯文本文件
    (3)制定公司特定格式:excel,csv等
    (4)专门做数据存储的公司:mysql,sqlsever,oracle,DB2等

  2. 关于数据库:
    数据库服务器:硬件
    数据库服务、数据库客户端:软件
    命令行:sql语句; 客户端软件:不唯一;数据库的名字:一般代表某一个应用程序

  3. 数据库的主要职能:保存大量数据、检索数据、数据维护(备份、压缩等)

  4. 常见数据库:MySql, SqlServer, Oracle,SqILite,通用语言都是SQL

  5. SQL是Structured Query Language(结构化查询语言)的缩写,SQL是专为数据库而建立的操作命令集,是一种功能齐全的数据库语言

  6. SQL对数据库的操作:
    (1)数据定义:称为“SQL DDL”,定义数据库的逻辑结构,包括定义数据库、基本表、视图和索引
    (2)数据操纵:称为“SQL DML”,其中包括数据查询和数据更新两大类操作,其中数据更新又包括插入、删除和更新
    (3)数据控制:称为“DCL”,对用户访问数据的控制有基本表和视图的授权、完整性规则的描述,事务控制语句
    (4)其他要素:规定SQL语句在宿主语言的程序中使用的规则

  7. 数据控制:
    (1)安全性控制:授权—>GRANT, 回收---->REVOKE…
    (2)完整性控制:数据库的完整性是指数据的正确性和相容性,主要防止语义上不正确的数据进入数据库。
    (3)事务控制:事务提交:COMMIT; 事务撤销:ROLLBACK…
    (4)并发控制:数据库作为共享资源,允许多个用户程序并行地存取数据**。当多个用户并行地操作数据库时,需要通过并发控制对它们加以协调、控制,以保证并发操作的正确执行,并保证数据库的一致性**,LOCK TABLE 表名(或表名集合)IN ……

Java中JDBC的基本操作

  1. JDBC的概念:是由一组Java语言编写的类和接口组成,是一种用于执行SQL语句的规范 官网链接

  2. JDBC API(API: 应用程序编程接口)提供两类主要接口:
    (1)面向开发人员的java.sql程序包,使得Java程序员能够进行数据库连接,执行SQL查询,并得到结果集合
    (2)面向底层数据库厂商的JDBC Drivers

  3. 创建JDBC应用的步骤:
    (1)加载数据库的驱动程序(首先引入数据库驱动的jar包)
    下载地址
    Class.forName("com.mysql.jdbc.Driver");
    (2)建立数据库连接

    (3)执行数据库操作SQL
    Statement stmt = conn.createStatement();
    ResultSet rs = stmt.exsuteQuery(sql);
    (4)得到ResultSet进行结果处理
    (5)关闭数据库连接。

  4. DriverManager:是JDBC的管理层,管理一组JDBC驱动程序的基本服务。DriverManager类的主要作用:追踪可用的驱动程序,并在数据库和相应驱动程序之间建立连接。调用DriverManager.getConnection()方法将建立与数据库的连接,得到与数据库连接的Connection对象

  5. (1) Connection类是JDBC规范中最核心的类,statement对象和ResultSet对象等都直接或者间接的来源于它
    (2)Connection对象表示与特定数据库的连接(会话)。
    1)得到Statement对象的方法:
    createStatement();
    prepareStatement(String sql); 【该方法返回一个PreparedStatement对象,并能把sql语句提交到数据库进行预编译
    prepareCall(String sql)
    2)为了保证数据库事务的原子性,Connection可以设置手动提交事务
    补充该类的两个方法:
    commit()进行当前业务开始以来的所有变化;
    rollback()放弃当前业务开始以来的所有改变。

  6. Statement是向数据库提交SQL语句并返回相应结果的工具。语句可以是SQL查询、修改、插入或者删除
    (1)PreparedStatement接口:防止SQL注入攻击(使用占位符“?”); 提高SQL的执行性能(在执行之前有预处理); 避免使用SQL方言; 提高JDBC中有关SQL代码的可读性。
    (2)CallableStatement接口用于执行SQL存储过程的接口
    (3)Statement常用方法:
    * execute:执行给定SQL语句,可能返回多条结果
    * executeQuery:执行给定的 SQL 语句,该语句返回单个 ResultSet 对象
    * executeUpdate执行,该语句可能为 INSERT、UPDATE 或 DELET给定 SQL 语句
    * getConnection:获取生成此 Statement 对象的 Connection 对象
    * close:立即释放此 Statement 对象的数据库和 JDBC 资源,而不是等待该对象自动关闭时发生此操作
    * getFetchSize:获取结果集合的行数
    * getQueryTimeout:获取驱动程序等待 Statement 对象执行的秒数

  7. PreparedStatement类:是Statement的子接口。用PreparedStatement类效率会更高。
    PreparedStatement实例要通过Connection对象调用prepareStatement(String sql)方法获得。
    常用方法:

    • public ResultSetMetaData getMetaData()
    • public void setInt(int parameterIndex, int x)
    • public void setFloat(int parameterIndex, float x)
    • public void setString(int parameterIndex, String x)
    • public void setDate(int parameterIndex, Date x)
  8. CallableStatement用于执行 SQL 存储过程的接口
    CallableStatement继承了PreparedStatement接口,所以也继承了PreparedStatement的方法(很少用)

  9. ResultSet:表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
    其对象具有指向其当前数据行的光标
    常用方法: String getString(int columnIndex):以 Java 编程语言中 String 的形式获取此 ResultSet 对象的当前行中指定列的值

    while (rs.next()) {System.out.println(rs.getString("name"));
    }
    

    常用方法:

    • boolean next():将光标从当前位置向前移一行。当调用 next 方法返回 false 时,光标位于最后一行的后面
    • int getInt(String columnIndex):以 Java 编程语言中 int 的形式获取此 ResultSet 对象的当前行中指定列的值。
    • next:将光标从当前位置向前移一行
    • getXXX:以某种对象的形式获取指定 JDBC 该类型参数的值
    • absolute:将光标移动到此 ResultSet 对象的给定行编号
    • afterLast:将光标移动到此 ResultSet 对象的末尾,正好位于最后一行之后
    • beforeFirst:将光标移动到此 ResultSet 对象的开头,正好位于第一行之前
    • close:立即释放此 ResultSet 对象的数据库和 JDBC 资源,而不是等待该对象自动关闭时发生此操作
    • first:将光标移动到此 ResultSet 对象的第一行
    • getRow:获取当前行编号
    • isFirst:获取光标是否位于此 ResultSet 对象的第一行
    • isLast:获取光标是否位于此 ResultSet 对象的最后一行
    • last:将光标移动到此 ResultSet 对象的最后一行
    • previous:将光标移动到此 ResultSet 对象的上一行
  10. 关于关闭数据库的连接,一共有三处:
    检测ResultSet是否关闭,否则关闭
    检测Statement是否关闭,否则关闭
    检测Connection是否关闭,否则关闭

    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)

  1. 所以我们对于一张表的所有操作,在Java程序中体现到了一个实体类的所有的操作。
    一般标准工程中一个实体类会有一个对应的DAO类(Data Access Object),来进行这个类的所有的操作。

下面也都是代码的栗子了:

  1. 创建一个数据库
package xxx.www.xhx;import java.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}}}
}
  1. 查询
    在创建的数据库中,可以加入一个表,我这里命名为test0509, 下面代码用来查询表中的信息。
    提示,URL后的?useUnicode=true&characterEncoding=utf-8&useSSL=true或者仅加上?useSSL=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,你品,你慢慢品,就是prepareStatement得到statement对象,他会把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));//关闭连接}
}

效果如下:

  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.

用prepareStatement实现插入:

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语句即可
update user set age =?
更新操作封装时,可能出现参数个数不确定的问题,浅浅给出一个代码,不想看就别看了。

public static int update(String sql, Object...objects) {return 0;}

更多推荐

测试方向基础——JDBC数据库连接技术浅析

本文发布于:2024-02-25 17:41:28,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1699793.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:数据库连接   方向   基础   测试   技术

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!