1.数据库驱动
想一下我们之前是怎么操作数据库,是不是使用SQL语句对其mysql数据库管理系统,然后管理系统在进行数据库(硬盘文件里面的)进行操作。那么我现在想使用应用程序对其数据库进行操作,应该怎么办呢?
那么数据库驱动就是搭建在应用程序和数据库之间的桥梁!!!
2.JDBC
根据上面的图可以知道,不同的数据库就需要使用不同的数据库驱动进行操作,适合麻烦的,在java上面就需要使用不同的数据库驱动,是很不方便的!
sun公司为了简化开发人员对于数据库的操作,提供了(java操作数据库的)规范,俗称JDBC(java database conection顾名思义就是java与数据库的连接)
2.1JDBC下载
我使用的mysql版本是8.0,因此我需要下相关的java-connector 8.0.28相对来说稳定一点!
JDBC下载
2.2JDBC的第一个代码测试
2.2.1前期工作:
首先我们需要对其进行jar的导入,导入依赖,(先创建一个lib目录,然后添加进去就行!注意需要对lib右键里面的 add as library)
2.2.2开始编写代码:
数据库里面的表:
java里面的代码:
package com.xcl.test;
import java.sql.*;
public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.添加驱动(固定写法,加载驱动)
Class.forName("com.mysql.cj.jdbc.Driver");
//2.用户信息和url
//useUnicode=true(表示中文有效) &characterEncoding=utf8(编码要求) && useSSL=true(一些其他错误的警告)
String url = "jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&&useSSL=true";
String username = "root";
String password = "123456";
//3.连接成功,数据库对象(拿到了数据库对象,现在就可以对其进行操作数据库对象,connection就代表数据库)
Connection connection = DriverManager.getConnection(url, username, password);
//4.执行SQL对象
Statement statement = connection.createStatement();
//5.执行SQL对象去执行SQL,查看返回结果
//SQL语句
String sql = "select * from student";
//执行结果
ResultSet resultSet = statement.executeQuery(sql);
while (resultSet.next()){
System.out.print("id=" + resultSet.getObject("id"));
System.out.print("name=" + resultSet.getObject("name"));
System.out.print("password=" + resultSet.getObject("password"));
System.out.print("sex=" + resultSet.getObject("sex"));
System.out.print("birthday=" + resultSet.getObject("birthday"));
System.out.print("address=" + resultSet.getObject("address"));
System.out.print("email=" + resultSet.getObject("email"));
}
//6.释放连接
resultSet.close();
statement.close();
connection.close();
}
}
分析一下:
2.2.3步骤:
1.注册驱动DriverManager
2.用户信息(用户名、密码)和url
url:
"jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&&useSSL=true"
格式:协议://主机地址:端口号/数据库名?参数1&参数2
3.获取数据库驱动对象,connection代表数据库,那就拥有数据的权利,(数据库设置自动提交
事务提交、事务回滚)
Connection connection = DriverManager.getConnection(url, username, password);
connection.commit();
connection.rollback();
connection.setAutoCommit(true);
4.具体sql执行类,上面我们有了数据库需要对于表进行操作还需要一个执行sql语句的类对象
Statement statement = connection.createStatement();
然后就使用sql语句对其进行增删改查
Statement statement = connection.createStatement();
statement.execute(); // 执行任何sql语句
statement.executeUpdate(); //更新、插入、删除都是这个,显示的结果是受到影响的行数
statement.executeQuery(); //查询操作返回的ResultSet
=======================================================================
3.JDBC的抽取
根据上面我们可以知道对于驱动和连接,以及释放资源都是固定,我们需要进行改变的就是statement对其进行增删改查(CURD),因此我们需要对其进行提取工具类以及重点介绍一下statement的操作!!!
3.1.首先我想对于文件的,我想避免耦合,因此我想写一个配置文件对其进行提取(写在一个.properties文件)
driver=com.mysql.cj.jdbc.Driver url=jdbc:mysql://localhost:3306/school?useUnicode=true&characterEncoding=utf8&&useSSL=true username=root password=123456
3.2.上面是完成了一些文件的修改,我还行进一步简化就是我想创建一个工具类JDBCUnity
package com.xcl.test.Utils;
import java.io.FileReader;
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 {
//1.propertise集合类
Properties properties = new Properties();
//加载这个文件
properties.load(new FileReader("D:\\javaLearn\\JDBC\\src\\dataBase.properties"));
//开始获取文件里面的内容
driver = properties.getProperty("driver");
url = properties.getProperty("url");
username = properties.getProperty("username");
password = properties.getProperty("password");
//然后就开始体现工具类里面的东西
Class.forName("driver");
} catch (Exception e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(url, username, password);
}
//释放资源
public static void close(Statement statement,Connection connection){//释放资源
if (statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
public static void close(ResultSet resultSet,Statement statement,Connection connection){//释放资源
if (resultSet!=null){
try {
resultSet.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (statement!=null){
try {
statement.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (connection!=null){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
3.3.那么我就简单进行测试一下(进行增删改查)
package com.xcl.test;
import com.xcl.test.Utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo02 {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet results = null;
try {
//获得连接
connection = JdbcUtils.getConnection();
//常见sql对象
statement = connection.createStatement();
//开始增删改查
//添加
// String sqlAdd = "insert into student value ('12', '张三', '123456', '男', '1999-01-01', '北京', '123456@qq.com')";
// int i = statement.executeUpdate(sqlAdd);
// if (i > 0){
// System.out.println("添加成功");
// }
//删除
// String sqlDelete = "delete from student where id = '12'";
// int i = statement.executeUpdate(sqlDelete);
// if (i > 0){
// System.out.println("删除成功");
// }
//修改
// String sqlUpdate = "update student set name = '李四' where id = '11'";
// int i = statement.executeUpdate(sqlUpdate);
// if (i > 0){
// System.out.println("修改成功");
// }
//
// //查询
String sqlQuery = "select * from student";
results = statement.executeQuery(sqlQuery);
while (results.next()){
System.out.print("id=" + results.getObject("id"));
System.out.print("name=" + results.getObject("name"));
System.out.print("password=" + results.getObject("password"));
System.out.print("sex=" + results.getObject("sex"));
System.out.print("birthday=" + results.getObject("birthday"));
System.out.print("address=" + results.getObject("address"));
System.out.print("email=" + results.getObject("email"));
System.out.println();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
JdbcUtils.close(statement,connection);
}
}
}
4.SQL注入
SQL存在漏洞,会被攻击导致数据泄露。SQL会被拼接or,使得你查询语句where判断一直变成true,就可以盗取!!!
package com.xcl.test;
import com.xcl.test.Utils.JdbcUtils;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SQLError {
//SQL注入
public static void main(String[] args) {
login("' or '1=1","' or '1=1");
// login("赵六","123456");
}
private static void login(String userName,String password) {
Connection connection = null;
Statement statement = null;
ResultSet results = null;
try {
//获得连接
connection = JdbcUtils.getConnection();
//常见sql对象
statement = connection.createStatement();
//查询
String sqlQuery = "select * from student where name='"+userName+"' and password='"+password+"'";
results = statement.executeQuery(sqlQuery);
while (results.next()){
System.out.print("id=" + results.getObject("id"));
System.out.print("name=" + results.getObject("name"));
System.out.print("password=" + results.getObject("password"));
System.out.print("sex=" + results.getObject("sex"));
System.out.print("birthday=" + results.getObject("birthday"));
System.out.print("address=" + results.getObject("address"));
System.out.print("email=" + results.getObject("email"));
System.out.println();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
JdbcUtils.close(statement,connection);
}
}
}
因此我们就需要更好的对象去先预处理这个东西
(主要就是进行预编译,里面输入的参数还用?先先代替就行)
步骤:
1.先用问号代替
2.然后进行填充
代码展示:
package com.xcl.test;
import com.xcl.test.Utils.JdbcUtils;
import java.sql.*;
public class SQLError {
//SQL注入
public static void main(String[] args) {
// login("' or '1=1","' or '1=1");
login("赵六","123456");
}
private static void login(String userName,String password) {
Connection connection = null;
Statement statement = null;
ResultSet results = null;
try {
//获得连接
connection = JdbcUtils.getConnection();
//常见sql对象
// statement = connection.createStatement();
//查询
String sqlQuery = "select * from student where name= ? and password= ?";
PreparedStatement preparedStatement = connection.prepareStatement(sqlQuery);
preparedStatement.setString(1,userName);
preparedStatement.setString(2,password);
results = preparedStatement.executeQuery();
while (results.next()){
System.out.print("id=" + results.getObject("id"));
System.out.print("name=" + results.getObject("name"));
System.out.print("password=" + results.getObject("password"));
System.out.print("sex=" + results.getObject("sex"));
System.out.print("birthday=" + results.getObject("birthday"));
System.out.print("address=" + results.getObject("address"));
System.out.print("email=" + results.getObject("email"));
System.out.println();
}
} catch (SQLException e) {
throw new RuntimeException(e);
}finally {
JdbcUtils.close(statement,connection);
}
}
}
5.事务(在java里面表现事务)【这不是完整代码,里面还有工具类和数据库,只是给大家一个思路!】
package com.xcl.test;
import com.xcl.test.Utils.JdbcUtils;
import java.sql.*;
public class TransactionDemo {
public static void main(String[] args) {
Connection con = null;
PreparedStatement ps = null;
ResultSet resultSet = null;
try {
//连接
con = JdbcUtils.getConnection();
//关闭自动提交,之后不需要开启因为会自动开启事务
con.setAutoCommit(false);
//进行转账的修改
String sql_A = "update account set money = money - 200 where name = 'A'";
ps = con.prepareStatement(sql_A);
ps.executeUpdate();
String sql_B = "update account set money = money + 200 where name = 'B'";
ps = con.prepareStatement(sql_B);
ps.executeUpdate();
//提交事务
con.commit();
System.out.println("转账成功!");
} catch (SQLException e) {
//失败后进行回滚
try {
con.rollback();
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
throw new RuntimeException(e);
}finally {
JdbcUtils.close(resultSet,ps,con);
}
}
}