【JDBC】基础知识整理

本文详细介绍了Java数据库连接JDBC的六步编程,包括注册驱动、获取连接、操作数据库等,并通过代码示例展示了Statement和PreparedStatement的使用。同时,讨论了SQL注入的安全隐患,解释了其根本原因,并提出了使用PreparedStatement来防止SQL注入的问题。最后,通过示例代码演示了PreparedStatement如何避免SQL注入风险。
摘要由CSDN通过智能技术生成

1.jdbc

Java DataBase Connectivity(java语言连接数据库)
jdbc是sun公司定义的一套接口,本质是一套接口

在这里插入图片描述
如果采用文本编辑器方式进行开发,需要配置到环境变量classpath当中
D:\mysql-connector-java-5.1.23\mysql-connector-java-5.1.23\mysql-connector-java-5.1.23-bin.jar
如果classpath本身没有需要新建,同时输入
.;D:\mysql-connector-java-5.1.23\mysql-connector-java-5.1.23\mysql-connector-java-5.1.23-bin.jar
注意:.;必须有

如果采用IDEA进行开发,则其本身有配置方式

2.jdbc编程六步


第一步:注册驱动(告诉java程序,即将要连接的哪个品牌的数据库)
第二步:获取连接(表示jvm的进程和数据库进程之间的通道打开了,这属于进程之间的通信,重量级的,使用完之后一定要关闭)
第三步:获取数据库操作对象(专门执行sql语句的对象)
第四步:执行sql语句(DQL.DML、、、)
第五步:处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集)
第六步:释放资源(使用完资源后一定要关闭资源,java和数据库属于进程间的通信,开启之后一定要关闭)
在这里插入图片描述

3.sql注入


以前存在的一个安全隐患,黑客经常使用
即假如用户名:a,如果密码:a’ or ‘1’=‘1’,无论如何都会成功登陆


sql注入问题可参考视频:

JDBC从入门到精通视频教程-JDBC实战精讲


导致sql注入的根本原因是什么?
用户输入的信息中含有sql语句的关键字,并且这些关键字参与sql语句的编译过程,
导致sql 语句的原意被扭曲,进而达到sql注入。

解决sql注入问题?
只要用户提供的信息不参与sql语句的编译过程,问题就解决了。
即使用户提供的信息中含有sql语句的关键字,但是没有参与编译,不起作用
要想用户信息不参与sql语句的编译,那么必须使用java.sql.PreparedStatement
PreparedStatement接口继承了java.sql.Statement
PreparedStatement是属于预编译的数据库操作对象
PreparedStatement的原理是:预先对sql语句的框架进行编译,然后再给sql语句传值

解决sql注入关键是什么?
用户提供的信息中即使含有sql语句的关键字,但是这些关键字并没有参与编译,不起作用


sql注入解决可参考视频

JDBC从入门到精通视频教程-JDBC实战精讲


对比一下statement和preparedstatement?
statement存在sql注入问题,preparedstatement解决了sql注入问题
statement是编译一次执行一次,preparedstatement是编译一次,可执行n次。preparedstatement的效率较高一些
preparedstatement会在编译阶段做类型的安全检查,比如输入的是字符串还是int类型等等
综上:preparedstatement使用较多,只有较少数情况下需要使用statement

什么情况下必须使用statement呢?
业务方面要求必须支持sql注入的时候;
statement支持sql注入,凡是业务方面要求是需要进行sql语句拼接的,必须使用statement。

JDBC1–没有使用资源绑定

/*
	JDBC编程六步
*/
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.Statement;

public class JDBC1{
	public static void main(String[] args){


		Connection conn=null;
		Statement stmt=null;
		try{
			//1.注册驱动
			//第一种方式
			//Driver driver =new com.mysql.jdbc.Driver();//多态,父类型引用指向子类型对象
			//DriverManager.registerDriver(driver);
			//第二种方式(常用,采用反射机制)
			//为什么常用?因为参数是一个字符串,字符串可以写到***.properties文件中
			//以下方法不需要接受返回值,因为我们只想用他的类加载动作
			String driver="com.mysql.jdbc.Driver";
			Class.forName(driver);

			//2.获取连接
			/*
				url:统一资源定位符(网络中某个资源的绝对路径)
					http://www.baidu.com/就是url
				url包括哪些内容?
					协议
					ip
					port(端口)
					资源名

				http://180.101.49.12:80/index.html
					http:// --通讯协议
					180.101.49.12--服务器ip地址--cmd 中ping www.baidu.com 获取
					80 服务器上软件的端口
					index.html 是服务器上某个资源名

				jdbc:mysql://127.0.0.1:3306/qc
					jdbc:mysql:// 协议
					127.0.0.1 ip地址
					3306 mysql数据库端口号
					qc 具体数据库实例名

				说明:127.0.0.1和localhost都是本机ip地址

				什么是通信协议,有什么用?
					通信协议是通信之前就提前定好的数据传送格式。
					数据包具体怎么传数据,格式提前定好的

			*/
			String url="jdbc:mysql://127.0.0.1:3306/qc";
			String user="root";
			String password="";
			conn=DriverManager.getConnection(url,user,password);
			System.out.println("数据库连接对象="+conn);

			//3.获取数据库操作对象(Statement专门执行sql语句的)
			stmt=conn.createStatement();

			//4.执行sql
			String sql="INSERT INTO `test_sht`( `data5`, `deal_num`) VALUES( 2, 2)";
			//专门执行DML语句的(insert delete update)
			//返回值是“影响数据库中的记录条数"
			int count=stmt.executeUpdate(sql);
			System.out.println(count == 1 ?"保存成功":"保存失败");
			//5.处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集)
			

		}catch(SQLException e){
			e.printStackTrace();
		}
		catch(ClassNotFoundException e){
			e.printStackTrace();
		}finally{
			//6.释放资源
			//为了保证资源一定释放,在finally语句块中关闭资源
			//并且要遵循从小到大依次关闭,比如应该先关闭stmt,在关闭conn
			//分别对其try..catch
			try{
				if(stmt !=null){
					stmt.close();
				}
			}catch(SQLException e){
				e.printStackTrace();
			}
			try{
				if(conn !=null){
					conn.close();
					}
			}catch(SQLException e){
				e.printStackTrace();
			}

		}
	}
}

JDBC2–没有使用选择语句

/*
	JDBC编程六步
*/
import java.sql.*;
import java.util.*;

public class JDBC2{
	public static void main(String[] args){

		//使用资源绑定器绑定属性配置文件
		ResourceBundle bundle=ResourceBundle.getBundle("jdbc");
		String driver=bundle.getString("driver");
		String url=bundle.getString("url");
		String user=bundle.getString("user");
		String password=bundle.getString("password");

		Connection conn=null;
		Statement stmt=null;
		try{
			//1.注册驱动
			Class.forName(driver);

			//2.获取连接
			conn=DriverManager.getConnection(url,user,password);
			System.out.println("数据库连接对象="+conn);

			//3.获取数据库操作对象(Statement专门执行sql语句的)
			stmt=conn.createStatement();

			//4.执行sql
			String sql="INSERT INTO `test_sht`( `data5`, `deal_num`) VALUES( 2, 2)";
			//专门执行DML语句的(insert delete update)
			//返回值是“影响数据库中的记录条数"
			int count=stmt.executeUpdate(sql);
			System.out.println(count == 1 ?"保存成功":"保存失败");
			//5.处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集)
			

		}catch(Exception e){
			e.printStackTrace();
		}finally{
			//6.释放资源
			//为了保证资源一定释放,在finally语句块中关闭资源
			//并且要遵循从小到大依次关闭,比如应该先关闭stmt,在关闭conn
			//分别对其try..catch
			try{
				if(stmt !=null){
					stmt.close();
				}
			}catch(SQLException e){
				e.printStackTrace();
			}
			try{
				if(conn !=null){
					conn.close();
					}
			}catch(SQLException e){
				e.printStackTrace();
			}

		}
	}
}


JDBC3–选择语句的使用

/*
	处理查询结果集
*/
import java.sql.*;
import java.util.*;

public class JDBC3{
	public static void main(String[] args){

		//使用资源绑定器绑定属性配置文件
		ResourceBundle bundle=ResourceBundle.getBundle("jdbc");
		String driver=bundle.getString("driver");
		String url=bundle.getString("url");
		String user=bundle.getString("user");
		String password=bundle.getString("password");

		Connection conn=null;
		Statement stmt=null;
		ResultSet rs=null;
		try{
			//1.注册驱动
			Class.forName(driver);

			//2.获取连接
			conn=DriverManager.getConnection(url,user,password);
			System.out.println("数据库连接对象="+conn);

			//3.获取数据库操作对象(Statement专门执行sql语句的)
			stmt=conn.createStatement();

			//4.执行sql
			String sql="SELECT `id`, `data5`, `deal_num` as a FROM `test_sht` WHERE 1";
			//int executeUpdate(insert/delete/update)
			//ResultSet executeQuery(select)
			rs=stmt.executeQuery(sql);//专门执行DQL语句的方法
			//5.处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集)
			/*boolean flag1=rs.next();
			if(flag1){
				//光标指向行有数据
				//此处getString()方法的特点是:不管数据库中的数据类型是什么,都以String的形式取出
				String column1=rs.getString(1);//jdbc中所有下标从1开始,不是从0开始
				String column2=rs.getString(2);
				String column3=rs.getString(3);
				System.out.println(column1+"+"+column2+"+"+column3);
				

			}*/
			while(rs.next()){
				String column1=rs.getString(1);//jdbc中所有下标从1开始,不是从0开始
				String column2=rs.getString("data5");
				String column3=rs.getString("a");//别名后不能是deal_num
				System.out.println(column1+"+"+column2+"+"+column3+"\n");
			}

		}catch(Exception e){
			e.printStackTrace();
		}finally{
			//6.释放资源
			//为了保证资源一定释放,在finally语句块中关闭资源
			//并且要遵循从小到大依次关闭,比如应该先关闭stmt,在关闭conn
			//分别对其try..catch
			try{
				if(rs !=null){
					rs.close();
				}
			}catch(Exception e){
				e.printStackTrace();
			}
			try{
				if(stmt !=null){
					stmt.close();
				}
			}catch(Exception e){
				e.printStackTrace();
			}
			try{
				if(conn !=null){
					conn.close();
					}
			}catch(Exception e){
				e.printStackTrace();
			}

		}
	}
}

–使用statement

import java.sql.*;

public class JDBC {
    /*public static void update(String id,String data5,String deal_num){

        Connection conn=null;
        //Statement stmt=null;
        PreparedStatement ps=null;
        try{
            //1.注册驱动
            //第一种方式
            //Driver driver =new com.mysql.jdbc.Driver();//多态,父类型引用指向子类型对象
            //DriverManager.registerDriver(driver);
            //第二种方式(常用,采用反射机制)
            //为什么常用?因为参数是一个字符串,字符串可以写到***.properties文件中
            //以下方法不需要接受返回值,因为我们只想用他的类加载动作
            String driver="com.mysql.jdbc.Driver";
            Class.forName(driver);

            //2.获取连接
			*//*
				url:统一资源定位符(网络中某个资源的绝对路径)
					http://www.baidu.com/就是url
				url包括哪些内容?
					协议
					ip
					port(端口)
					资源名

				http://180.101.49.12:80/index.html
					http:// --通讯协议
					180.101.49.12--服务器ip地址--cmd 中ping www.baidu.com 获取
					80 服务器上软件的端口
					index.html 是服务器上某个资源名

				jdbc:mysql://127.0.0.1:3306/qc
					jdbc:mysql:// 协议
					127.0.0.1 ip地址
					3306 mysql数据库端口号
					qc 具体数据库实例名

				说明:127.0.0.1和localhost都是本机ip地址

				什么是通信协议,有什么用?
					通信协议是通信之前就提前定好的数据传送格式。
					数据包具体怎么传数据,格式提前定好的

			*//*
            String url="jdbc:mysql://127.0.0.1:3306/qc";
            String user="root";
            String password="";
            conn= DriverManager.getConnection(url,user,password);
            //System.out.println("数据库连接对象="+conn);

            //3.获取数据库操作对象(Statement专门执行sql语句的)
            //stmt=conn.createStatement();

            int data5i=Integer.parseInt(data5);
            int deal_numi=Integer.parseInt(deal_num);

            //4.执行sql
            String sql="INSERT INTO `test_sht`( `data5`, `deal_num`) VALUES(?,?)";
            ps= conn.prepareStatement(sql);
            ps.setInt(1,data5i);
            ps.setInt(2,deal_numi);
            //专门执行DML语句的(insert delete update)
            //返回值是“影响数据库中的记录条数"
            ps.execute();
//            int count=ps.executeUpdate(sql);
//            System.out.println(count == 1 ?"保存成功":"保存失败");
            //5.处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集)


        }catch(SQLException e){
            e.printStackTrace();
        }
        catch(ClassNotFoundException e){
            e.printStackTrace();
        }finally{
            //6.释放资源
            //为了保证资源一定释放,在finally语句块中关闭资源
            //并且要遵循从小到大依次关闭,比如应该先关闭stmt,在关闭conn
            //分别对其try..catch
            try{
//                if(stmt !=null){
//                    stmt.close();
//                }
                if (ps !=null){
                    ps.close();
                }
            }catch(SQLException e){
                e.printStackTrace();
            }
            try{
                if(conn !=null){
                    conn.close();
                }
            }catch(SQLException e){
                e.printStackTrace();
            }

        }


    }*/
    public static void update(String data5){

        Connection conn=null;
        //Statement stmt=null;
        PreparedStatement ps=null;
        try{
            //1.注册驱动
            //第一种方式
            //Driver driver =new com.mysql.jdbc.Driver();//多态,父类型引用指向子类型对象
            //DriverManager.registerDriver(driver);
            //第二种方式(常用,采用反射机制)
            //为什么常用?因为参数是一个字符串,字符串可以写到***.properties文件中
            //以下方法不需要接受返回值,因为我们只想用他的类加载动作
            String driver="com.mysql.jdbc.Driver";
            Class.forName(driver);

            //2.获取连接
			/*
				url:统一资源定位符(网络中某个资源的绝对路径)
					http://www.baidu.com/就是url
				url包括哪些内容?
					协议
					ip
					port(端口)
					资源名

				http://180.101.49.12:80/index.html
					http:// --通讯协议
					180.101.49.12--服务器ip地址--cmd 中ping www.baidu.com 获取
					80 服务器上软件的端口
					index.html 是服务器上某个资源名

				jdbc:mysql://127.0.0.1:3306/qc
					jdbc:mysql:// 协议
					127.0.0.1 ip地址
					3306 mysql数据库端口号
					qc 具体数据库实例名

				说明:127.0.0.1和localhost都是本机ip地址

				什么是通信协议,有什么用?
					通信协议是通信之前就提前定好的数据传送格式。
					数据包具体怎么传数据,格式提前定好的

			*/
            String url="jdbc:mysql://127.0.0.1:3306/qc";
            String user="root";
            String password="";
            conn= DriverManager.getConnection(url,user,password);
            //System.out.println("数据库连接对象="+conn);

            //3.获取数据库操作对象(Statement专门执行sql语句的)
            //stmt=conn.createStatement();

            //int data5i=Integer.parseInt(data5);
            //int deal_numi=Integer.parseInt(deal_num);

            //4.执行sql
            String sql="INSERT INTO `test_sht`( `deal_num`) VALUES(?)";
            ps= conn.prepareStatement(sql);
            //ps.setInt(1,data5i);
            ps.setString(1,data5);
            //ps.setInt(2,deal_numi);
            //专门执行DML语句的(insert delete update)
            //返回值是“影响数据库中的记录条数"
            ps.execute();
//            int count=ps.executeUpdate(sql);
//            System.out.println(count == 1 ?"保存成功":"保存失败");
            //5.处理查询结果集(只有当第四步执行的是select语句的时候,才有这第五步处理查询结果集)


        }catch(SQLException e){
            e.printStackTrace();
        }
        catch(ClassNotFoundException e){
            e.printStackTrace();
        }finally{
            //6.释放资源
            //为了保证资源一定释放,在finally语句块中关闭资源
            //并且要遵循从小到大依次关闭,比如应该先关闭stmt,在关闭conn
            //分别对其try..catch
            try{
//                if(stmt !=null){
//                    stmt.close();
//                }
                if (ps !=null){
                    ps.close();
                }
            }catch(SQLException e){
                e.printStackTrace();
            }
            try{
                if(conn !=null){
                    conn.close();
                }
            }catch(SQLException e){
                e.printStackTrace();
            }

        }


    }

}

资源参考
添加链接描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

傻傻虎虎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值