JDBC和连接池02

3.ResultSet[结果集]

  • 基本介绍
  1. 表示数据库结果集的数据表,通常通过执行查询数据库的语句生成
  2. ResultSet对象保持一个光标指向其当前的数据行,最初,光标位于第一行的之前
  3. next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false,因此可以在while循环中使用循环来遍历结果集

例子

首先在数据库的actor表中添加两行数据

INSERT INTO actor VALUES(NULL,'刘德华','男','1970-12-12','110'),
(NULL,'jack','男','1990-11-11','112')

package li.jdbc.resultset_;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Date;
import java.util.Properties; @SuppressWarnings("all")
public class ResultSet_ {
public static void main(String[] args) throws Exception {
//通过Properties对象拿到配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//获取相关的值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver"); //1.注册驱动
Class.forName(driver);//建议写上
//2.得到连接
Connection connection = DriverManager.getConnection(url, user, password); //3.得到statement
Statement statement = connection.createStatement();
//4.组织sql
String sql = "select id,name,sex,borndate from actor";
//执行给定的sql语句,该语句返回单个ResultSet对象 /**
+----+-----------+-----+----------------------+
| id | name | sex | borndate |
+----+-----------+-----+----------------------+
| 1 | 刘德华 | 男 | 1970-12-12 00:00:00 |
| 2 | jack | 男 | 1990-11-11 00:00:00 |
+----+-----------+-----+----------------------+
*/
/**
* resultset源码 ResultSet对象的结构
*
*/
ResultSet resultSet = statement.executeQuery(sql); //5.使用while循环取出数据
//最开始时next指向表头(第一行之前)
while (resultSet.next()) {//让光标向后移动,如果没有更多行,则返回false
int id = resultSet.getInt(1);//获取该行的第1列数据
String name = resultSet.getString(2);//获取该行的第2列数据
String sex = resultSet.getString(3);//获取该行的第3列数据
Date date = resultSet.getDate(4);//获取该行的第4列数据
System.out.println(id+"\t"+name+"\t"+sex+"\t"+date);
} //6.关闭连接
resultSet.close();
statement.close();
connection.close();
}
}

运行结果如下:

在语句ResultSet resultSet = statement.executeQuery(sql);旁打上断点,点击debug,点击step over,选择resultset数组,再选择rowdata。

可以看到底层是arraylist的一个对象数组。

4.Statement

  • 基本介绍
  1. Statement对象,用于执行静态SQL语句并返回其生成的结果的对象
  2. 在建立连接后,需要对数据库进行访问,执行命名或是SQL语句,可以通过
    • Statement [存在SQL注入问题]
    • PreparedStatement [预处理]
    • CallableStatement [存储过程]
  3. Statement对象执行SQL语句,存在SQL注入风险
  4. SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令,恶意攻击数据库
  5. 要防范SQL注入,只要用PreparedStatement(从Statement扩展而来)取代Statement就可以了

例子1-sqlyog演示sql注入

-- 演示sql注入
-- 创建一张表
CREATE TABLE admin( -- 管理员表
NAME VARCHAR(32) NOT NULL UNIQUE,
pwd VARCHAR(32) NOT NULL DEFAULT ''
)CHARACTER SET utf8; -- 添加数据
INSERT INTO admin VALUES('tom','123'); -- 正常情况下,查找某个管理是否存在
SELECT * FROM admin
WHERE NAME = 'tom' AND pwd = '123'; -- SQL注入
-- 输入用户名为 1' or
-- 输入密码为 or '1'='1
-- 这样就变成了下面的语句,可以将所有的数据都查找出来
SELECT * FROM admin
WHERE NAME = '1' OR' AND pwd = 'OR '1'='1';

例子2-java程序演示SQL注入

package li.jdbc.statement;

//演示statement的注入问题

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.Properties;
import java.util.Scanner; public class Statement_ {
public static void main(String[] args) throws Exception { Scanner scanner = new Scanner(System.in); //让用户输入管理员的名字和密码
System.out.print("请输入管理员的名字:");
String admin_name = scanner.nextLine();//如果希望看到SQL注入,这里需要使用nextLine,如果用next():当接收到空格或者 '就是表示结束
System.out.print("请输入管理员的密码:");
String admin_pwd = scanner.nextLine(); //通过Properties对象拿到配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//获取相关的值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver"); //1.注册驱动
Class.forName(driver);
//2.获取连接
Connection connection = DriverManager.getConnection(url, user, password);
//3.得到Statement对象
Statement statement = connection.createStatement();
//4.组织SQL语句 String sql = "select name,pwd from admin where name='"
+ admin_name + "' and pwd ='" + admin_pwd + "'";
ResultSet resultSet = statement.executeQuery(sql);
if (resultSet.next()) {//如果查询到一条记录,则说明该管理员存在
System.out.println("恭喜,登录成功");
} else {
System.out.println("对不起,登录失败");
} //5.关闭连接
resultSet.close();
statement.close();
connection.close();
}
}

5.PreparedStatement[预处理查询]

  • 基本介绍
  1. PreparedStatement执行的SQL语句中的 参数用问号(?)来表示,调用PreparedStatement对象的setXxx()方法来设置这些参数。

    setXxx()方法有两个参数,第一个参数是要设置的SQL语句中的参数的索引(从1开始),第二个参数是设置的SQL语句中的参数的值

  2. 调用executeQuery(),返回ResultSet对象

  3. 调用executeUpdate():执行更新,包括增,删,修改

  • 预处理的好处
  1. 不再使用+拼接sql语句,减少语法错误
  2. 有效地解决了SQL注入问题
  3. 大大减少了编译次数,效率较高

例子-解决SQL注入问题

package li.jdbc.preparedstatement_;

import java.io.FileInputStream;
import java.sql.*;
import java.util.Properties;
import java.util.Scanner; //演示PreparedStatement的使用
@SuppressWarnings("all")
public class PreparedStatement_ {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in); //让用户输入管理员的名字和密码
System.out.print("请输入管理员的名字:");
String admin_name = scanner.nextLine();
System.out.print("请输入管理员的密码:");
String admin_pwd = scanner.nextLine(); //通过Properties对象拿到配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//获取相关的值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver"); //1.注册驱动
Class.forName(driver);
//2.获取连接
Connection connection = DriverManager.getConnection(url, user, password);
//3.得到PreparedStatement对象
//3.1组织SQL语句,sql语句的问号就相当于占位符
String sql = "select name,pwd from admin where name= ? and pwd = ?";
//3.2preparedStatement对象是实现了 PreparedStatement接口的 实现类的 对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//3.3给 ? 赋值
preparedStatement.setString(1,admin_name);
preparedStatement.setString(2,admin_pwd); //4.执行select语句使用 executeQuery
// 如果执行的是dml(update,insert,delete)语句使用executeUpdate
// 这里执行 executeQuery,不用再写sql进去了
ResultSet resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {//如果查询到一条记录,则说明该管理员存在
System.out.println("恭喜,登录成功");
} else {
System.out.println("对不起,登录失败");
} //5.关闭连接
resultSet.close();
preparedStatement.close();
connection.close();
}
}

5.1预处理DML

package li.jdbc.preparedstatement_;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.util.Properties;
import java.util.Scanner; //演示PreparedStatement的使用
@SuppressWarnings("all")
public class PreparedStatementDML_ {
public static void main(String[] args) throws Exception {
Scanner scanner = new Scanner(System.in); //让用户输入管理员的名字和密码
System.out.print("请输入管理员的名字:");
String admin_name = scanner.nextLine();
// System.out.print("请输入管理员的密码:");
// String admin_pwd = scanner.nextLine(); //通过Properties对象拿到配置文件的信息
Properties properties = new Properties();
properties.load(new FileInputStream("src\\mysql.properties"));
//获取相关的值
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String url = properties.getProperty("url");
String driver = properties.getProperty("driver"); //1.注册驱动
Class.forName(driver);
//2.获取连接
Connection connection = DriverManager.getConnection(url, user, password);
//3.得到PreparedStatement对象
//3.1组织SQL语句,sql语句的问号就相当于占位符
//添加记录
//String sql = "insert into admin values (?,?)";
//更改
//String sql = "update admin set pwd=? where name =?";
//删除
String sql = "delete from admin where name=?"; //3.2preparedStatement对象是实现了 PreparedStatement接口的 实现类的 对象
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//3.3给 ? 赋值
preparedStatement.setString(1, admin_name);
// preparedStatement.setString(2, admin_pwd); //4.执行dml(update,insert,delete)语句使用executeUpdate
int rows = preparedStatement.executeUpdate();
System.out.println(rows > 0 ? "执行成功" : "执行失败"); //5.关闭连接
preparedStatement.close();
connection.close();
}
}

  • 练习

参考上面的代码

  1. 创建admin表
  2. 使用PreparedStatement添加5条数据
  3. 修改tom的记录,将name改成King
  4. 删除一条记录
  5. 查询全部记录,并显示在控制台

6.JDBC API

7.JDBCUtils开发

7.1封装JDBCUtils

  • 说明

在jdbc操作中,获取连接和释放资源是经常使用到的,可以将其封装为JDBC连接的工具类JDBCUtils

例子

封装的工具类JDBCUtils:

package li.jdbc.utils;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties; /**
* 这是一个工具类,完成mysql的连接和关闭资源
*/
public class JDBCUtils {
//定义相关的属性(4个),因为只需要一份,因此我们将其做成static属性
private static String user;//用户名
private static String password;//密码
private static String url;//url
private static String driver;//驱动名 //在static代码块去初始化
static {
Properties properties = new Properties();
try {
properties.load(new FileInputStream("src\\mysql.properties"));
user = properties.getProperty("user");
password = properties.getProperty("password");
url = properties.getProperty("url");
driver = properties.getProperty("driver");
} catch (IOException e) {
//在实际开发中往往会这样处理
// 1.将 编译异常 转为 运行异常
// 2.这时调用者可以选择捕获该异常,亦可以选择默认处理该异常,比较方便
// (对于运行异常,程序中如果没有处理,默认就是throw的方式处理)
throw new RuntimeException(e);
}
} //连接数据库,返回Connection
public static Connection getConnection() {
try {
return DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
//将 编译异常 转为 运行异常,原因同上
throw new RuntimeException(e);
}
} //关闭相关资源
/**
* 1.ResultSet 结果集
* 2.Statement 或者 PreparedStatement
* 3.Connection
* 4.如果需要关闭资源,就传入对象,否则就传入null
*/
//这里用Statement作为参数接收,是因为Statement是PreparedStatement的父接口,
// 因此Statement参数既可以接收Statement的对象实现,也可以接收PreparedStatement类型的对象实现
public static void close(ResultSet set, Statement statement, Connection connection) {
//判断是否为null
try {
if (set != null) {
set.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
//将 编译异常 转为 运行异常,原因同上
throw new RuntimeException(e);
}
}
}

使用测试JDBCUtils_Use:

package li.jdbc.utils;

import org.junit.Test;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date; /**
* 该类演示如何使用JDBCUtils工具类,完成 dml和 select
*/
public class JDBCUtils_Use { @Test
public void testSelect() {//insert update delete
//1.得到连接
Connection connection = null; //2.组织一个sql语句
String sql = "Select * from actor"; //3.创建PreparedStatement对象
PreparedStatement preparedStatement = null;
ResultSet set = null;
try {
connection = JDBCUtils.getConnection();
preparedStatement = connection.prepareStatement(sql); //执行sql,得到结果集
set = preparedStatement.executeQuery();
//遍历该结果集
while (set.next()) {
int id = set.getInt("id");
String name = set.getString("name");
String sex = set.getString("sex");
Date borndate = set.getDate("borndate");
String phone = set.getString("phone");
System.out.println(id + "\t" + name + "\t" + sex + "\t" + borndate + "\t" + phone);
} } catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭资源
JDBCUtils.close(set, preparedStatement, connection);
}
} @Test
public void testDML() {//insert update delete
//1.得到连接
Connection connection = null; //2.组织一个sql语句
String sql = "update actor set name=? where id=?"; //3.创建PreparedStatement对象
PreparedStatement preparedStatement = null;
try {
connection = JDBCUtils.getConnection();
preparedStatement = connection.prepareStatement(sql);
//给占位符赋值
preparedStatement.setString(1, "周星星");//第1个占位符的值为周星星
preparedStatement.setInt(2, 1);//第2个占位符的值为1
//执行sql
preparedStatement.executeUpdate(); } catch (SQLException e) {
e.printStackTrace();
} finally {
//关闭资源
JDBCUtils.close(null, preparedStatement, connection);
}
}
}

运行结果:



day46-JDBC和连接池02的更多相关文章

  1. c3p0、dbcp、tomcat jdbc pool 连接池配置简介及常用数据库的driverClass和驱动包

    [-] DBCP连接池配置 dbcp jar包 c3p0连接池配置 c3p0 jar包 jdbc-pool连接池配置 jdbc-pool jar包 常用数据库的driverClass和jdbcUrl ...

  2. jdbc数据连接池dbcp要导入的jar包

    jdbc数据连接池dbcp要导入的jar包 只用导入commons-dbcp-x.y.z.jarcommons-pool-a.b.jar

  3. 关于JDBC和连接池我学到的(转载保存)

    1.JDBC数据库连接池的必要性 在使用开发基于数据库的web程序时,传统的模式基本是按以下步骤: 在主程序(如servlet.beans)中建立数据库连接. 进行sql操作 断开数据库连接. 这种模 ...

  4. JDBC之 连接池

    JDBC之 连接池 有这样的一种现象: 用java代码操作数据库,需要数据库连接对象,一个用户至少要用到一个连接.现在假设有成千上百万个用户,就要创建十分巨大数量的连接对象,这会使数据库承受极大的压力 ...

  5. JDBC数据源连接池(4)---自定义数据源连接池

    [续上文<JDBC数据源连接池(3)---Tomcat集成DBCP>] 我们已经 了解了DBCP,C3P0,以及Tomcat内置的数据源连接池,那么,这些数据源连接池是如何实现的呢?为了究 ...

  6. JDBC数据源连接池(3)---Tomcat集成DBCP

    此文续<JDBC数据源连接池(2)---C3P0>. Apache Tomcat作为一款JavaWeb服务器,内置了DBCP数据源连接池.在使用中,只要进行相应配置即可. 首先,确保Web ...

  7. JDBC数据源连接池(2)---C3P0

    我们接着<JDBC数据源连接池(1)---DBCP>继续介绍数据源连接池. 首先,在Web项目的WebContent--->WEB-INF--->lib文件夹中添加C3P0的j ...

  8. DBCP,C3P0与Tomcat jdbc pool 连接池的比较

    hibernate开发组推荐使用c3p0; spring开发组推荐使用dbcp(dbcp连接池有weblogic连接池同样的问题,就是强行关闭连接或数据库重启后,无法reconnect,告诉连接被重置 ...

  9. JDBC数据源连接池的配置和使用实例

    个人学习参考所用,勿喷! 使用JDBC建立数据库连接的两种方式: 1.在代码中使用DriverManager获得数据库连接.这种方式效率低,并且其性能.可靠性和稳定性随着用户访问量得增加逐渐下降. 2 ...

随机推荐

  1. Modbus转BACnet IP网关

    BACnet是楼宇自动化和控制网络数据通信协议的缩写.它是为楼宇自动化网络开发的数据通信协议   根据1999年底互联网上楼宇自动化网络的信息,全球已有数百家国际知名制造商支持BACnet,包括楼宇自 ...

  2. Bika LIMS 开源LIMS集—— SENAITE的使用(检测流程)

    客户管理 登记客户信息,包括地址.合同报告邮寄地址.账单邮寄地址.付款银行账号等. 产品批次管理 例如某乳品公司生产处一批产品,该批产品送往实验室检测,实验室登记该批产品批号,如对该批产品做多次检测, ...

  3. 开源一个自动整理B站UWP客户端软件进行批量下载的视频文件的小工具BiliVideosReoganizeHelper​

    ​ 大家都知道B站是一个很受欢迎的视频学习网站,上面有很多无私的up主上传了大量优秀的教学视频,在此向B站致敬,向广大UP主致敬. 有时,我们需要下载收藏一些视频,以防止以后找不到了.那么我们可以用B ...

  4. ABP中的数据过滤器

      本文首先介绍了ABP内置的软删除过滤器(ISoftDelete)和多租户过滤器(IMultiTenant),然后介绍了如何实现一个自定义过滤器,最后介绍了在软件开发过程中遇到的实际问题,同时给出了 ...

  5. 前端React项目遇到【Uncaught SyntaxError: Unexpected token '<'】错误的解决方式

    问题描述 前端部署好项目后,打开相应的页面显示一片空白,打开console显示 问题排查思路 理解问题的本质 出现这个错误的原因是浏览器期望得到js文件,但页面却返回了html文件,如图中的js文件点 ...

  6. 在Kubernetes上部署k6的详细步骤

    k6介绍 k6是一款使用go语言编写的开源测试工具,支持用户编写测试脚本,解决了JMeter不易代码化的缺点.它的主要特点有 提供了友好的 CLI 工具 使用 JavaScript 代码编写测试用例 ...

  7. 创新能力加速产业发展,SphereEx 荣获“中关村银行杯”『大数据与云计算』领域 TOP1

    8 月 9 日下午,2022 中关村国际前沿科技创新大赛"中关村银行杯"大数据与云计算领域决赛在北京市门头沟区中关村(京西)人工智能科技园·智能文创园落下了帷幕.SphereEx ...

  8. Flutter 检测报错 Unable to locate Android SDK.

    安装好 Flutter SDK 之后,官方建议使用flutter doctor检查 Flutter SDK 的相关配置信息. 如果 Android Studio 安装 Android SDK 的时候选 ...

  9. html弹出二选一窗口,然后根据点击执行对应的js方法

    html弹出二选一窗口,然后根据点击执行对应的js方法 layer.confirm("我是弹出来的字", {btn:['确认','取消']}, function(){ ...方法1 ...

  10. 基于SpringSecurity的@PreAuthorize实现自定义权限校验方法

    一.前言 在我们一般的web系统中必不可少的就是权限的配置,也有经典的RBAC权限模型,是基于角色的权限控制.这是目前最常被开发者使用也是相对易用.通用权限模型.当然SpringSecurity已经实 ...