JavaWeb3——JDBC 编程进阶

1. PreparedStatement 研究

1.1 PreparedStatement 概念

  • 什么是带参数的 SQL 语句?
String sql = "select  * from students where sno = ?";
  • 解释参数 “ ?”(占位符)
- 这里并不是查询学号为 ? 号的学生。
- 而是代表一个参数,在执行该语句之前,必须给参数赋值。

1.2 为什么要多用 PreparedStatement ?而少用 Statement

  1. 代码的可读性和可维护性。
在这里插入代码片
  1. PreparedStatement 提高性能。
- 有一种常见情况:写好的 JDBC 代码,编译器会对代码预编译,而预编译语句可能重复调用。
- 因而,使用 PreparedStatement 可以提高性能。
- 因为,只需要将参数直接传入编译过的语句执行代码。
  1. 防止 SQL 注入攻击。
SQL 注入攻击:
- 用户合法的输入:但提交的是特殊的非法代码。
- 输入注入了 SQL 中,改变了 SQL 原有的逻辑。

例如:
- 在登陆界面,用户名输入:
- 'or'1'='1'or'1'='1
- SQL 语句就变成了:
- select * from students where sname = ''or'1'='1'or'1'='1'

1.3 如何使用 PreparedStatement

  1. 连接数据库
		/* 驱动程序描述字符串 */
		String driver = "com.mysql.jdbc.Driver";

		/* 加载驱动程序 */
		try {
			Class.forName(driver);
		} catch (ClassNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}

		/* 连接数据库 */
		String url = "jdbc:mysql://localhost:3306/mydb";
		String user = "root";
		String passwd = "123456";
		Connection con = null;
		try {
			con = DriverManager.getConnection(url, user, passwd);
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
  1. 创建命令对象——PreparedStatement
		/* 创建命令对象——PreparedStatement */
		String sql = "select * from students where sno = ?";
		PreparedStatement cmd = null;
		try {
			cmd = con.prepareStatement(sql);
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
  1. 输入参数
		/* 设置参数 */
		try {
			
			/*
			 * 1. setString(1, "张三")
			 * 
			 * 2. 1 表示从左到右你写的 sql 语句的第一个参数(相当于 ? 的位置)
			 * 
			 * 3. "张三" 表示查询的值
			 */
			cmd.setString(1, "张三");
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
  1. 执行
		/* 执行 */
		try {
			System.out.print("执行是否成功:" + cmd.execute());
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
  1. 关闭接口
		/* 关闭接口 */
		try {
			if (cmd != null) {
				cmd.close();
				cmd = null;
			}
			if (con != null) {
				con.close();
				con = null;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
执行是否成功:true

1.4 使用 PreparedStatement 示例

	public static void addStudent() throws UnsupportedEncodingException {
		Connection con = null;
		PreparedStatement cmd = null;
		ResultSet rs = null;
		String url = "jdbc:mysql://localhost:3306/mydb";
		String user = "root";
		String passwd = "123456";

		try {

			/* 驱动 */
			Class.forName("com.mysql.jdbc.Driver");

			/* 连接数据库 */
			con = DriverManager.getConnection(url, user, passwd);

			/* 增加一个学生代码——使用 PreparedStatement */
			String sql1 = "insert into students(sno, sname, ssex) values(?, ?, ?);";
			cmd = con.prepareStatement(sql1);
			cmd.setString(1, "1005");
			cmd.setString(2, "李四");
			cmd.setString(3, "男");
			cmd.executeUpdate();

			/* 打印到控制台 */
			String sql2 = "select * from students";
			rs = cmd.executeQuery(sql2);
			while (rs.next()) {
				String sno = rs.getString("sno");
				String sname = rs.getString(2);
				String ssex = rs.getString("ssex");
				System.out.printf("%-8s%-6s%-3s\n", sno, sname, ssex);
			}

		} catch (ClassNotFoundException e) {
			// TODO JDBC 驱动
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO 连接数据库
			e.printStackTrace();
		} finally {
			try {
				if (rs != null) {
					rs.close();
					rs = null;
				}
				if (cmd != null) {
					cmd.close();
					cmd = null;
				}
				if (con != null) {
					con.close();
					con = null;
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

控制台输出:

1001    李晨    男  
1002    王丽    女  
1003    陈军    男  
1004    张三    男  
1005    李四    男  

MySQL:

在这里插入图片描述

2. 如何获得元数据 MetaData

2.1 元数据就是字段那些

  • 元数据最本质的定义为:data about data(关于数据的数据)。
  • JDBC 通过元数据(MetaData)来获得表的相关信息,如:字段,字段属性等。
  • JDBC 提供了两个元数据对象类型:DatabaseMetaData 和 ResultSetMetadata

2.2 元数据访问示例

	public static void practiceMetaData() throws Exception {
		Connection con = null;
		Statement cmd = null;
		ResultSet rs = null;
		String url = "jdbc:mysql://localhost:3306/mydb";
		String user = "root";
		String passwd = "123456";

		try {

			/* 驱动 */
			Class.forName("com.mysql.jdbc.Driver");

			/* 连接数据库 */
			con = DriverManager.getConnection(url, user, passwd);

			/* 创建数据库的元数据 */
			DatabaseMetaData meta = con.getMetaData(); // 获取数据库的元数据对象
			System.out.println("数据库名为:" + meta.getDatabaseProductName());
			System.out.println("数据库版本号为:" + meta.getDatabaseProductVersion());
			System.out.println("数据库Url为:" + meta.getURL());
			System.out.println("数据库登录名为:" + meta.getUserName());
			System.out.println("数据库驱动名为:" + meta.getDriverName());

			/* 1. 创建表的元数据 */
			/* 2. 打印 students 表到控制台 */
			System.out.println("Students 表为:");
			cmd = con.createStatement();
			String sql2 = "select * from students";
			rs = cmd.executeQuery(sql2);

			// 1
			ResultSetMetaData rsmd = rs.getMetaData();
			System.out.println("第一列的类型为:" + rsmd.getColumnType(1));
			System.out.println("第一列的列类型名为:" + rsmd.getColumnTypeName(1));
			System.out.println("第一列所在的表为:" + rsmd.getTableName(1));

			// 2
			while (rs.next()) {
				String sno = rs.getString("sno");
				String sname = rs.getString(2);
				String ssex = rs.getString("ssex");
				System.out.printf("%-8s%-6s%-3s\n", sno, sname, ssex);
			}

		} catch (ClassNotFoundException e) {
			// TODO JDBC 驱动
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO 连接数据库
			e.printStackTrace();
		} finally {
			try {
				if (rs != null) {
					rs.close();
					rs = null;
				}
				if (cmd != null) {
					cmd.close();
					cmd = null;
				}
				if (con != null) {
					con.close();
					con = null;
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
数据库名为:MySQL
数据库版本号为:8.0.23
数据库Url为:jdbc:mysql://localhost:3306/mydb
数据库登录名为:root@localhost
数据库驱动名为:MySQL Connector/J
Students 表为:
第一列的类型为:4
第一列的列类型名为:INT
第一列所在的表为:students
1001    李晨    男  
1002    王丽    女  
1003    陈军    男  
1004    张三    男  
1005    李四    男 

3. 事务处理

3.1 什么是 Java 事务

  • 要么全部执行成功,要么撤销全部不执行。
  • 数据库 JDBC 操作的事务习惯就称为 Java 事务。

3.2 数据库事务编程示例

	public static void practiceTransaction() {
		Connection con = null;
		Statement cmd = null;
		ResultSet rs = null;
		String url = "jdbc:mysql://localhost:3306/mydb";
		String user = "root";
		String passwd = "123456";

		try {

			/* 驱动 */
			Class.forName("com.mysql.jdbc.Driver");

			/* 连接数据库 */
			con = DriverManager.getConnection(url, user, passwd);

			/* 创建命令对象 */
			String sql1 = "insert into students(sno, sname, ssex) values(1006, \"王老五\", \"男\");";
			cmd = con.createStatement();

			/* 事务处理 */
			try {
				con.setAutoCommit(false); // 禁止自动提交事务,我们自己定义事务
				cmd.executeUpdate(sql1);
				cmd.executeUpdate(sql1);
				con.commit(); // 提交事务
			} catch (Exception e) {
				// TODO 事务
				try {
					con.rollback();
				} catch (SQLException ee) {
					ee.printStackTrace();
				}
			}

			/* 打印到控制台 */
			String sql2 = "select * from students";
			rs = cmd.executeQuery(sql2);
			while (rs.next()) {
				String sno = rs.getString("sno");
				String sname = rs.getString(2);
				String ssex = rs.getString("ssex");
				System.out.printf("%-8s%-6s%-3s\n", sno, sname, ssex);
			}

		} catch (ClassNotFoundException e) {
			// TODO JDBC 驱动
			e.printStackTrace();
		} catch (SQLException e) {
			// TODO 连接数据库
			e.printStackTrace();
		} finally {
			try {
				if (rs != null) {
					rs.close();
					rs = null;
				}
				if (cmd != null) {
					cmd.close();
					cmd = null;
				}
				if (con != null) {
					con.close();
					con = null;
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

可以看到,并没有插入数据

1001    李晨    男  
1002    王丽    女  
1003    陈军    男  
1004    张三    男  
1005    李四    男 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

姜满月

鼓励,鼓励,更加努力

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

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

打赏作者

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

抵扣说明:

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

余额充值