1.JDBC概述

JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。是Java访问数据库的标准规范

JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。

JDBC需要连接驱动,驱动是两个设备要进行通信,满足一定通信数据格式,数据格式由设备提供商规定,设备提供商为设备提供驱动软件,通过软件可以与该设备进行通信。

2.JDBC原理

Java提供访问数据库规范称为JDBC,而生产厂商提供规范的实现类称为驱动。

JDBC是接口,驱动是接口的实现,没有驱动将无法完成数据库连接,从而不能操作数据库!每个数据库厂商都需要提供自己的驱动,用来连接自己公司的数据库,也就是说驱动一般都由数据库生成厂商提供。

3.案例数据准备

CREATE TABLE sort(
sid INT PRIMARY KEY AUTO_INCREMENT,
sname VARCHAR(100),
sprice DOUBLE,
sdesc VARCHAR(5000)
);
#初始化数据
INSERT INTO sort(sname,sprice,sdesc) VALUES('家电',2000,'优惠的促销'),
('家具',8900,'家具价格上调,原材料涨价'),
('儿童玩具',300,'赚家长钱'),
('生鲜',500.99,'生鲜商品'),
('服装',24000,'换季销售'),
('洗涤',50,'洗发水促销');

4.JDBC开发步骤

  1. 注册驱动.
  2. 获得连接.
  3. 获得语句执行平台
  4. 执行sql语句
  5. 处理结果
  6. 释放资源.

4.1导入驱动jar包

创建lib目录,用于存放当前项目需要的所有jar包

选择jar包,右键执行build path / Add to Build Path

4.2注册驱动

代码:Class.forName("com.mysql.jdbc.Driver");

JDBC规范定义驱动接口:java.sql.Driver,MySql驱动包提供了实现类:com.mysql.jdbc.Driver

DriverManager工具类,提供注册驱动的方法 registerDriver(),方法的参数是java.sql.Driver,所以我们可以通过如下语句进行注册:

DriverManager.registerDriver(new com.mysql.jdbc.Driver());

以上代码不推荐使用,存在两方面不足

  1. 硬编码,后期不易于程序扩展和维护
  2. 驱动被注册两次。

通常开发我们使用Class.forName() 加载一个使用字符串描述的驱动类。

如果使用Class.forName()将类加载到内存,该类的静态代码将自动执行。

通过查询com.mysql.jdbc.Driver源码,我们发现Driver类“主动”将自己进行注册

4.3获得链接

代码:Connection con = DriverManager.getConnection
(“jdbc:mysql://localhost:3306/mydb”,”root”,”123456”);

获取连接需要方法 DriverManager.getConnection(url,username,password),三个参数分别表示,url 需要连接数据库的位置(网址) user用户名  password 密码

4.4获得语句执行平台

String sql = "某SQL语句";

获取Statement语句执行平台:Statement stmt = con.createStatement();

常用方法:

  • int executeUpdate(String sql); --执行insert update delete语句.
  • ResultSet executeQuery(String sql); --执行select语句.
  • boolean execute(String sql); --执行select返回true 执行其他的语句返回false.

4.5处理结果集(执行insert、update、delete无需处理)

ResultSet实际上就是一张二维的表格,我们可以调用其boolean next()方法指向某行记录,当第一次调用next()方法时,便指向第一行记录的位置,这时就可以使用ResultSet提供的getXXX(int col)方法(与索引从0开始不同个,列从1开始)来获取指定列的数据:

  • rs.next();//指向第一行
  • rs.getInt(1);//获取第一行第一列的数据

常用方法:

  • Object getObject(int index) / Object getObject(String name) 获得任意对象
  • String getString(int index) / Object getObject(String name) 获得字符串
  • nt getInt(int index) / Object getObject(String name) 获得整形
  • double getDouble(int index) / Object getObject(String name) 获得双精度浮点型

4.6释放资源

与IO流一样,使用后的东西都需要关闭!关闭的顺序是先得到的后关闭,后得到的先关闭。

  • rs.close();
  • stmt.close();
  • con.close();
package cn.jxufe.java.chapter11.demo01;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement; /*JDBC操作数据库的步骤
* 1. 注册驱动.
* 告知JVM是哪一个的数据库的驱动
2. 获得连接.
使用JDBC中的类完成对MYSQL的连接
3. 获得语句执行平台
通过连接对象获取对SQL语句的执行者对象
4. 执行sql语句
使用执行这对象,向数据库执行SQL语句
获取到数据库的执行后的结果
5. 处理结果 6. 释放资源.
close()
*/
public class Test01JDBC { public static void main(String[] args) throws ClassNotFoundException, SQLException {
// TODO Auto-generated method stub
// 1.注册驱动 反射技术,将驱动类加入到内容
// 使用java.sql.DriverManager类静态方法 registerDriver(Driver driver)
// Diver是一个接口,参数传递,MySQL驱动程序中的实现类
// DriverManager.registerDriver(new Driver());
// 驱动类源代码,注册2次驱动程序
Class.forName("com.mysql.jdbc.Driver");
// 2.获得数据库连接 DriverManager类中静态方法
// static Connection getConnection(String url, String user, String password)
// 返回值是Connection接口的实现类,在mysql驱动程序
// url: 数据库地址 jdbc:mysql://连接主机IP:端口号/数据库名字
String url = "jdbc:mysql://localhost:3306/mydatabase";
String username = "root";
String password = "123456";
Connection con = DriverManager.getConnection(url, username, password);
// 3.获得语句执行平台, 通过数据库连接对象,获取到SQL语句的执行者对象
// con对象调用方法 Statement createStatement() 获取Statement对象,将SQL语句发送到数据库
// 返回值是 Statement接口的实现类对象,,在mysql驱动程序 Statement stat = con.createStatement();
// 4.执行sql语句
// 通过执行者对象调用方法执行SQL语句,获取结果
// int executeUpdate(String sql) 执行数据库中的SQL语句, insert delete update
// 返回值int,操作成功数据表多少行
int row = stat.executeUpdate("INSERT INTO sort(sname,sprice,sdesc) VALUES('汽车用品',50000,'疯狂涨价')");
System.out.println(row);
// 6.释放资源 一堆close()
stat.close();
con.close();
} }

package cn.jxufe.java.chapter11.demo01;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; /*
* JDBC技术,查询数据表,获取结果集
*/
public class Test02JDBC { public static void main(String[] args) throws ClassNotFoundException, SQLException {
// TODO Auto-generated method stub
// 1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2. 获取连接对象
String url = "jdbc:mysql://localhost:3306/mydatabase";
String username = "root";
String password = "123456";
Connection con = DriverManager.getConnection(url, username, password);
// 3 .获取执行SQL 语句对象
Statement stat = con.createStatement();
// 拼写查询的SQL
String sql = "SELECT * FROM sort";
// 4. 调用执行者对象方法,执行SQL语句获取结果集
// ResultSet executeQuery(String sql) 执行SQL语句中的select查询
// 返回值ResultSet接口的实现类对象,实现类在mysql驱动中
ResultSet rs = stat.executeQuery(sql);
// 5 .处理结果集
// ResultSet接口方法 boolean next() 返回true,有结果集,返回false没有结果集
while (rs.next()) {
// 获取每列数据,使用是ResultSet接口的方法 getXX方法参数中,建议写String列名
System.out.println(rs.getInt("sid") + " " + rs.getString("sname") + " " + rs.getDouble("sprice") + " "
+ rs.getString("sdesc"));
}
// 6.释放资源
rs.close();
stat.close();
con.close();
} }

5.注入攻击

CREATE TABLE users(
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(100),
PASSWORD VARCHAR(100)
); INSERT INTO users (username,PASSWORD) VALUES ('a',''),('b',''); SELECT * FROM users;

package cn.jxufe.java.chapter11.demo01;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner; /*
* Java程序实现用户登录,用户名和密码,数据库检查
* 演示被别人注入攻击
*/
public class Test03JDBC { public static void main(String[] args) throws ClassNotFoundException, SQLException {
// TODO Auto-generated method stub
// 1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2. 获取连接对象
String url = "jdbc:mysql://localhost:3306/mydatabase";
String username = "root";
String password = "123456";
Connection con = DriverManager.getConnection(url, username, password);
// 3 .获取执行SQL 语句对象
Statement stat = con.createStatement();
Scanner sc = new Scanner(System.in);
String user = sc.nextLine();
String pass = sc.nextLine(); // 执行SQL语句,数据表,查询用户名和密码,如果存在,登录成功,不存在登录失败
String sql = "SELECT * FROM users WHERE username='" + user + "' AND PASSWORD='" + pass + "'";
System.out.println(sql);
ResultSet rs = stat.executeQuery(sql);
while (rs.next()) {
System.out.println(rs.getString("username") + " " + rs.getString("password"));
} rs.close();
stat.close();
con.close();
} }

这就是注入攻击,别人密码不对,照样可以登录。

6.使用使用PrepareSatement防止注入攻击

package cn.jxufe.java.chapter11.demo01;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Scanner; /*
* Java程序实现用户登录,用户名和密码,数据库检查
* 防止注入攻击
* Statement接口实现类,作用执行SQL语句,返回结果集
* 有一个子接口PreparedStatement (SQL预编译存储,多次高效的执行SQL)
* PreparedStatement的实现类数据库的驱动中,如何获取接口的实现类
*
* 是Connection数据库连接对象的方法
* PreparedStatement prepareStatement(String sql)
*/
public class Test04JDBC { public static void main(String[] args) throws ClassNotFoundException, SQLException {
// TODO Auto-generated method stub
// 1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2. 获取连接对象
String url = "jdbc:mysql://localhost:3306/mydatabase";
String username = "root";
String password = "123456"; Connection con = DriverManager.getConnection(url, username, password);
Scanner sc = new Scanner(System.in);
String user = sc.nextLine();
String pass = sc.nextLine(); // 执行SQL语句,数据表,查询用户名和密码,如果存在,登录成功,不存在登录失败
String sql = "SELECT * FROM users WHERE username=? AND PASSWORD=?";
// 调用Connection接口的方法prepareStatement,获取PrepareStatement接口的实现类
// 方法中参数,SQL语句中的参数全部采用问号占位符
PreparedStatement pst = con.prepareStatement(sql);
// System.out.println(pst);
// 调用pst对象set方法,设置问号占位符上的参数
pst.setObject(1, user);
pst.setObject(2, pass); // 调用方法,执行SQL,获取结果集
ResultSet rs = pst.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("username") + " " + rs.getString("password"));
}
rs.close();
pst.close();
con.close();
} }

这种方式可以防止注入攻击

7.使用PrepareStatement接口,实现数据表的更新操作

package cn.jxufe.java.chapter11.demo02;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException; /*
* 使用PrepareStatement接口,实现数据表的更新操作
*/
public class Test01PreparedStatement { public static void main(String[] args) throws ClassNotFoundException, SQLException {
// TODO Auto-generated method stub
// 1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2. 获取连接对象
String url = "jdbc:mysql://localhost:3306/mydatabase";
String username = "root";
String password = "123456";
Connection con = DriverManager.getConnection(url, username, password); // 拼写修改的SQL语句,参数采用?占位
String sql = "UPDATE sort SET sname= ?,sprice=? WHERE sid=?";
// 调用数据库连接对象con的方法prepareStatement获取SQL语句的预编译对象
PreparedStatement pst = con.prepareStatement(sql);
// 调用pst的方法setXXX设置?占位
pst.setObject(1, "汽车美容");
pst.setObject(2, 49988);
pst.setObject(3, 7);
// 调用pst方法执行SQL语句
pst.executeUpdate();
pst.close();
con.close();
} }

8.使用PrepareStatement接口实现数据表的查询操作

package cn.jxufe.java.chapter11.demo02;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; public class Test02PrepareStatement { public static void main(String[] args) throws ClassNotFoundException, SQLException {
// TODO Auto-generated method stub
// 1. 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 2. 获取连接对象
String url = "jdbc:mysql://localhost:3306/mydatabase";
String username = "root";
String password = "123456";
Connection con = DriverManager.getConnection(url, username, password); String sql = "SELECT * FROM sort";
PreparedStatement pst = con.prepareStatement(sql);
// 调用pst对象的方法,执行查询语句,Select
ResultSet rs = pst.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("sid") + " " + rs.getString("sname") + " " + rs.getString("sprice") + " "
+ rs.getString("sdesc"));
}
rs.close();
pst.close();
con.close();
} }

9. 实现JDBC的工具类

package cn.jxufe.java.chapter11.jdbc_util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement; /*
* 实现JDBC的工具类
* 定义方法,直接返回数据库的连接对象
*
* 写关闭方法
*/
public class JDBCUtils {
private static Connection con; private JDBCUtils() {
} static {
try {
Class.forName("com.mysql.jdbc.Driver");
String url = "jdbc:mysql://localhost:3306/mydatabase";
String username = "root";
String password = "123456";
con = DriverManager.getConnection(url, username, password);
} catch (Exception ex) {
throw new RuntimeException(ex + "数据库连接失败");
}
} /*
* 定义静态方法,返回数据库的连接对象
*/
public static Connection getConnection() {
return con;
} public static void close(Connection con, Statement stat) { if (stat != null) {
try {
stat.close();
} catch (SQLException ex) {
}
} if (con != null) {
try {
con.close();
} catch (SQLException ex) {
}
} } public static void close(Connection con, Statement stat, ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException ex) {
}
} if (stat != null) {
try {
stat.close();
} catch (SQLException ex) {
}
} if (con != null) {
try {
con.close();
} catch (SQLException ex) {
}
} }
}
package cn.jxufe.java.chapter11.demo02;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; import cn.jxufe.java.chapter11.jdbc_util.JDBCUtils; public class Test03JDBCUtil { public static void main(String[] args) throws SQLException {
// TODO Auto-generated method stub
Connection con= JDBCUtils.getConnection();
PreparedStatement pst = con.prepareStatement("SELECT * FROM sort");
ResultSet rs = pst.executeQuery();
while(rs.next()){
System.out.println(rs.getString("sname"));
}
JDBCUtils.close(con, pst, rs);
} }

10.将数据库中的表数据存储到java对象

package cn.jxufe.java.chapter11.demo02;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List; import cn.jxufe.java.chapter11.jdbc_util.JDBCUtils; public class Test03JDBCUtil { public static void main(String[] args) throws SQLException {
// TODO Auto-generated method stub
Connection con = JDBCUtils.getConnection();
PreparedStatement pst = con.prepareStatement("SELECT * FROM sort");
ResultSet rs = pst.executeQuery();
// 创建集合对象
List<Sort> list = new ArrayList<>();
while (rs.next()) {
// 获取每列元素,封装到Sort对象中
Sort s = new Sort(rs.getInt("sid"), rs.getString("sname"), rs.getDouble("sprice"), rs.getString("sdesc"));
list.add(s);
}
JDBCUtils.close(con, pst, rs);
// 遍历list集合
for (Sort sort : list) {
System.out.println(sort);
}
} } class Sort {
private int sid;
private String sname;
private double sprice;
private String sdesc; public Sort(int sid, String sname, double sprice, String sdesc) {
this.sid = sid;
this.sname = sname;
this.sprice = sprice;
this.sdesc = sdesc;
} public int getSid() {
return sid;
} public void setSid(int sid) {
this.sid = sid;
} public String getSname() {
return sname;
} public void setSname(String sname) {
this.sname = sname;
} public double getSprice() {
return sprice;
} public void setSprice(double sprice) {
this.sprice = sprice;
} public String getSdesc() {
return sdesc;
} public void setSdesc(String sdesc) {
this.sdesc = sdesc;
} @Override
public String toString() {
return "Sort [sid=" + sid + ", sname=" + sname + ", sprice=" + sprice + ", sdesc=" + sdesc + "]";
} }

11.properties配置文件

11.1使用properties配置文件

开发中获得连接的4个参数(驱动、URL、用户名、密码)通常都存在配置文件中,方便后期维护,程序如果需要更换数据库,只需要修改配置文件即可。

通常情况下,我们习惯使用properties文件,此文件我们将做如下要求:

  1. 文件位置:任意,建议src下
  2. 文件名称:任意,扩展名为properties
  3. 文件内容:一行一组数据,格式是“key=value”.
  • key命名自定义,如果是多个单词,习惯使用点分隔。例如:jdbc.driver
  • value值不支持中文,如果需要使用非英文字符,将进行unicode转换。

11.2创建配置文件

在src根目录下新建一个mydatabase.properties文件,里面的内容如下:

driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydatabase
username=root
password=123456

11.3加载配置文件:Properties对象

对应properties文件处理,开发中也使用Properties对象进行。我们将采用加载properties文件获得流,然后使用Properties对象进行处理。

package cn.jxufe.java.chapter11.demo03;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties; /*
* 加载properties配置文件
* IO读取文件,键值对存储到集合
* 从集合中以键值对方式获取数据库的连接信息,完成数据库的连接
*/
public class Test01Properties { public static void main(String[] args) throws IOException, ClassNotFoundException, SQLException {
// TODO Auto-generated method stub
/*FileInputStream fis = new FileInputStream("src\\mydatabase.properties");
System.out.println(fis);*/ // 发布给用户的时候没有src文件夹,所以如何不使用src这个路径还可以找到这个文件呢?
// 使用类的加载器,是从bin目录下加载
InputStream in = Test01Properties.class.getClassLoader().getResourceAsStream("mydatabase.properties");
System.out.println(in);
Properties pro = new Properties();
pro.load(in);
// 获取集合中的键值对
String driverClass = pro.getProperty("driverClass");
String url = pro.getProperty("url");
String username = pro.getProperty("username");
String password = pro.getProperty("password");
Class.forName(driverClass);
Connection con = DriverManager.getConnection(url, username, password);
System.out.println(con);
} }

12.采用配置文件方式编写数据库连接的工具类,JDBC工具类

package cn.jxufe.java.chapter11.demo03;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties; public class Test02JDBCUtilsConfig {
public static void main(String[] args) {
Connection con = JDBCUtilsConfig.getConnection();
System.out.println(con);
}
} /*
* 编写数据库连接的工具类,JDBC工具类
* 获取连接对象采用读取配置文件方式
* 读取文件获取连接,执行一次,static{}
*/
class JDBCUtilsConfig {
private static Connection con;
private static String driverClass;
private static String url;
private static String username;
private static String password;
static {
try {
readConfig();
Class.forName(driverClass);
con = DriverManager.getConnection(url, username, password);
} catch (Exception ex) {
throw new RuntimeException("数据库连接失败");
}
} private static void readConfig() throws Exception {
InputStream in = JDBCUtilsConfig.class.getClassLoader().getResourceAsStream("mydatabase.properties");
Properties pro = new Properties();
pro.load(in);
driverClass = pro.getProperty("driverClass");
url = pro.getProperty("url");
username = pro.getProperty("username");
password = pro.getProperty("password");
} public static Connection getConnection() {
return con;
}
}

12JDBC的更多相关文章

  1. 【12-JDBC编程】

    JDBC编程 JDBC概述 •通过使用JDBC API,Java程序可以非常方便地操作各种主流数据库,这是使Java语言的巨大 魅力所在.而且由于Java语言的跨平台特性,所以使用JDBC API所编 ...

随机推荐

  1. [CSP-S模拟测试]:简单的序列(DP)

    题目描述 从前有个括号序列$s$,满足$|s|=m$.你需要统计括号序列对$(p,q)$的数量. 其中$(p,q)$满足$|p|+|s|+|q|=n$,且$p+s+q$是一个合法的括号序列. 输入格式 ...

  2. Java数据结构与算法(2):栈

    栈是一种线性表,特点在于它只能在一个位置上进行插入和删除,该位置是表的末端,叫做栈的顶(top).因此栈是后进先出的(FIFO).栈的基本操作有push.peek.pop. 栈的示意图 进栈和出栈都只 ...

  3. Vue点击切换Class变化,实现Active当前样式

    刚自学Vue不久,所以还不太熟,所以直接上代码. 一.先在data里增加一个变量,用来储存当前点击的元素 data() { return { activeClass: -1, // 0为默认选择第一个 ...

  4. Linux shell - 按时间和文件大小排序显示文件(ll)

    在工作中有这样的情况,需要显示所有的文件,按照时间先后或者文件大小先后排序显示 命令:ls 1.按时间排序显示文件 test@> ll -rt 2.按文件大小排序显示文件(文件大小单位:k,M) ...

  5. mysql-c++连接

    1.mysql-c++连接MySQL :: Download Connector/C++ https://dev.mysql.com/downloads/connector/cpp/ 1-1VS201 ...

  6. leetcode 40. 组合总和 II (python)

    给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的每个数字在每个组合中只能使用一次. ...

  7. 在centos7.4 nginx mysql php部署 thinkphp5.0 项目

    系统 centos7  环境 php 7.1.3 nignx 1.12.2 mysql 5.5.6 我是通过lnmp 集成环境安装 fastcgi.conf 末尾添加 vim fastcig.conf ...

  8. mysql5.7.23性能调优之innodb_buffer_pool_size

    前言 我的数据库版本是5.7.23,最近发现执行SQL越来越慢,一条SQL语句执行需要将近30s. 对于原因,查询资料, https://www.cnblogs.com/qwangxiao/p/892 ...

  9. C++边双缩点,Redundant Paths 分离的路径

    一道比较简单的 关于边双的题,个人感觉难度不大. 求出整个图的边双,根据边双的定义我们可以延伸出 边双的任两个点都有至少两种路径来互相抵达(因为其不存在割边) .不妨将每个边双缩成一个点,样例中的图便 ...

  10. C# 保留N位小数

    1.只要求保留N位不四舍五入 float   f   =   0.55555f;    int   i   =(int)(f   *   100);    f   =   (float)(i*1.0) ...