如果使用JDBC来操作MySQL数据库
Posted IT_Holmes
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如果使用JDBC来操作MySQL数据库相关的知识,希望对你有一定的参考价值。
文章目录
本章是关于JDBC 的相关内容,模拟JDBC操作数据库。源码和jar包获取:https://gitee.com/it-sherlock/jdbc-source-code
1. 数据库驱动
一般分是三个部分,先是,调用JDBC这一部分;然后调用JDBC驱动;最后,访问数据库。
2. JDBC
SUN公司为了简化,开发人员的(对数据库的统一)操作,提供了一个(Java操作数据库)
这些规范的实现由具体的厂商去做。
对于开发人员来说,我们只需要掌握JDBC的操作就可以了。
JDBC驱动下载:https://mvnrepository.com/artifact/mysql/mysql-connector-java
3. 第一个 JDBC 程序
创建测试的数据库:
CREATE DATABASE jdbcStudy CHARACTER SET utf8 COLLATE utf8_general_ci;
USE jdbcStudy
CREATE TABLE users(
id INT PRIMARY KEY,
`name` VARCHAR(40),
`password` VARCHAR(40),
email VARCHAR(60),
birthday DATE
);
INSERT INTO users (id,`name`,`password`,email,birthday)
VALUES (1,'zhangsan','123456','zs@qq.com','1999-11-01'),(2,'lisi','123456','ls@qq.com','1229-11-01'),(3,'wangwu','123456','ww@qq.com','2009-11-01');
1. 创建一个项目。
2. 导入数据库驱动jar包。
3. 编写测试代码。
package com.zhangsan.demo01;
import java.sql.*;
// 我的第一个jdbc程序
public class JdbcFistDemo {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
// 1. 加载驱动
Class.forName("com.mysql.jdbc.Driver"); // 固定写法,加载驱动
// 2. 用户信息和url
// 三个参数:useUnicode=true&characterEncoding=utf8&useSSL=true
// useUnicode=true :支持中文编码
// characterEncoding=utf8 :设置字符集为utf8
// useSSL=true :使用安全的连接
String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
String username = "root";
String password = "123456";
// 3. 连接成功,数据库对象 这里的connection代表数据库
Connection connection = DriverManager.getConnection(url,username,password);
// 4. 执行sql的对象 Statement用来执行sql的
Statement statement = connection.createStatement();
// 5. 执行sql
String sql = "SELECT * FROM users";
// resultSet :返回的结果集,结果集中封装了我们全部的查询结果
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.println("id = " + resultSet.getObject("id"));
System.out.println("name = " + resultSet.getObject("name"));
System.out.println("pwd = " + resultSet.getObject("password"));
System.out.println("email = " + resultSet.getObject("email"));
System.out.println("birthday = " + resultSet.getObject("birthday"));
System.out.println("===============================================");
}
// 6. 释放连接(关闭连接)
// 关闭连接的顺序刚好是反着的
resultSet.close();
statement.close();
connection.close();
}
}
步骤总结:
- 1.加载驱动,Class.forName(“com.mysql.jdbc.Driver”);
- 2.连接数据库 DriverManager
- 3.获得执行sql的对象 Statement
- 4.获得返回的结果集 ResultSet
- 5.释放连接(关闭连接)
DriverManager:
// DriverManager.registerDriver(new com.mysql.jdbc.Driver());
Class.forName("com.mysql.jdbc.Driver"); // 固定写法,加载驱动
//其实上面的forName就是调用的DiverManager中的registerDriver,使用上推荐使用forName。
//它们两个功能都是一样的,加载驱动
// connection 代表的就是数据库。
Connection connection = DriverManager.getConnection(url,username,password);
// 前面在mysql中所说的事务回滚,事务提交,数据库设置为自动提交,都可以通过connection来操作。
connection.rollback();
connection.commit();
connection.setAutoCommit();
URL:
// 三个参数:useUnicode=true&characterEncoding=utf8&useSSL=true
// useUnicode=true :支持中文编码
// characterEncoding=utf8 :设置字符集为utf8
// useSSL=true :使用安全的连接
String url = "jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true";
//mysql 默认端口号:3306
//mysql的URL格式:
//jdbc:mysql://主机地址:端口号/数据库名?参数1&参数2&参数3
//oracle 默认端口号:1521
//oracle的URL格式:
//jdbc:oracle:thin:@localhost:1521:sid
//像jdbc:mysql 或者 jdbc.oracle 这些都是一种协议。
Statement执行SQL对象:(还有一个PrepareStatement 也是执行sql对象的)
String sql = "SELECT * FROM users"; // 编写sql
statement.executeQuery("sql语句"); //查询操作,返回resultSet。
statement.execute("sql语句"); //可以执行任何sql,它能执行任何sql就说明它会有一个判断形式,性能比其他语句低。
statement.executeUpdate("sql语句"); // 更新,插入,删除,都是用update操作。
statement.executeBatch("sql语句"); //可以存放多个sql语句,执行。
ResultSet 查询的结果集:封装了所有的查询结果
ResultSet resultSet = statement.executeQuery(sql);
resultSet.getObject("列名"); //在不知道列类型的情况下使用,getObject()
//如果知道列的类型就是用指定类型
resultSet.getString("列名");
resultSet.getInt("列名");
resultSet.getFloat("列名");
resultSet.getDate("列名");
...
ResultSet结果集的遍历,指针操作:
resultSet.beforeFirst(); // 移动到最前面
resultSet.afterLast(); // 移动到最后面
resultSet.next(); // 移动到下一个数据
resultSet.previous(); //移动到前一行
resultSet.absolute(row); //移动到指定行
释放资源:
resultSet.close();
statement.close();
connection.close();
// 一定要释放资源,用完关掉!不然占内存。
4. statement 对象
JDBC中的statement对象用于向数据库发送SQL语句,向完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。
- statement对象中的executeUpdate方法,用于向数据库发送增删改查的sql语句,它返回的是一个整数(即增删改语句导致了数据库几行数据发生了变化)。
- statement.executeQuery方法用于像数据库发送查询语句,它返回一个ResultSet对象数据集。
封装数据:
db.properties 文件:用来存储连接数据库的内容。
// db.properties文件:
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/jdbcstudy?useUnicode=true&characterEncoding=utf8&useSSL=true
username=root
password=123456
JdbcUtiles文件:获取db.properties文件内容,驱动加载,获取连接和释放连接操作。
// JdbcUtils文件:
package com.zhangsan.demo02.utils;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;
public class JdbcUtils {
private static String driver = null;
private static String url = null;
private static String username = null;
private static String password = null;
static {
try {
//获取db.properties的文件,因为在src下,因此不用链接地址。 这里会返回一个输入流
InputStream in = JdbcUtils.class.getClassLoader().getResourceAsStream("db.properties");
Properties properties = new Properties();
properties.load(in); // 读取字节流种的属性列表
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
//1. 驱动加载
Class.forName(driver);
}catch (Exception e){
e.printStackTrace();
}
}
// 获取连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url,username,password);
}
//释放连接资源
public static void release(Connection con, Statement st, ResultSet rs){
if (rs!=null){
try{
rs.close();
} catch (SQLException e){
e.printStackTrace();
}
}
if (st!=null){
try{
st.close();
} catch (SQLException e){
e.printStackTrace();
}
}
if (con!=null){
try{
con.close();
} catch (SQLException e){
e.printStackTrace();
}
}
}
}
操作sql语句的文件:增删改查。
//步骤都是一样,就是通过修改sql语句实现。注意是select查询语句有resultset返回集。
package com.zhangsan.demo02;
import com.zhangsan.demo02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class TestUpdate {
public static void main(String[] args) {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection(); // 获取数据库连接
st = conn.createStatement(); //获得sql的执行对象
String sql = "UPDATE users SET `name`='张三',`email`='无' WHERE id=3";
int i = st.executeUpdate(sql);
if (i>0){
System.out.println("更新成功|!!");
}
} catch(SQLException e){
e.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}
SQL注入的问题:
sql存在漏洞,会被攻击导致数据泄露,换句话说就是将SQL语句进行拼接。
package com.zhangsan.demo02;
import com.zhangsan.demo02.utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQL注入 {
public static void main(String[] args) {
//这样我们可以通过login链接数据库完成登录
//login("张三","123456");
//sql注入别的语句操作,这里通过拼接其他的sql语句即便没有密码用户,照样能获取数据库信息。
login("' or '1=1","' or '1=1");
}
// 登录业务
public static void login(String username,String password){
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
conn = JdbcUtils.getConnection(); // 获取数据库连接
st = conn.createStatement(); //获得sql的执行对象
String sql = "SELECT * FROM users WHERE `name` = '"+username+"' AND `password` = '"+password+"'";
rs = st.executeQuery(sql);
while (rs.next()){
System.out.println(rs.getString("name"));
System.out.println(rs.getString("password"));
System.out.println("===================================");
}
} catch(SQLException e){
e.printStackTrace();
} finally {
JdbcUtils.release(conn,st,rs);
}
}
}
5. PreparedStatement 对象
PreparedStatement 可以防止SQL注入,并且效率更高。
PreparedStatement是继承了Statement这个类。
依照上面sql注入,采用preparedstatement就可以有效的避免:
package com.zhangsan.demo02; import com.zhangsan.demo02.utils.JdbcUtils; import java.sql.*; public class SQL注入 { public static void main(String[] args) { //这样我们可以通过使用PreparedStatement就避免了SQL注入的问题。 //login("老铁","123456"); login("' or '1=1","' or '1=1"); } // 登录业务 public static void login(String username,String password){ Connection conn = null; PreparedStatement st = null; ResultSet rs = null; try { conn = JdbcUtils.getConnection(); String sql = "SELECT * FROM users WHERE `name` = ? AND `password` = ?"; // PreparedStatement 防止SQL注入的本质,把传递进来的参数当作字符。 // 假设其中存在转移字符,比如说: ' 会被直接转义。 st = conn.prepareStatement(sql); st.setString(1,username); st.setString(2,password); rs = st.executeQuery(); while (rs.next()){ System.out.println(rs.getString("name")); System.out.println(rs.getString("password")); System.out.println("==================================="); } } catch(SQLException e){ e.printStackTrace(); } finally { JdbcUtils.release(conn,st,rs); } } }
以上是关于如果使用JDBC来操作MySQL数据库的主要内容,如果未能解决你的问题,请参考以下文章关于mysql驱动版本报错解决,Cause: com.mysql.jdbc.exceptions.jdbc4Unknown system variable ‘query_cache_size(代码片段