原创

JDBC基础---常见的API


avatar

1.什么是JDBC

JDBC(Java-Database-Connectivity)是一套用于执行SQL语句的Java的API。应用程序可通过这套API连接到关系型数据库,并使用SQL语句来完成对数据库中数据的查询、新增、更新和删除等操作。

2.JDBC的编程步骤

通常情况下,JDBC的使用可以按照下面几个步骤进行:

  1. 导入驱动jar包:mysql-connector-java-5.1.37-bin.jar
  2. DriverManager:注册驱动、驱动管理对象
  3. Connection:数据库连接对象
  4. 定义SQL语句
  5. Statement/PreparedStatement:执行SQL的语句
  6. ResultSet:结果集对象,封装查询结果
  7. 关闭连接,释放资源

简单模拟一下整个流程:将数据库test中的表sales中的“xiaohua”的sum值改为10000

avatar

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

public class Demo01 {
	public static void main(String[] args) throws Exception {
		// 1.导入驱动jar包
		// 2.注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		
		// 3.获取数据库连接对象
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "19991204");
		
		// 4.定义SQL语句
		String str = "update sales set sum = 10000 where name = 'xiaohua'";
		
		// 5.获取执行sql对象Statement
		Statement stmt= conn.createStatement();
		
		// 6.执行SQL语句
		int count = stmt.executeUpdate(str);
		
		// 7.处理结果
		System.out.println(count);
		
		// 8.释放资源
		stmt.close();
		conn.close();
	}
}	
1

avatar

3.DriverManager驱动管理对象

功能:注册驱动、获取数据库连接

(1)注册驱动

static void registerDriver(Driver driver):注册与给定的驱动程序DriverManager

写代码使用:使用Class.forName("com.mysql.jdbc.Driver");

【说明】:通过查看源码发现:在com.mysql.jdbc.Driver类中存在静态代码块用来注册驱动,因此我们通过上面的代码会简单一些。

// 1.注册驱动
Class.forName("com.mysql.jdbc.Driver");

【注意】:MySQL5之后的驱动jar包可以省略注册的步骤。

(2)获取数据库连接:

static Connection getConnection(String url, String user, String password),

  • 参数url:指定连接的路径(语法:jdbc:mysql://ip地址(域名):端口号/数据库名称)
  • 参数user:指用户名
  • 参数password:指密码
// 3.获取数据库连接对象
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "19991204");

【注意】:如果连接的是本机mysql服务器,并且mysql服务器默认端口3306,则url可以简写为:jdbc:mysql://数据库名称。

4.Connection数据库连接对象

功能:获取执行SQL对象、管理事务

(1)获取执行SQL对象:

  • Statement createStatment()
  • PreparedStatement prepareStatement(String sql)

(2)管理事务:

  • 开启事务:void setAutoCommit(boolean autoCommit):参数为false,在执行SQL之前开启事务
  • 提交事务:void commit():当所有SQL都执行完毕后提交事务
  • 回滚事务:rollback():在catch中回滚事务

5.Statement执行SQL的对象(静态)

  • boolean execute(String sql):可以执行任意的SQL 【了解】
  • int executUpdate(String sql):执行DML(增、删、改)语句、DDL(create、alter、drop)语句
  • ResultSet executeQuery(String sql):执行DQL(select)语句,返回结果集对象

【注意】executUpdate的返回值:影响的行数,可以通过这个影响的行数判断DML语句是否执行成功,返回值>0的则执行成功。

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

public class Demo02 {
	public static void main(String[] args) {
		Statement stmt = null;  //如果不在外面提前定义好,那么在finally代码块中无法看到stmt
		Connection conn = null; 
		
		try {
			// 1.注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			
			// 2.获取Connection对象
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "19991204");
			
			// 3.定义SQL
			String str = "insert into sales values('xiaoxiong', 10000)";
			
			// 4.获取执行sql对象Statement
			stmt = conn.createStatement();
			
			// 5.执行SQL语句
			int count = stmt.executeUpdate(str);  //返回值是行数
			 
			// 6.处理结果
			System.out.println("影响的行数一共有:" + count);
			
			if(count > 0){
				System.out.println("添加成功!");
			}else{
				System.out.println("添加失败!");
			}
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			//stmt.close();
			// 7.释放资源
			//避免空指针异常
			if(stmt != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

影响的行数一共有:1
添加成功!

avatar

【说明】:

  1. “释放资源”放入finally:防止前面的程序出现错误,程序终止无法释放资源。
  2. “释放资源”的时候判断空指针异常:防止在连接数据库时密码错误导致无法执行Statement,出现的空指针情况。

6.ResultSet:结果集对象,封装查询结果

  • boolean next():光标向下移动一行,判断当前行是否是最后一行末尾(是否有数据)
  • getXxx(参数):获取数据

【注意】:

  • Xxx:数据类型 如:int getInt()、 String getString();
  • 两种参数类型的情况:int代表列的标号(从1开始),如:getString(1),String代表列的名称,如:getDouble("balance")

流程步骤:

  1. 光标向下移动一行
  2. 判断是否有数据
  3. 获取数据
import java.sql.*;

public class Demo04 {
	public static void main(String[] args) {
		Statement stmt = null;  //如果不在外面提前定义好,那么在finally代码块中无法看到stmt
		Connection conn = null; 
		ResultSet rs = null;
		
		try {
			// 1.注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			// 2.获取Connection对象
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test", "root", "19991204");
			// 3.定义SQL
			String str = "select * from sales";
			// 4.获取执行sql对象Statement
			stmt = conn.createStatement();
			
			// 5.执行SQL语句
			rs = stmt.executeQuery(str);
			
			// 6.处理结果
			// 6.1光标向下移动一行
			rs.next();
			// 6.2获取数据
			String name = rs.getString("name");
			double balance = rs.getDouble(2);
			// 6.3打印数据
			System.out.println(name + "---" + balance);
			
			rs.next();
			name = rs.getString("name");
			balance = rs.getDouble(2);
			System.out.println(name + "---" + balance);
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			// 7.释放资源
			//避免空指针异常
			if(rs != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			
			if(stmt != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

xiaohua---10000.0
zhoutong---1000.0

重新更改一部分代码,来打印表中的所有数据:

            // 6.处理结果
			// 判断光标是否为最后一行
			while(rs.next()){
				// 获取数据
				//String name = rs.getString(1);
				String name = rs.getString("name");
				//double balance = rs.getDouble(2);
				double balance = rs.getDouble("sum");
				// 打印数据
				System.out.println(name + "---" + balance);
			}
xiaohua---10000.0
zhoutong---1000.0
roy---2000.0
xiaoxiong---10000.0

打印CHARACTER_SETS表中的数据:

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

public class Demo06 {
	public static void main(String[] args) {
		Statement stmt = null; 
		Connection conn = null; 
		ResultSet rs = null;
		
		try {
			// 1.注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			// 2.获取Connection对象
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/information_schema", "root", "19991204");
			// 3.定义SQL
			String str = "SELECT * FROM CHARACTER_SETS;";
			// 4.获取执行sql对象Statement
			stmt = conn.createStatement();
			
			// 5.执行SQL语句
			rs = stmt.executeQuery(str);
			
			// 6.处理结果
			// 判断光标是否为最后一行
			while(rs.next()){
				// 获取数据
				String str1 = rs.getString(1);
				String str2 = rs.getString(2);
				String str3 = rs.getString(3);
				double num = rs.getDouble(4);

				// 打印数据
				System.out.println(str1 + "---" + str2 + "---" + str3 + "---" + num);
			}
			
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}finally{
			// 7.释放资源
			//避免空指针异常
			if(rs != null){
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			
			if(stmt != null){
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
			
			if(conn != null){
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
gb2312---gb2312_chinese_ci---GB2312 Simplified Chinese---2.0
greek---greek_general_ci---ISO 8859-7 Greek---1.0
cp1250---cp1250_general_ci---Windows Central European---1.0
gbk---gbk_chinese_ci---GBK Simplified Chinese---2.0
latin5---latin5_turkish_ci---ISO 8859-9 Turkish---1.0
armscii8---armscii8_general_ci---ARMSCII-8 Armenian---1.0
utf8---utf8_general_ci---UTF-8 Unicode---3.0
ucs2---ucs2_general_ci---UCS-2 Unicode---2.0
cp866---cp866_general_ci---DOS Russian---1.0
keybcs2---keybcs2_general_ci---DOS Kamenicky Czech-Slovak---1.0
macce---macce_general_ci---Mac Central European---1.0
macroman---macroman_general_ci---Mac West European---1.0
cp852---cp852_general_ci---DOS Central European---1.0
latin7---latin7_general_ci---ISO 8859-13 Baltic---1.0

7.重构代码---封装

import java.util.Date;

public class Emp {
	private int employee_id;
	private String first_name;
	private String last_name;
	private String email;
	private String phone_number;
	private String job_id;
	private double salary;
	private double commission_pct;
	private int manager_id;
	private int department_id;
	private Date hiredate;
	
	public Date getHiredate() {
		return hiredate;
	}
	public void setHiredate(Date hiredate) {
		this.hiredate = hiredate;
	}
	public int getEmployee_id() {
		return employee_id;
	}
	public void setEmployee_id(int employee_id) {
		this.employee_id = employee_id;
	}
	public String getFirst_name() {
		return first_name;
	}
	public void setFirst_name(String first_name) {
		this.first_name = first_name;
	}
	public String getLast_name() {
		return last_name;
	}
	public void setLast_name(String last_name) {
		this.last_name = last_name;
	}
	public String getEmail() {
		return email;
	}
	public void setEmail(String email) {
		this.email = email;
	}
	public String getPhone_number() {
		return phone_number;
	}
	public void setPhone_number(String phone_number) {
		this.phone_number = phone_number;
	}
	public String getJob_id() {
		return job_id;
	}
	public void setJob_id(String job_id) {
		this.job_id = job_id;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
	public double getCommission_pct() {
		return commission_pct;
	}
	public void setCommission_pct(double commission_pct) {
		this.commission_pct = commission_pct;
	}
	public int getManager_id() {
		return manager_id;
	}
	public void setManager_id(int manager_id) {
		this.manager_id = manager_id;
	}
	public int getDepartment_id() {
		return department_id;
	}
	public void setDepartment_id(int department_id) {
		this.department_id = department_id;
	}
	@Override
	public String toString() {
		return "Emp [employee_id=" + employee_id + ", first_name=" + first_name + ", last_name=" + last_name
				+ ", email=" + email + ", phone_number=" + phone_number + ", job_id=" + job_id + ", salary=" + salary
				+ ", commission_pct=" + commission_pct + ", manager_id=" + manager_id + ", department_id="
				+ department_id + ", hiredate=" + hiredate + "]";
	}	
}
import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;

public class Demo07 {
	public static void main(String[] args) {
		List<Emp> list = new Demo07().findAll();
		System.out.println(list);
		System.out.println(list.size());
	}
	
	public List<Emp> findAll(){
		Statement stmt = null; 
		Connection conn = null; 
		ResultSet rs = null;
		List<Emp> list = null;
		
		try {
			// 1.注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			// 2.获取Connection对象
			conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myemployees", "root", "19991204");
			// 3.定义SQL
			String str = "SELECT * FROM employees;";
			// 4.获取执行sql对象Statement
			stmt = conn.createStatement();
			// 5.执行SQL语句
			rs = stmt.executeQuery(str);

			
			// 6.遍历结果集,封装对象,装在集合
			Emp emp = null; //提前定义好,放置每次循环重复创建对象,占用过多的栈内存!
		    list = new ArrayList<Emp>();
			while (rs.next()) {
				// 获取数据
				int employee_id = rs.getInt("employee_id");
				String first_name = rs.getString("first_name");
				String last_name = rs.getString("last_name");
				String email = rs.getString("email");
				String phone_number = rs.getString("phone_number");
				String job_id = rs.getString("job_id");
				double salary = rs.getDouble("salary");
				double commission_pct = rs.getDouble("commission_pct");
				int manager_id = rs.getInt("manager_id");
				int department_id = rs.getInt("department_id");
				Date hiredate = rs.getDate("hiredate");
				
				// 创建对象并赋值
				emp = new Emp();
				emp.setEmployee_id(employee_id);
				emp.setFirst_name(first_name);
				emp.setLast_name(last_name);
				emp.setEmail(email);
				emp.setPhone_number(phone_number);
				emp.setJob_id(job_id);
				emp.setSalary(salary);
				emp.setCommission_pct(commission_pct);
				emp.setManager_id(manager_id);
				emp.setDepartment_id(department_id);
				emp.setHiredate(hiredate);
				
				// 装载集合
				list.add(emp);
			}
						
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		} finally{
			// 7.释放资源
			// 避免空指针异常
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}

			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}

			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return list;
	}
}

//略了一部分数据
[Emp [employee_id=100, first_name=Steven, last_name=K_ing, email=SKING, phone_number=515.123.4567, job_id=AD_PRES, salary=24000.0, commission_pct=0.0, manager_id=0, department_id=90, hiredate=1992-04-03], Emp [employee_id=101, first_name=Neena, last_name=Kochhar, email=NKOCHHAR, phone_number=515.123.4568, job_id=AD_VP, salary=17000.0, commission_pct=0.0, manage.............]
107

8.代码重构---工具类

目的:简化书写。

分析

  1. 注册驱动也抽取
  2. 抽取一个方法获得连接对象:不想传递参数,还得保证工具类的通用性--->配置文件jdbc.properties
  3. 抽取一个方法释放资源

配置文件:jdbc.properties

url=jdbc:mysql:///myemployees
user=root
password=19991204
driver=com.mysql.jdbc.Driver
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.URL;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
import java.sql.ResultSet;

public class JDBCUtils {
	private static String url;
	private static String user;
	private static String password;
	private static String driver;
	
	// 文件读取,只需要读取一次即可拿到这些值,使用静态代码块
	static{
		
		try {
			//读取资源文件,获取值
			//1.创建Properties集合类
			Properties pro = new Properties();
			
//			//获取src路径下的文件的方式--->ClassLoader 类加载器
//			ClassLoader classLoader = JDBCUtils.class.getClassLoader();
//			URL res = ClassLoader.getSystemResource("jdbc.properties");
//			String path = res.getPath();
//			System.out.println(path);
			
			//2.加载文件
			pro.load(new FileReader("src/jdbc.properties"));      //【注意】:路径可能出现问题,写绝对路径肯定正确,但是不合适
			
//			pro.load(new FileReader(path));
			
			//3.获取属性,赋值
			url = pro.getProperty("url");
			user = pro.getProperty("user");
			password = pro.getProperty("password");
			driver = pro.getProperty("driver");
			//4.注册驱动
			Class.forName(driver);
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	
	// 获取链接,返回连接对象
	public static Connection getConnection() throws SQLException{
		return DriverManager.getConnection(url, user, password);
	}
	
	
	// 释放资源
	public static void close(Statement stmt, Connection conn){
		if(stmt != null){
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
	
	public static void close(ResultSet rs, Statement stmt, Connection conn){
		if(stmt != null){
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}
}

import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.util.ArrayList;
import java.util.List;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.ResultSet;

public class Demo08 {
	public static void main(String[] args) {
		List<Emp> list = new Demo08().findAll2();
		System.out.println(list);
		System.out.println(list.size());
	}
	
	

	public List<Emp> findAll2(){
		Statement stmt = null; 
		Connection conn = null; 
		ResultSet rs = null;
		List<Emp> list = null;
		
		try {
//			// 1.注册驱动
//			Class.forName("com.mysql.jdbc.Driver");
//			// 2.获取Connection对象
			conn = JDBCUtils.getConnection();
			// 3.定义SQL
			String str = "SELECT * FROM employees;";
			// 4.获取执行sql对象Statement
			stmt = conn.createStatement();
			// 5.执行SQL语句
			rs = stmt.executeQuery(str);

			// 6.遍历结果集,封装对象,装在集合
			Emp emp = null; //提前定义好,放置每次循环重复创建对象,占用过多的栈内存!
		    list = new ArrayList<Emp>();
			while (rs.next()) {
				// 获取数据
				int employee_id = rs.getInt("employee_id");
				String first_name = rs.getString("first_name");
				String last_name = rs.getString("last_name");
				String email = rs.getString("email");
				String phone_number = rs.getString("phone_number");
				String job_id = rs.getString("job_id");
				double salary = rs.getDouble("salary");
				double commission_pct = rs.getDouble("commission_pct");
				int manager_id = rs.getInt("manager_id");
				int department_id = rs.getInt("department_id");
				Date hiredate = rs.getDate("hiredate");
				
				// 创建对象并赋值
				emp = new Emp();
				emp.setEmployee_id(employee_id);
				emp.setFirst_name(first_name);
				emp.setLast_name(last_name);
				emp.setEmail(email);
				emp.setPhone_number(phone_number);
				emp.setJob_id(job_id);
				emp.setSalary(salary);
				emp.setCommission_pct(commission_pct);
				emp.setManager_id(manager_id);
				emp.setDepartment_id(department_id);
				emp.setHiredate(hiredate);
				
				// 装载集合
				list.add(emp);
			}
						
		} catch (SQLException e) {
			e.printStackTrace();
		} finally{
			JDBCUtils.close(rs, stmt,conn);
		}
		return list;
	}
}
//略了一部分数据
[Emp [employee_id=100, first_name=Steven, last_name=K_ing, email=SKING, phone_number=515.123.4567, job_id=AD_PRES, salary=24000.0, commission_pct=0.0, manager_id=0, department_id=90, hiredate=1992-04-03], Emp [employee_id=101, first_name=Neena, last_name=Kochhar, email=NKOCHHAR, phone_number=515.123.4568, job_id=AD_VP, salary=17000.0, commission_pct=0.0, manage.............]
107

【说明】:代码变得简洁干净。

9.案例分析:登录账户

数据库user中的账户及密码情况:

avatar

配置文件:

url=jdbc:mysql:///test
user=root
password=19991204
driver=com.mysql.jdbc.Driver
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
import java.sql.PreparedStatement;

public class Demo09 {
	public static void main(String[] args) {
		//1.键盘录入,接受用户名和密码
		Scanner sc = new Scanner(System.in);
		System.out.println("请输入用户名: ");
		String username = sc.nextLine();
		System.out.println("请输入密码: ");
		String password = sc.nextLine();
		//2.调用方法
		boolean flag = new Demo09().login(username, password);
		//3.判断结果
		if(flag){
			System.out.println("登陆成功!");
		}else{
			System.out.println("用户名或密码错误!");
		}
	}
	
	// 登陆方法
	public boolean login(String username, String password){
		if(username == null || password == null){
			return false;
		}
		
		Statement stmt = null; 
		Connection conn = null; 
		ResultSet rs = null;
		
		//连接数据库
		//1.获取连接
		try {
			conn = JDBCUtils.getConnection();
			//2.定义SQL
			String sql = "select * from user where username = '"+username+"' and password = '"+password+"' ";
			//3.获取执行SQL的对象
			stmt = conn.createStatement();
			//4.执行查询
			rs = stmt.executeQuery(sql);
			//5.判断
			return rs.next(); //如果有下一行,则返回true
			
		} catch (SQLException e) {
			e.printStackTrace();
		} finally{
			JDBCUtils.close(rs, stmt,conn);
		}
		
		return false;
	}
}

请输入用户名: 
zt
请输入密码: 
123456
登陆成功!

10.安全问题---SQL注入及PreparedStatement

还在上面的案例中,用户名随机输入,在密码栏中输入a' or 'a' = 'a,发现竟然登陆成功!!!账户与密码信息没有出现在数据库中的user表中,却可以登陆成功!

请输入用户名: 
123
请输入密码: 
a' or 'a' = 'a
登陆成功!

【说明】:SQL语句变成了“select * from user where username = '123' and password = 'a' or 'a' = 'a'”

SQL注入问题:在拼接SQL时,有一些SQL的特殊关键字与字符串拼接,会造成安全问题。

预编译的SQL:参数使用?作为占位符

解决方案:使用PreparedStatement对象来解决

  1. 定义SQL语句时候,利用?作为占位符
  2. 获取执行SQL语句的对象 PreparedStatement Connection.prepareStatement(String sql)
  3. 给?赋值:利用setXxx(参数1,参数2)

【注意】:参数1:?的位置编号,从1开始;参数2:?的值

再重新利用PreparedStatement来实现一个新的登陆方法:

// 登陆方法 【注意】:利用了PreparedStatement实现
	public boolean login2(String username, String password) {
		if (username == null || password == null) {
			return false;
		}

		PreparedStatement pstmt = null;
		Connection conn = null;
		ResultSet rs = null;

		// 连接数据库
		// 1.获取连接
		try {
			conn = JDBCUtils.getConnection();
			// 2.定义SQL
			String sql = "select * from user where username = ? and password = ?";
			// 3.获取执行SQL的对象
//			stmt = conn.createStatement();
			pstmt = conn.prepareStatement(sql);
			//给?赋值
			pstmt.setString(1, username);
			pstmt.setString(2, password);
			// 4.执行查询
//			rs = stmt.executeQuery(sql);
			rs = pstmt.executeQuery();
			// 5.判断
			return rs.next(); // 如果有下一行,则返回true

		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			JDBCUtils.close(rs, pstmt, conn);
		}

		return false;
	}
请输入用户名: 
123
请输入密码: 
a' or 'a' = 'a
登陆失败!

11.JDBC控制事务---Connection

事务:一个包含多个步骤的业务操作。如果这个业务操作被事务管理,则多个步骤要么同时成功,要么同时失败。

  1. 开启事务:void setAutoCommit(boolean autoCommit)
  2. 提交事务:void commit()
  3. 回滚事务:rollback()

【说明】:例如如果在记账的时候,由于程序中间出现错误导致程序中断,就会造成一部分员工的工资改变,一部分人的工资没变,产生巨大的影响。

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;

public class Demo10 {
	public static void main(String[] args) {
		PreparedStatement pstmt1 = null;
		PreparedStatement pstmt2 = null;
		Connection conn = null;
		ResultSet rs = null;
		
		try {
			// 1.获取连接
			conn = JDBCUtils.getConnection();
			//----------------------开启事务-----------------------
			conn.setAutoCommit(false);
			// 2.定义SQL
			String sql1 = "update counts set balance = balance - ? where id = ?";
			String sql2 = "update counts set balance = balance + ? where id = ?";
			// 3.获取执行SQL的对象
			pstmt1 = conn.prepareStatement(sql1);
			pstmt2 = conn.prepareStatement(sql2);
			// 4.给?赋值
			pstmt1.setDouble(1, 500);
			pstmt1.setInt(2, 1);
			pstmt2.setDouble(1, 500);
			pstmt2.setInt(2, 2);
			// 5.执行sql
			pstmt1.executeUpdate();
			int i = 3/0;   //故意写出的错误!!!!!
			pstmt2.executeUpdate();
			//----------------------提交事务-----------------------
			conn.commit();

		} catch (SQLException e) {
			//事务回滚
			try {
				if(conn != null){
					conn.rollback();
				}
			} catch (SQLException e1) {
				e1.printStackTrace();
			}
			e.printStackTrace();
		} finally {
			JDBCUtils.close(pstmt1, conn);
			JDBCUtils.close(pstmt2, conn);
		}

	}
}

Exception in thread "main" java.lang.ArithmeticException: / by zero
	at Demo10.main(Demo10.java:33)

【说明】:程序中间出现错误,导致中断,两个SQL语句都不执行!

Java
MySql
  • 作者:李延松(联系作者)
  • 发表时间:2020-09-03 14:19
  • 版本声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)
  • 公众号转载:请在文末添加作者公众号二维码

评论

留言