JDBC入门

JDBC数据库操作详解
本文详细介绍了Java Database Connectivity (JDBC) 的基本概念,包括如何使用JDBC进行数据库操作的步骤,涉及的常用类和接口,如DriverManager、Connection、Statement、ResultSet等,以及批处理操作、SQL注入防范和资源释放的最佳实践。

一、JDBC简介

 1、JDBC简介
	*Java Database Connectivity : java 连接数据库

	*使用java操作数据库需要驱动
			-驱动:两个设置之间的桥梁

	*如果想要使用java操作数据库,需要数据库生产厂商提供驱动,程序熟悉java代码,熟悉数据库驱动里面的操作代码,程序员不仅要熟悉mysql代码,也要熟悉oracle代码,会造成程序员压力会很大。
		
	*sun公司针对于这个情况,提出解决方案,sun公司和各个生产厂商进行商量,sun公司提供了一套标准的接口,各个数据库厂商实现这个接口,程序员只需要熟悉sun公司提供的这套接口就可以了,这套接口是jdbc。

	*想要实际使用jdbc操作数据库,第一步需要操作‘安装’驱动,即导入jar包

 二、JDBC入门程序

2、JDBC入门程序
	*操作步骤(模板)

		-步骤:
		(1)加载(注册)数据库驱动
		(2)创建与数据库的链接
		(3)编写一个sql语句
		(4)执行语句(如果执行的是一个查询语句,得到数据的结果)
		(5)释放资源
		(关闭资源的顺序,谁先打开谁最后关闭,谁最后打开谁先关闭)

		-代码演示
		public class TestJDBC {
			public static void main(String[] args) {
				
				try {
					//一、加载数据库驱动,使用类DriverManager
					DriverManager.registerDriver(new Driver());
					 Class.forName("包类路径");
					
					//二、创建与数据库的链接,使用到DriverManager方法getConnection方法创建链接
					/*	url:数据库的路径  ip+3306
						username: 数据库用户名
						password:数据库密码*/
					Connection conn = (Connection) DriverManager.getConnection("jdbc:mysql://localhost:3306/info","root","123");
					
					//三、编写sql语句
					String sql = "select * from dept";
					
					//四、执行sql语句(如果执行的是一个查询语句,得到数据的结果)
					/*使用statement执行sql
						statement如何得到,Connection里面的方法得到	*/
					Statement stmt =(Statement) conn.createStatement();
					//得到ResultSet 结果及 返回查询的表格
					ResultSet rs = stmt.executeQuery(sql);
					//遍历结果集ResuleSet
					while(rs.next()){
						//获取表格里面的每一个值、
						int id = rs.getInt("did");
						String name = rs.getString("dname");
						System.out.println("id:"+id+"    name:"+name);
					}
					
					//五、释放资源
					rs.close();
					stmt.close();
					conn.close();
						
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}


======JDBC操作数据库使用到的类或者接口都在java.sql包里面=====

 三、JDBC涉及常用类

3、JDBC时使用到的类

(1)====DriverManager、Driver====
	*JDBC的DriverManager对象、
		*java.sql包下面

		*作用:
			-注册数据库驱动
				--使用registerDriver(Driver driver)方法注册驱动
					*这个registerDriver方法存在一个问题:导致驱动注册两次
						-因为在Driver类里面有一个静态代码块,静态代码块会在类加载时执行
						-在Driver类加载时候执行registerDriver(new Driver())加载一次

						-在jdbc代码里面也写了一个DriverManager.registerDriver(new Driver())又加载一次
					
					*在一般开发不使用上述这个方式,而采用反射来完成
						class.forName("com.mysql.jdbc.Driver");

						-加载时完成注册
	
	*创建于数据库的连接
		*Connection getConnection(String url,String user,String password);

			-返回Connection对象、

			-三个参数
				*第一个参数:
					要连接的数据库的ip+端口号3306+数据库名称
					-jdbc:mysql://localhost:3306/day15

					-如果连接的是本地的数据库同时端口号是3306,这个时候简写方式
					jdbc:mysql:///day17
				
				*第二个参数:
					要连接的数据库用户名

				*第三个参数
					要连接的数据库密码

				DriverManager.getConnection("jdbc:mysql:///day17","root","123");
	

(2)====Connection====
		*Connection conn = DriverManager.getConnection("jdbc:mysql:///day15","root","123");

			-方法返回一个Connection对象
		
		*在java.sql.*;包里面

		*用于创建执行sql的对象
			-Statement stmt  = conn.createStatement():创建一个statement对象

			-PreparedStatement preparedStatement = conn.preparedStatement(String sql);
				--创建一个PreparedStatement对象,预编译对象,防止sql注入
			
			-CallableStatement prepareCall(String sql):创建一个CallableStatement对象,可以执行存储过程

		*可以和事务一起使用
			-serAutoCommit(boolean autoCommit):设置数据库是否自动提交,默认是自动提交,值是true、

			-rollback():回滚事务里面的语句,回到执行之前的效果

			-commit():提交事务,让事务里面语句真正的执行

		
(3)====Statement====
		*Statement stmt = conn.ctreateStatement();

		*在java.sql.*;包里面
		0
		*用来执行sql语句

			-ResultSet executeQuery(String sql);执行查询语句,返回的是ResultSet结果集

			-int executeUpadte(String sql):执行修改,删除,更新语句,返回的是int类型,返回的成功操作的记录数
					--比如增加一条记录,返回int值,int值是成功添加的记录的数量

			-boolean execute(String sql):执行sql语句,crud语句都可以执行,返回的是boolean类型
				--如果查询出的结果是ResultSet,返true、
				--不是查询的操作,返回是false、

		*用来执行批处理的操作
			-有很多sql语句,批量执行很多的sql语句

			-addBatch(String sql):把 多个sql语句放到批处理里面

			-clearBatch():清楚批处理里面的语句

			-int[] executeBatch():执行批处理的语句

(4)====ResultSet====
		*ResultSet rs = stmt.execute(String sql);

		*在java.sql.*;包里面

		*代表查询之后的结果集,类似查询出来的那个表格

		*对返回的结果集进行遍历

			while(rs.next()){
				rs.getInt();
				rs.getString();
				.....
			}

		*画图分析结果集的遍历
			-执行while循环,使用next方法,之后一行一行向下遍历,在没有使用next方法时候,在第一行之前

			-遍历之后只能向下执行,不能向上,遍历的结果不能修改

			-
			获取具体的某一行数据
				--两种方式:
					*一、rs.getString("字段名称");
					*二、rs.getString("字段查询出来的所在的位置");
							rs.getString(1);
							
						getInt() getString.....等方法

					*一般使用第一种方式,比较准确

 四、滚动结果集

(5)滚动结果集

	*创建statement,使用createStatement(int resultSetType, int resultSetConcurrency);

		- 结果集类型
			* TYPE_FORWARD_ONLY : 结果集只能向下
			* TYPE_SCROLL_INSENSITIVE : 结果集可以滚动
			* TYPE_SCROLL_SENSITIVE : 结果集可以滚动

		- 结果集并发策略
			* CONCUR_READ_ONLY : 结果集不可以修改
			* CONCUR_UPDATABLE : 结果集可以修改

		- 组合方式
			* TYPE_FORWARD_ONLY   CONCUR_READ_ONLY: 只能向下,不能修改(默认的方式)

			* TYPE_SCROLL_INSENSITIVE  CONCUR_READ_ONLY : 结果集可滚动,但不可修改.

			* TYPE_SCROLL_SENSITIVE  CONCUR_UPDATABLE : 结果集可滚动,而且可修改.

	* 如果使用滚动结果集,操作的表里面必须要有一个主键 primary key

	*代码演示

		import java.sql.Connection;
		import java.sql.DriverManager;
		import java.sql.ResultSet;
		import java.sql.SQLException;
		import java.sql.Statement;

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

				try {
					// 加载sql驱动;
					Class.forName("com.mysql.jdbc.Driver");

					// 建立连接
					Connection connection = DriverManager.getConnection(
							"jdbc:mysql:///info", "root", "123");

					// 编写sql语句
					String sql = "select * from modify";

					// 执行语句
					// 得到statement对象,设置滚动结果集
					Statement stmt = connection
							.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
									ResultSet.CONCUR_UPDATABLE);
					ResultSet rs = stmt.executeQuery(sql);

					// 遍历到第一行记录
					rs.absolute(2);
					// 更改dname值
					rs.updateString("dname", "QQQQ");
					// 执行修改
					rs.updateRow();

					// 是rs移动到第一行之前
					rs.absolute(1);
					// 遍历结果集
					while (rs.next()) {
						int did = rs.getInt("did");
						String dname = rs.getString("dname");
						System.out.println("did :" + did + "  dname :" + dname);
					}

					// 关闭资源
					rs.close();
					stmt.close();
					connection.close();

				} catch (ClassNotFoundException e) {

					e.printStackTrace();
				} catch (SQLException e) {

					e.printStackTrace();
				}
			}
		}

4、jdbc释放资源
	*谁先打开,谁最后关闭
		
		- 需要时try-catch对异常进行捕获,需要释放资源的语句写到finally里面
			
			-- 因为finally特点就是,无论程序是否出现异常,finally里面的语句肯定会执行
		
		- 标准的写法
		if(rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
			}
			rs = null;//让jvm快速回收
		}
		
		if(stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
			}
			stmt = null;
		}
		
		if(conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
			}
			conn = null;
		}

五、JDBC批处理操作

5、批处理的操作(了解)
		* Statement.addBatch(sql) :把多个sql语句放入到批处理里面
		* executeBatch()方法:执行多个sql语句
			- 向一张表中插入多条记录
			
			- 代码
				//编写sql
				String sql1 = "insert into student values(3,'aaa','222')";
				String sql2 = "insert into student values(4,'bbb','333')";
				String sql3 = "insert into student values(5,'ccc','444')";
				//需要使用批处理操作
				stmt = conn.createStatement();
				//把这些sql放到批处理里面
				stmt.addBatch(sql1);
				stmt.addBatch(sql2);
				stmt.addBatch(sql3);
				//执行这些sql语句
				stmt.executeBatch();

 

 六、JDBC工具类封装——加载配置文件(***)

6、封装jdbc操作的方法工具类
		*读取配置文件(****)
			/*第一种方式读取配置文件 类加载器
			 * 	try {
					// 读取配置文件
					Properties pro = new Properties();

					// 类加载器
					InputStream in = JDBCUtils.class.getClassLoader()
							.getResourceAsStream("dp.properties");

					// 加载文件
					pro.load(in);

					drivername = pro.getProperty("driverName");
					url = pro.getProperty("url");
					username = pro.getProperty("username");
					password = pro.getProperty("password");

				} catch (IOException e) {
					e.printStackTrace();
				}*/
			/*第二种方式读取配置文件 类ResourceBundle*/
				//getBundle()方法 当配置文件所在src下面直接写文件的名称(***)
				//getString()方法 直接获取配置文件中key的值
				drivername = ResourceBundle.getBundle("db").getString("driverName");
				url  = ResourceBundle.getBundle("db").getString("url");
				username = ResourceBundle.getBundle("db").getString("username");
				password = ResourceBundle.getBundle("db").getString("password");

		* 封装了释放资源的方法
			- 由于查询时候需要多关闭一个结果集
			- 重载了方法实现不同的操作,关闭不同的连接

七、SQL注入问题解决

	7、SQL注入的漏洞的防范
		* 用户名输入框里面输入这样一句话 zhangsan' or '1=1

			select * from student where username='zhangsan' or '1=1 ' and password='123456'

		* 使用prepareStatement对象防范sql注入的漏洞
			- 把sql语句先编译出来
		
		* 代码
			String sql = "select * from student where username=? and password=?";	
			//创建一个prepareStatement
			PreparedStatement pst = conn.prepareStatement(sql); //把sql先编译
			//传递参数
			pst.setString(1,stu.getUsername());
			pst.setString(2, stu.getPassword());
			//执行sql
			rs = pst.executeQuery();
			*** 执行查询方法 executeQuery();
			*** 执行增加,删除,更新 executeUpdate();

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值