JDBC


JDBC介绍

Sun公司为了简化开发人员的(对数据库的统一)操作,提供了(Java操作数据库的)规范,俗称JDBC,这些规范的由具体由具体的厂商去做

对于开发人员来说,我们只需要掌握JDBC接口的操作即可

所需要的jar包

  • java.sql(默认有)
  • javax.sql(默认有)

    还需要导入数据库驱动包

java程序链接mySQL

注意! 增删改操作都需要提交事务

步骤:

  1. 加载驱动
  2. 登陆链接数据库对象
  3. 创建statement对象,用于执行sql语句 statement(清单)
  4. 执行sql语句
  5. 返回结果集,结果集中封装了我们查询的所有结果
  6. 释放链接
 // 1.加载驱动
Class.forName("com.mysql.jdbc.Driver");
//协议://主机:端口/数据库名?编码设置&使用安全的链接
String url = "url=jdbc:mysql://localhost:3306/db01?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=true";
String use = "root"; //用户名
String password = "123456"; //密码
//2.登陆链接数据库对象
Connection connection = DriverManager.getConnection(url, use, password);
//3.创建statement对象,用于执行sql语句 statement(清单)
Statement statement = connection.createStatement();
//4.执行sql语句
String sql = "SELECT * from class"; //sql语句
//5.返回结果集,结果集中封装了我们查询的所有结果
ResultSet resultSet = statement.executeQuery(sql); while (resultSet.next()){
System.out.println("classno:"+resultSet.getNString("classno"));
System.out.println("classname:"+resultSet.getNString("classname"));
System.out.println("department:"+resultSet.getNString("department"));
System.out.println("monitor(班长):"+resultSet.getNString("monitor(班长)"));
System.out.println("==========================================================");
}
//6.释放链接
resultSet.close();
statement.close();
connection.close();
}
}

几个重要对象

DirverManager 驱动管理

Class.forName("com.mysql.jdbc.Driver");
DriverManager.registerDriver(new Driver()); //这是Driver源码

URL 资源地址

//协议://主机:端口/数据库名?时区设置&编码设置&使用安全的链接
String url = "url=jdbc:mysql://localhost:3306/db01?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=true";

Connection 链接对象,操作数据库的对象

connection.commit();  //提交事务
connection.rollback(); //回滚事务
connection.setAutoCommit(); //自动提交事务 /* Statemen 清单,执行sql的对象 */
```java
statement.executeQuery("sql"); //执行查询,返回结果集
statement.executeUpdate("sql"); //执行更新(插入和删除也算更新),返回受影响的行数
statement.execute("sql"); //执行全部的sql语句

ResultSet:查询后的结果集

获取数据:

resultSet.getNString();
resultSet.getObject(); //不知道什么类型的情况下使用
resultSet.getInt();
resultSet.getDate();
resultSet.getFloat();

指针移动:

resultSet.next();
resultSet.previous();
resultSet.absolute();
resultSet.beforeFirst();
resultSet.afterLast();

关闭链接

resultSet.close();
statement.close();
connection.close();

SQL注入的问题

SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。

即:通过sql语句的漏洞来实现一些非法操作.

// 欲根据用户id来进行获取用户的其他信息,但是使用如下语句就会将所有用户的信息都查询到
select * from db01.user where (id =' 'or 1=1)"; --sql注入
PreparedStatement对象

可以防止sql注入,并且效率更高,如:在编辑sql语句时使用?代表占位符,并且预编译sql语句,随后在设置参数防止sql注入

常用方法:
preparedStatement.executeQuery();
preparedStatement.executeUpdate();
preparedStatement.setString(); //给参数传递字符串类型的值
preparedStatement.setInt(); //给参数传递 int 类型的值
preparedStatement.setDate(); //给参数传递 Date 类型的值
... 等等

例子:

//带参数的sql语句
String sql = "select * from db01.user where(id = ?)" ;
//预编译sql语句并且返回一个PreparedStatement对象
preparedStatement = con.prepareStatement(sql);
//给参数传递值(适当的使用对应类型的方法能提高效率)
preparedStatement.setString(1,id); //注意下标从1开始
//运行sql语句
resultSet = preparedStatement.executeQuery();

解藕,封装工具类

我们可以将配置信息编写成配置文件(xxx.properties),然后通过Properties类读取文件内容对应参数来配置信息

配置文件db.properties, 我们需要将此配置文件放入字节码的相同路径(maven项目的resources目录下)

# 驱动类名
driver=com.mysql.cj.jdbc.Driver
# //协议://主机:端口/数据库名?设置时区&编码设置&使用安全的链接协议
url=jdbc:mysql://localhost:3306/db01?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=true
user=root
password=123456

JdbcUtil类

package SQL_injection;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties; public class JdbcUtility {
// 初始化变量,并且避免作用域问题
static Properties properties = new Properties();
static Connection con = null;
static PreparedStatement preparedStatement = null;
static ResultSet resultSet = null;
static String username = null;
static String password = null; //初始化配置
static {
// 获取输入流, 通过此类的类加载器获取类加载路径,进而获取到配置文件的输入流
InputStream in = JdbcUtility.class.getClassLoader().getResourceAsStream("db.properties");
try {
// 通过properties对象加载配置文件的输入流
properties.load(in);
//相当于加载驱动Class.forName("com.mysql.jdbc.Driver"); 只不过是将配置文件的driver参数获取出来
JdbcUtility.class.forName(properties.getProperty("driver"));
} catch (Exception e) {
e.printStackTrace();
}
}
//使用配置文件内容信息链接数据库
public JdbcUtility(){
try {
//获取配置文件信息
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
// 根据参数链接数据库
con = DriverManager.getConnection(url,user,password);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
} //使用自定义的用户名和密码登陆数据库
public JdbcUtility(String username,String password){
try {
con = DriverManager.getConnection(properties.getProperty("url"), username, password);
} catch (SQLException throwables) {
throwables.printStackTrace();
}
} public boolean select(String id){
String sql = "select * from db01.user where(id = ?)" ; //执行查询语句
try {
preparedStatement = con.prepareStatement(sql);
preparedStatement.setString(1,id);
resultSet = preparedStatement.executeQuery();
if(!resultSet.next()) {
System.out.println("查询失败!");
return false;
}
} catch (SQLException throwables) {
throwables.printStackTrace();
}
return true;
} public void getResult(){
try {
do {
System.out.print("id:"+resultSet.getString(1)+"\t");
//System.out.println("password:"+resultSet.getString(0)+"\t");
System.out.print("name:"+resultSet.getString(3)+"\t");
System.out.print("sex:"+resultSet.getString(4)+"\t");
System.out.print("birthday:"+resultSet.getString(5)+"\t");
System.out.println();
}
while (resultSet.next());
}
catch (Exception e){
e.printStackTrace();
}
} public void insert(String id ,String name,String sex ){
String sql = "insert into db01.user (id,name,sex,birthday) " +
"values(?,?,?,?)" ;
try {
preparedStatement = con.prepareStatement(sql); preparedStatement.setString(1,id);
preparedStatement.setString(2,name);
preparedStatement.setString(3,sex);
Date date = new Date(new java.util.Date().getTime());
preparedStatement.setDate(4,date); int n = preparedStatement.executeUpdate();
if (n == 0) System.out.println("插入失败!");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
} //删除
public void delete(String id){
String sql = "delete from db01.user where(id = ?);" ;
try {
preparedStatement = con.prepareStatement(sql);
preparedStatement.setString(1,id);
if (preparedStatement.executeUpdate()==0) System.out.println("删除失败!");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
} public void update(String id,String columnname,String value){
String sql = "update db01.user set "+columnname +" = ? where (id = ? )" ;
try {
preparedStatement = con.prepareStatement(sql);
//preparedStatement.setString(1,columnname);
preparedStatement.setString(1,value);
preparedStatement.setString(2,id); if(preparedStatement.executeUpdate()==0) System.out.println("更新失败");
} catch (SQLException throwables) {
throwables.printStackTrace();
} } //关闭
public void close(){
try {
resultSet.close();
con.close();
preparedStatement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
} }

JDBC操作事务

注意! 增删改操作都需要提交事务

常用方法
connection.setAutoCommit(boolean flag); //设置事务是否自动提交,默认是提交的
connection.commit(); //提交事务
connection.rollback(); //回滚事务,一般不用设置,事务一般发送错误会自动回滚

下面代码是模拟一笔转账操作,A账户减少100元,B账户增加100元,两个sql操作为一个事务,同时执行成功或者失败(失败事务发生回滚)

 JdbcUtility jdbc = new JdbcUtility();
try {
//关闭自动提交事务
jdbc.con.setAutoCommit(false);
//进行一笔转账操作,其中update()方法,参数1代表付款或者收款人,参数2代表是否收款
jdbc.update("A",true);
jdbc.update("B",false);
//提交一笔转账事务
jdbc.con.commit(); } catch (SQLException throwables) {
try {
//实际上事务会自动回滚当出现错误时
jdbc.con.rollback();
} catch (SQLException e) {
e.printStackTrace();
}
throwables.printStackTrace();
}

MySQL JDBC常用知识,封装工具类,时区问题配置,SQL注入问题的更多相关文章

  1. MySQL JDBC事务处理、封装JDBC工具类

    MySQL数据库学习笔记(十)----JDBC事务处理.封装JDBC工具类 一.JDBC事务处理: 我们已经知道,事务的概念即:所有的操作要么同时成功,要么同时失败.在MySQL中提供了Commit. ...

  2. 一、JDBC的概述 二、通过JDBC实现对数据的CRUD操作 三、封装JDBC访问数据的工具类 四、通过JDBC实现登陆和注册 五、防止SQL注入

    一.JDBC的概述###<1>概念 JDBC:java database connection ,java数据库连接技术 是java内部提供的一套操作数据库的接口(面向接口编程),实现对数 ...

  3. JAVA之旅(五)——this,static,关键字,main函数,封装工具类,生成javadoc说明书,静态代码块

    JAVA之旅(五)--this,static,关键字,main函数,封装工具类,生成javadoc说明书,静态代码块 周末收获颇多,继续学习 一.this关键字 用于区分局部变量和成员变量同名的情况 ...

  4. Android OkHttp网络连接封装工具类

    package com.lidong.demo.utils; import android.os.Handler; import android.os.Looper; import com.googl ...

  5. 常用的Java工具类——十六种

    常用的Java工具类——十六种 在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类.以下工具类.方法按使用流行度排名,参考数据来源于Github上随机选 ...

  6. 泛型(二)封装工具类CommonUtils-把一个Map转换成指定类型的javabean对象

    1.commons-beanutils的使用 commons-beanutils-1.9.3.jar 依赖 commons-logging-1.2.jar 代码1: String className ...

  7. SpringMVC:com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: You have an error in your SQL syntax;

    今天用SpringMVC做修改添加操作,之前的操作都实现了添加修改,但始终报com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: You have ...

  8. 创建Jdbc封装工具类

    jdbc.propertie url=jdbc:mysql:///empye user=root password=root driver=com.mysql.jdbc.Driver 读取资源文件  ...

  9. Android 开源控件与常用开发框架开发工具类

    Android的加载动画AVLoadingIndicatorView 项目地址: https://github.com/81813780/AVLoadingIndicatorView 首先,在 bui ...

随机推荐

  1. Centos下Ambari2.7.5的编译和安装

    前言 终于,要开始写点大数据相关的文章了.当真的要开始写老本行的时候,还是考虑了挺久的.一是不知道从何处写起,二是如何能写点有意思的. 我们常说,过程比结果重要.也是有很多人喜欢准备完全之后,才会开始 ...

  2. 使用第三方插件pagination在页面实现分页功能

    1.导入相应的js和css文件 2.在相应的页面映入pagination.js和pagination.css 3.将页面的分页代码替换为pagination动态生成的分页代码 4.编写js代码

  3. 【程序员的实用工具推荐】 Mac 效率神器 Alfred

    Alfred 是一款功能非常强大,能有效提升 Mac 电脑使用效率的神器.可以说有了 Alfred 你就基本上可以脱离鼠标实现各种操作.相比 Mac 自带的聚焦搜索,完全可以称得上拥有碾压性的优势. ...

  4. 为什么我建议在复杂但是性能关键的表上所有查询都加上 force index

    最近,又遇到了慢 SQL,简单的看了下,又是因为 MySQL 本身优化器还有查询计划估计不准的问题.SQL 如下: select * from t_pay_record WHERE (( user_i ...

  5. 一个命令让redis服务端所有信息无所遁形~(收藏吃灰系列)

    1.info命令作用 在redis客户端执行INFO 命令以便于计算机解析和人工阅读的简单格式返回有关redis服务端的所有信息和统计数据. 可选参数可用于选择特定的信息部分: Server 服务器基 ...

  6. Bugku--web-wp

    Bugku地址:https://ctf.bugku.com/challenges 0x01 web2 地址:http://123.206.87.240:8002/web2/ ,查看源码 web2 0x ...

  7. 使用已有流量进行RFC2544测试—信而泰网络测试仪实操

    一.测试说明 先创建流量,将流量运行起来,流量正常.再使用创建的流量进行RFC2544测试,可以避免因为配置原因流量不通,影响RFC 2544测试. 而且创建流量的时候,可以编辑报文,例如增加TCP/ ...

  8. C++ 派生类函数重载与虚函数继承详解

    目录 一.作用域与名字查找 1.作用域的嵌套 2.在编译时进行名字查找 3.名字冲突与继承 4.通过作用域运算符来使用隐藏的成员 二.同名函数隐藏与虚函数覆盖 1.几种必须区分的情况 2.一个更复杂的 ...

  9. 走进第四范式:决策类AI企业的生存之道

    根据不同的应用领域,人工智能行业可以分为视觉类人工智能.语音及语义类人工智能和决策类人工智能. 通常,我们接触的都是视觉类.语音类的人工智能,它们主要用来帮助人类执行具体任务,例如人脸识别,语音控制等 ...

  10. html续篇及初识爬虫

    今日内容概要 form表单 requests模块 可以模拟浏览器朝服务端发送各式各样的请求 cookie与session requests模块小案例(网站的基本防爬措施) 今日内容详细 form表单 ...