admin管理员组

文章数量:1033039

JavaWeb后端入门1

一、前期准备

1、数据库的安装

此次测试使用的版本为mysql-5.5.62-win64 ,下载链接如下

普通网络

北京电信

辽宁电信

安装说明:点击查看

2、Java jdk安装

使用官网下载的jdk-15.0.2_windows-x64_bin

3、Eclipse安装

4、mysql的java驱动包

mysql驱动包为mysql-connector-java-5.1.7-bin.jar

点击下载

二、基本使用

2.1创建工程,引入jar包

2.2 JDBC开发步骤

加载驱动

获得链接

基本操作(创建操作对象、编写SQL、执行SQL)

释放资源

2.3代码实现(仅为演示,不标准)

SRC目录下新建包,新建类

代码语言:javascript代码运行次数:0运行复制
package com.itheima.jdbc.demo1;

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

import org.junit.Test;
//JDBC入门程序
public class JDBCDemo1 {
	@Test
	public void demo1() throws Exception {
		//1.加载驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2.获得链接
		Connection conn =  DriverManager.getConnection("jdbc:mysql://IP:3306/数据库名", "数据库用户名", "数据库密码");
		//3.基本操作 SQL语句
		//3.1获取执行SQL语句的对象
		Statement Statement =  conn.createStatement();
		//3.2编写SQL语句
		String sql = "select * from user";
		//3.3执行SQL
		ResultSet rs = Statement.executeQuery(sql);
		//3.4遍历结果集
		while(rs.next()) {
			System.out.print(rs.getInt("id")+" ");
			System.out.print(rs.getString("username")+" ");
			System.out.print(rs.getString("password")+" ");
			System.out.print(rs.getString("nickname")+" ");
			System.out.print(rs.getInt("age"));
			System.out.println();
		}
		//4.释放资源
		rs.close();
		Statement.close();
		conn.close();
	}
}

三、JDBC的常用API

3.1 Drivermanager接口

作用有两个:注册驱动、获得连接

注册驱动:一般不使用这个API注册驱动,而是采取以下语句注册

代码语言:javascript代码运行次数:0运行复制
Class.forName("com.mysql.jdbc.Driver");

获得连接:使用getconnection方法

代码语言:javascript代码运行次数:0运行复制
Connection conn =  DriverManager.getConnection("jdbc:mysql://IP:3306/数据库名", "user", "password");

如果为本地的数据库,且端口为3306,则localhost:3306可以省略,即url部分可以简化为jdbc:mysql:///数据库名

3.2 Connection接口

作用有两个:创建执行SQL语句的对象、管理事务

创建对象:createStatement( )方法、prepareCall( )方法、prepareStatement( )方法

Statement用来执行SQL语句、CallableStatement用来执行数据库中的存储过程、PrepareStatement用来执行SQL语句,预处理,解决SQL注入漏洞

管理事务:setAutoCommit方法、commit方法、rollback方法

3.3 Statement接口

作用:执行SQL语句、执行批处理

①执行SQL语句:execute方法、executeQuery方法、executeUpdate方法

boolean execute(string sql)查询、修改、添加、删除,返回true

ResultSet executeQuery(string sql)执行查询select语句

int executeUpdate(string sql)执行修改,添加,删除,返回修改的行数

②执行批处理语句:addBatch语句、clearBatch语句、executeBatch语句

3.4 ResultSet接口

**只有select查询才会有ReslutSet结果,

一般使用getxxx( )方法的重载

代码语言:javascript代码运行次数:0运行复制
ResultSet rs = statement.executeQuery(sql);
rs.getint("age");
rs.getString("name");

四、资源回收

代码语言:javascript代码运行次数:0运行复制
if(stmt != null) {
	try {
		stmt.close();
	} catch (SQLException e) {
		// TODO 自动生成的 catch 块
		e.printStackTrace();
	}
	stmt = null;
}
if(conn != null) {
	try {
		conn.close();
	} catch (SQLException e) {
		// TODO 自动生成的 catch 块
		e.printStackTrace();
	}
	conn = null;
}

五、增删改查(CRUD)、提取抽象类、从配置文件提取配置信息

5.1CRUD——增加

代码语言:javascript代码运行次数:0运行复制
package com.itheima.jdbc.demo2;
/*IDBC的增删改查*/

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

import org.junit.Test;

public class JDBCDemo2 {
public void demo1() {
	//1.定义
	Connection conn = null;
	Statement stmt = null;
	try {
		//注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//获得链接
		conn = DriverManager.getConnection("jdbc:mysql://ip:3306/web_test3", "root", "password");
		//执行操作:
		//创建执行SQL语句的对象
		stmt = conn.createStatement();
		//编写SQL
		String sql = "insert into user values (null,'eee','123','阿黄','21')";
		//执行SQL
		int num = stmt.executeUpdate(sql);
		if(num>0) {
			System.out.println("保存用户成功!");
		}else {
			System.out.println("失败!");
		}
	} catch (Exception e) {
		// TODO: handle exception
		e.printStackTrace();
	}finally {
		if(stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			stmt = null;
		}
		if(conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			conn = null;
		}
	}
}
}

5.2 CRUD——修改

代码语言:javascript代码运行次数:0运行复制
@Test
//修改操作的代码实现
public void Demo2() {
	Connection conn = null;
	Statement stmt = null;
	try {
		//注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//获得链接
		conn = DriverManager.getConnection("jdbc:mysql://ip:3306/web_test3", "root", "password");
		//执行操作
		//创建对象
		stmt = conn.createStatement();
		//编写sql
		String sql = "update user set password= 'abc',nickname='旺财' where id =5";
		//执行SQL
		int num = stmt.executeUpdate(sql);
		if (num>0) {
			System.out.println("修改信息成功!");
		}else {
			System.out.println("修改失败!");
		}
	} catch (Exception e) {
		// TODO: handle exception
		e.printStackTrace();
	}finally {
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			stmt = null;
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			conn = null;
		}
	}
}

5.3 CRUD——删除

代码语言:javascript代码运行次数:0运行复制
@Test
//删除操作
public void Demo3() {
	Connection conn = null;
	Statement stmt = null;
	try {
		//注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//获得链接
		conn = DriverManager.getConnection("jdbc:mysql://ip:3306/web_test3", "root", "password");
		//执行操作
		//获得对象
		stmt = conn.createStatement();
		//编写SQL
		String sql = "delete from user where id = 6";
		//执行SQL
		int num = stmt.executeUpdate(sql);
		if (num > 0 ) {
			System.out.println("删除成功!");
		}else {
			System.out.println("删除失败");
		}
	} catch (Exception e) {
		e.printStackTrace();
		// TODO: handle exception
	}finally {
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			stmt = null;
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			conn = null;
		}
	}
}

5.4 CRUD——查询多条记录

代码语言:javascript代码运行次数:0运行复制
@Test
//查询多条记录
public void Demo4() {
	Connection conn = null;
	Statement stmt = null;
	ResultSet rs = null;
	try {
		//注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//获得链接
		conn = DriverManager.getConnection("jdbc:mysql://ip:3306/web_test3", "root", "password");
		//执行操作
		//创建执行SQL语句的对象
		stmt = conn.createStatement();
		//编写SQL
		String sql = "select * from user";
		//执行SQL
		rs = stmt.executeQuery(sql);
		while (rs.next()) {
			System.out.println(rs.getInt("id")+ " "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("nickname")+" "+rs.getInt("age"));				
		}
	} catch (Exception e) {
		e.printStackTrace();
		// TODO: handle exception
	}finally {
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			stmt = null;
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			conn = null;
		}
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			rs = null;
		}
	}
}

5.5 CRUD——查询一条记录

代码语言:javascript代码运行次数:0运行复制
@Test
//查询一条记录
public void Demo5() {
	Connection conn = null;
	Statement stmt = null;
	ResultSet rs = null;
	try {
		//注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//获得链接
		conn = DriverManager.getConnection("jdbc:mysql://ip:3306/web_test3", "root", "password");
		//执行操作
		//创建执行SQL语句的对象
		stmt = conn.createStatement();
		//编写SQL
		String sql = "select * from user where id =4";
		//执行SQL
		rs = stmt.executeQuery(sql);
		if (rs.next()) {
			System.out.println(rs.getInt("id")+ " "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("nickname")+" "+rs.getInt("age"));				
		}
	} catch (Exception e) {
		e.printStackTrace();
		// TODO: handle exception
	}finally {
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			stmt = null;
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			conn = null;
		}
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			rs = null;
		}
	}
}

5.6 提取抽象类

把数据连接、数据释放封装成一个类

新建一个utils包,包下新建一个JDBCUtils.java类(下面程序的代码都是基于这个类)

代码语言:javascript代码运行次数:0运行复制
package com.itheima.jdbc.utils;
/*JDBC工具类*/

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 *注册驱动的方法 
 **/
public static void loadDriver() {
	try {
		Class.forName(driverClassName);
	} catch (ClassNotFoundException e) {
		// TODO 自动生成的 catch 块
		e.printStackTrace();
	}
}
/**
 *获得链接的方法 
 **/
public static Connection getConnection() {
	Connection conn=null;
	try {
		//将驱动注册
		loadDriver();
		//获得链接
		conn = DriverManager.getConnection("jdbc:mysql://ip:3306/web_test3", "root", "password");
	} catch (SQLException e) {
		// TODO 自动生成的 catch 块
		e.printStackTrace();
	}
	return conn;
}

/**
 *资源释放的方法 
 **/
public static void release(Statement stmt,Connection conn) {
	if (stmt != null) {
		try {
			stmt.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		stmt = null;
	}
	if (conn != null) {
		try {
			conn.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		conn = null;
	}
}
public static void release(ResultSet rs,Statement stmt,Connection conn) {
	if (stmt != null) {
		try {
			stmt.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		stmt = null;
	}
	if (conn != null) {
		try {
			conn.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		conn = null;
	}
	if (rs != null) {
		try {
			rs.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			rs = null;
		}
	}

}

5.7 读取配置文件中的数据

将数据库ip、用户名、密码等数据写在配置文件中,这样当数据库发生改变时,不需要修改源代码即可实现。

①src目录下新建db.properties文件,采用键值对的形式书写。

代码语言:javascript代码运行次数:0运行复制
driverClassName=com.mysql.jdbc.Driver
url = jdbc:mysql://ip:3306/web_test3
username= root
password = 密码

②在 JDBCUtils.java 类中加入以下内容

代码语言:javascript代码运行次数:0运行复制
public class JDBCUtils {
	private static final String driverClassName;
	private static final String url;
	private static final String username;
	private static final String password;
	
	static {
		//获取属性文件中的内容
		Properties properties = new Properties();
		try {
			properties.load(new FileInputStream("src/db.properties"));
		} catch (FileNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
		driverClassName= properties.getProperty("driverClassName");
		url= properties.getProperty("url");
		username= properties.getProperty("username");
		password= properties.getProperty("password");
	}

六、SQL注入漏洞及解决

6.1代码演示

创建一个java类,命名为UserDao.java

代码语言:javascript代码运行次数:0运行复制
package com.itheima.jdbc.demo4;
/*
 * 基本登录功能
 * */
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import com.itheima.jdbc.utils.JDBCUtils;

public class UserDao {
	public boolean login(String username,String password) {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		//定义一个变量
		boolean flag = false;
		try {
			//获得连接
			conn = JDBCUtils.getConnection();
			//完成登录功能
			//创建执行SQL语句的对象
			stmt = conn.createStatement();
			//编写SQL语句
			String sql = "select * from user where username= '"+username+"' and password = '"+password+"'";
			//执行SQL语句
			rs=stmt.executeQuery(sql);
			if (rs.next()) {
				//说明根据用户名和密码可以查询到这条记录
				flag = true;
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally {
			JDBCUtils.release(rs, stmt, conn);
		}
		return flag;
		
	}
}

登录测试

代码语言:javascript代码运行次数:0运行复制
package com.itheima.jdbc.demo4;
/*
 * SQL注入漏洞
 * */
import org.junit.Test;

public class JDBCDemo4 {
	@Test
	/*注入漏洞演示*/
	public void demo1() {
		UserDao userDao = new UserDao();
//		boolean flag = userDao.login("aaa'or'1=1", "123123");
//		boolean flag = userDao.login("aaa'-- ", "123123");
		boolean flag = userDao.login("aaa'-- ", "123123");
		if (flag) {
			System.out.println("登陆成功!");
		}else {
			System.out.println("登陆失败!");
		}
	}
}

用户名为aaa' or ' 1=1或者aaa' -- 即使随意输入密码也会登录成功。

6.2解决方法

使用preparedstatement方法, UserDao.java 改为:

代码语言:javascript代码运行次数:0运行复制
public boolean login(String username,String password) {
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	boolean flag=false;
	try {
		//获得连接
		conn = JDBCUtils.getConnection();
		//编写SQL
		String sql = "select * from user where username = ? and password = ?";
		//预编译SQL
		pstmt = conn.prepareStatement(sql);
		//设置相关参数
		pstmt.setString(1, username);
		pstmt.setString(2, password);
		//执行SQL
		rs = pstmt.executeQuery();
		if (rs.next()) {
			//说明根据用户名和密码可以查询到这条记录
			flag = true;
		}
	} catch (Exception e) {
		// TODO: handle exception
			e.printStackTrace();
		}finally {
			JDBCUtils.release(rs, pstmt, conn);
		}
		return flag;
	}
}

七. PrepareStatement的CRUD操作

直接放代码

代码语言:javascript代码运行次数:0运行复制
package com.itheima.jdbc.demo2;
/*JDBC的增删改查*/

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

import org.junit.Test;

public class JDBCDemo2 {
	@Test
	//查询一条记录
	public void Demo5() {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			//注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			//获得链接
			conn = DriverManager.getConnection("jdbc:mysql://43.226.152.21:3306/web_test3", "root", "Qq1991101313");
			//执行操作
			//创建执行SQL语句的对象
			stmt = conn.createStatement();
			//编写SQL
			String sql = "select * from user where id =4";
			//执行SQL
			rs = stmt.executeQuery(sql);
			if (rs.next()) {
				System.out.println(rs.getInt("id")+ " "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("nickname")+" "+rs.getInt("age"));				
			}
		} catch (Exception e) {
			e.printStackTrace();
			// TODO: handle exception
		}finally {
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				stmt = null;
			}
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				conn = null;
			}
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				rs = null;
			}
		}
	}
	@Test
	//查询多条记录
	public void Demo4() {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			//注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			//获得链接
			conn = DriverManager.getConnection("jdbc:mysql://43.226.152.21:3306/web_test3", "root", "Qq1991101313");
			//执行操作
			//创建执行SQL语句的对象
			stmt = conn.createStatement();
			//编写SQL
			String sql = "select * from user";
			//执行SQL
			rs = stmt.executeQuery(sql);
			while (rs.next()) {
				System.out.println(rs.getInt("id")+ " "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("nickname")+" "+rs.getInt("age"));				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				stmt = null;
			}
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				conn = null;
			}
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				rs = null;
			}
		}
	}
	
	@Test
	//删除操作
	public void Demo3() {
		Connection conn = null;
		Statement stmt = null;
		try {
			//注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			//获得链接
			conn = DriverManager.getConnection("jdbc:mysql://43.226.152.21:3306/web_test3", "root", "Qq1991101313");
			//执行操作
			//获得对象
			stmt = conn.createStatement();
			//编写SQL
			String sql = "delete from user where id = 6";
			//执行SQL
			int num = stmt.executeUpdate(sql);
			if (num > 0 ) {
				System.out.println("删除成功!");
			}else {
				System.out.println("删除失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
			// TODO: handle exception
		}finally {
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				stmt = null;
			}
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}
	
	@Test
	//修改操作的代码实现
	public void Demo2() {
		Connection conn = null;
		Statement stmt = null;
		try {
			//注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			//获得链接
			conn = DriverManager.getConnection("jdbc:mysql://43.226.152.21:3306/web_test3", "root", "Qq1991101313");
			//执行操作
			//创建对象
			stmt = conn.createStatement();
			//编写sql
//			String sql = "update user set password= 'abc',nickname='旺财' where id =5";
			String sql = "update user set password= 'abc',nickname='旺财' where id =5";
			//执行SQL
			int num = stmt.executeUpdate(sql);
			if (num>0) {
				System.out.println("修改信息成功!");
			}else {
				System.out.println("修改失败!");
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally {
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				stmt = null;
			}
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}
	
	@Test
	//保存操作的代码实现
	public void demo1() {
		//1.定义
		Connection conn = null;
		Statement stmt = null;
		try {
			//注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			//获得链接
			conn = DriverManager.getConnection("jdbc:mysql://43.226.152.21:3306/web_test3", "root", "Qq1991101313");
			//执行操作:
			//创建执行SQL语句的对象
			stmt = conn.createStatement();
			//编写SQL
			String sql = "insert into user values (null,'eee','123','阿黄','21')";
			//执行SQL
			int num = stmt.executeUpdate(sql);
			if(num>0) {
				System.out.println("保存用户成功!");
			}else {
				System.out.println("失败!");
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally {
			if(stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				stmt = null;
			}
			if(conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}
}

八. JDBC的批处理操作

8.1 什么是批处理

之前进行JDBC操作的时候,都是一条SQL语句执行。使用批处理,可以将一批SQL一起执行。

8.2 基本使用方法

不使用PreparedStatement方法

代码语言:javascript代码运行次数:0运行复制
public class JDBCDemo6 {
	@Test
	/*
	 *没有使用PreparedStatement方法 
	 *
	 **/
	public void demo1() {
		Connection conn = null;
		Statement stmt = null;
		try {
			//获得连接
			conn = JDBCUtils.getConnection();
			//创建执行批处理的对象:Statement
			stmt = conn.createStatement();
			//编写一批SQL语句
			String sql1 = "create database test1";
			String sql2 = "use test1";
			String sql3 = "create table user(id int primary key auto_increment,name varchar(20))";
			String sql4 = "insert into user values (null,'aaa')";
			String sql5 = "insert into user values (null,'bbb')";
			String sql6 = "insert into user values (null,'ccc')";
			String sql7 = "update user set name = 'mmm' where id =2";
			String sql8 = "delete from user where id =1";
			//添加到批处理
			stmt.addBatch(sql1);
			stmt.addBatch(sql2);
			stmt.addBatch(sql3);
			stmt.addBatch(sql4);
			stmt.addBatch(sql5);
			stmt.addBatch(sql6);
			stmt.addBatch(sql7);
			stmt.addBatch(sql8);
			//执行批处理
			stmt.executeBatch();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			JDBCUtils.release(stmt, conn);
		}
	}
}

使用 PreparedStatement方法

注意默认情况下MySQL的批处理是没有开启的,需要在url后面拼接一个参数 ?rewriteBatchedStatements=true!!

代码语言:javascript代码运行次数:0运行复制
public class JDBCDemo6 {
/*使用PreparedStatement插入*/
	
	//默认情况下MySQL的批处理是没有开启的,需要在url后面拼接一个参数
	@Test
	public void demo2() {
		//记录一下插入数据使用的时间
		//开始时间
		long begin = System.currentTimeMillis();
		Connection conn = null;
		PreparedStatement pstmt = null;
		try {
			//获得连接
			conn = JDBCUtils.getConnection();
			//编写SQL语句
			String sql = "insert into user values (null,?)";
			//预编译SQL
			pstmt = conn.prepareStatement(sql);
			for(int i=1;i<=10000;i++) {
				pstmt.setString(1, "name"+i);
				//添加到批处理
				pstmt.addBatch();
				//注意问题:一次性处理太多数据有可能会导致内存溢出
				//执行批处理,每执行1000次,清除内存
				if (i%1000 == 0) {
					//执行批处理
					pstmt.executeBatch();
					//清空批处理
					pstmt.clearBatch();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			JDBCUtils.release(pstmt, conn);
		}
		long end = System.currentTimeMillis();
		System.out.print("数据插入时间为(单位ms):");
		System.out.println(end-begin);
	}
	
}

九. 事务管理

9.1 事务的概念

事务指的是逻辑上的一组操作,组成这组操作各个逻辑单元要么全都成功,要么全都失败。

9.2 事务环境的准备

  • 创建数据库和表
代码语言:javascript代码运行次数:0运行复制
create database web_test4;
use web_test4;
create table account(
	id int primary key auto_increment,
	name varchar(20),
	money double
);
insert into account values(null,'aaa',10000);
insert into account values(null,'bbb',10000);
insert into account values(null,'ccc',10000);
  • 转账案例代码实现
代码语言:javascript代码运行次数:0运行复制
package com.itheima.trasaction.demo1;

import java.sql.Connection;
import java.sql.PreparedStatement;

import org.junit.Test;

import com.itheima.jdbc.utils.JDBCUtils;

/*
 * 事务管理测试类
 * */
public class TransactionDemo1 {
	@Test
	/*
	 * 完成转账案例
	 * */
	public void demo1() {
		Connection conn = null;
		PreparedStatement pstmt = null;
		try {
			//获取连接
			conn = JDBCUtils.getConnection();
			//编写SQL
			/*转账代码,一个账户扣钱,一个账户加钱:用aaa账号给 bbb账号转1000
			 * */
			String sql = "update account set money = money +? where name = ?";
			//预编译SQL
			pstmt = conn.prepareStatement(sql);
			//设置参数
			pstmt.setDouble(1, -1000);
			pstmt.setString(2, "aaa");
			//执行SQL:扣除aaa账号1000
			pstmt.executeUpdate();
			/* ########################################################## */
			//给bbb增加1000
			pstmt.setDouble(1, 1000);
			pstmt.setString(2, "bbb");
			pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			JDBCUtils.release(pstmt, conn);
		}
	}
}

此时如果认为在###处增加一个错误,那么会发生以下情况:aaa的钱被转走了,但是bbb的钱没有增加

  • 添加事务管理
代码语言:javascript代码运行次数:0运行复制
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.junit.Test;

import com.itheima.jdbc.utils.JDBCUtils;

/*
 * 事务管理测试类
 * */
public class TransactionDemo1 {
	@Test
	/*
	 * 完成转账案例
	 * */
	public void demo1() {
		Connection conn = null;
		PreparedStatement pstmt = null;
		try {
			//获取连接
			conn = JDBCUtils.getConnection();
			//开启事务
			conn.setAutoCommit(false);
			//编写SQL
			/*转账代码,一个账户扣钱,一个账户加钱:用aaa账号给 bbb账号转1000
			 * */
			String sql = "update account set money = money +? where name = ?";
			//预编译SQL
			pstmt = conn.prepareStatement(sql);
			//设置参数
			pstmt.setDouble(1, -1000);
			pstmt.setString(2, "aaa");
			//执行SQL:扣除aaa账号1000
			pstmt.executeUpdate();
			/* #######################人为发生异常########################## */
			int i =1/0;
			/* ########################################################## */
			//给bbb增加1000
			pstmt.setDouble(1, 1000);
			pstmt.setString(2, "bbb");
			pstmt.executeUpdate();
			
			//提交事务
			connmit();
		} catch (Exception e) {
			//发生异常时回滚
			try {
				conn.rollback();
			} catch (SQLException e1) {
				// TODO 自动生成的 catch 块
				e1.printStackTrace();
			}
			e.printStackTrace();
		}finally {
			JDBCUtils.release(pstmt, conn);
		}
	}
}

此时在在中间发生异常之后,aaa的钱也不会减少。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2021-04-07 ,如有侵权请联系 cloudcommunity@tencent 删除后端入门eclipsejdbcnull

JavaWeb后端入门1

一、前期准备

1、数据库的安装

此次测试使用的版本为mysql-5.5.62-win64 ,下载链接如下

普通网络

北京电信

辽宁电信

安装说明:点击查看

2、Java jdk安装

使用官网下载的jdk-15.0.2_windows-x64_bin

3、Eclipse安装

4、mysql的java驱动包

mysql驱动包为mysql-connector-java-5.1.7-bin.jar

点击下载

二、基本使用

2.1创建工程,引入jar包

2.2 JDBC开发步骤

加载驱动

获得链接

基本操作(创建操作对象、编写SQL、执行SQL)

释放资源

2.3代码实现(仅为演示,不标准)

SRC目录下新建包,新建类

代码语言:javascript代码运行次数:0运行复制
package com.itheima.jdbc.demo1;

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

import org.junit.Test;
//JDBC入门程序
public class JDBCDemo1 {
	@Test
	public void demo1() throws Exception {
		//1.加载驱动
		Class.forName("com.mysql.jdbc.Driver");
		//2.获得链接
		Connection conn =  DriverManager.getConnection("jdbc:mysql://IP:3306/数据库名", "数据库用户名", "数据库密码");
		//3.基本操作 SQL语句
		//3.1获取执行SQL语句的对象
		Statement Statement =  conn.createStatement();
		//3.2编写SQL语句
		String sql = "select * from user";
		//3.3执行SQL
		ResultSet rs = Statement.executeQuery(sql);
		//3.4遍历结果集
		while(rs.next()) {
			System.out.print(rs.getInt("id")+" ");
			System.out.print(rs.getString("username")+" ");
			System.out.print(rs.getString("password")+" ");
			System.out.print(rs.getString("nickname")+" ");
			System.out.print(rs.getInt("age"));
			System.out.println();
		}
		//4.释放资源
		rs.close();
		Statement.close();
		conn.close();
	}
}

三、JDBC的常用API

3.1 Drivermanager接口

作用有两个:注册驱动、获得连接

注册驱动:一般不使用这个API注册驱动,而是采取以下语句注册

代码语言:javascript代码运行次数:0运行复制
Class.forName("com.mysql.jdbc.Driver");

获得连接:使用getconnection方法

代码语言:javascript代码运行次数:0运行复制
Connection conn =  DriverManager.getConnection("jdbc:mysql://IP:3306/数据库名", "user", "password");

如果为本地的数据库,且端口为3306,则localhost:3306可以省略,即url部分可以简化为jdbc:mysql:///数据库名

3.2 Connection接口

作用有两个:创建执行SQL语句的对象、管理事务

创建对象:createStatement( )方法、prepareCall( )方法、prepareStatement( )方法

Statement用来执行SQL语句、CallableStatement用来执行数据库中的存储过程、PrepareStatement用来执行SQL语句,预处理,解决SQL注入漏洞

管理事务:setAutoCommit方法、commit方法、rollback方法

3.3 Statement接口

作用:执行SQL语句、执行批处理

①执行SQL语句:execute方法、executeQuery方法、executeUpdate方法

boolean execute(string sql)查询、修改、添加、删除,返回true

ResultSet executeQuery(string sql)执行查询select语句

int executeUpdate(string sql)执行修改,添加,删除,返回修改的行数

②执行批处理语句:addBatch语句、clearBatch语句、executeBatch语句

3.4 ResultSet接口

**只有select查询才会有ReslutSet结果,

一般使用getxxx( )方法的重载

代码语言:javascript代码运行次数:0运行复制
ResultSet rs = statement.executeQuery(sql);
rs.getint("age");
rs.getString("name");

四、资源回收

代码语言:javascript代码运行次数:0运行复制
if(stmt != null) {
	try {
		stmt.close();
	} catch (SQLException e) {
		// TODO 自动生成的 catch 块
		e.printStackTrace();
	}
	stmt = null;
}
if(conn != null) {
	try {
		conn.close();
	} catch (SQLException e) {
		// TODO 自动生成的 catch 块
		e.printStackTrace();
	}
	conn = null;
}

五、增删改查(CRUD)、提取抽象类、从配置文件提取配置信息

5.1CRUD——增加

代码语言:javascript代码运行次数:0运行复制
package com.itheima.jdbc.demo2;
/*IDBC的增删改查*/

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

import org.junit.Test;

public class JDBCDemo2 {
public void demo1() {
	//1.定义
	Connection conn = null;
	Statement stmt = null;
	try {
		//注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//获得链接
		conn = DriverManager.getConnection("jdbc:mysql://ip:3306/web_test3", "root", "password");
		//执行操作:
		//创建执行SQL语句的对象
		stmt = conn.createStatement();
		//编写SQL
		String sql = "insert into user values (null,'eee','123','阿黄','21')";
		//执行SQL
		int num = stmt.executeUpdate(sql);
		if(num>0) {
			System.out.println("保存用户成功!");
		}else {
			System.out.println("失败!");
		}
	} catch (Exception e) {
		// TODO: handle exception
		e.printStackTrace();
	}finally {
		if(stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			stmt = null;
		}
		if(conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			conn = null;
		}
	}
}
}

5.2 CRUD——修改

代码语言:javascript代码运行次数:0运行复制
@Test
//修改操作的代码实现
public void Demo2() {
	Connection conn = null;
	Statement stmt = null;
	try {
		//注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//获得链接
		conn = DriverManager.getConnection("jdbc:mysql://ip:3306/web_test3", "root", "password");
		//执行操作
		//创建对象
		stmt = conn.createStatement();
		//编写sql
		String sql = "update user set password= 'abc',nickname='旺财' where id =5";
		//执行SQL
		int num = stmt.executeUpdate(sql);
		if (num>0) {
			System.out.println("修改信息成功!");
		}else {
			System.out.println("修改失败!");
		}
	} catch (Exception e) {
		// TODO: handle exception
		e.printStackTrace();
	}finally {
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			stmt = null;
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			conn = null;
		}
	}
}

5.3 CRUD——删除

代码语言:javascript代码运行次数:0运行复制
@Test
//删除操作
public void Demo3() {
	Connection conn = null;
	Statement stmt = null;
	try {
		//注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//获得链接
		conn = DriverManager.getConnection("jdbc:mysql://ip:3306/web_test3", "root", "password");
		//执行操作
		//获得对象
		stmt = conn.createStatement();
		//编写SQL
		String sql = "delete from user where id = 6";
		//执行SQL
		int num = stmt.executeUpdate(sql);
		if (num > 0 ) {
			System.out.println("删除成功!");
		}else {
			System.out.println("删除失败");
		}
	} catch (Exception e) {
		e.printStackTrace();
		// TODO: handle exception
	}finally {
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			stmt = null;
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			conn = null;
		}
	}
}

5.4 CRUD——查询多条记录

代码语言:javascript代码运行次数:0运行复制
@Test
//查询多条记录
public void Demo4() {
	Connection conn = null;
	Statement stmt = null;
	ResultSet rs = null;
	try {
		//注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//获得链接
		conn = DriverManager.getConnection("jdbc:mysql://ip:3306/web_test3", "root", "password");
		//执行操作
		//创建执行SQL语句的对象
		stmt = conn.createStatement();
		//编写SQL
		String sql = "select * from user";
		//执行SQL
		rs = stmt.executeQuery(sql);
		while (rs.next()) {
			System.out.println(rs.getInt("id")+ " "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("nickname")+" "+rs.getInt("age"));				
		}
	} catch (Exception e) {
		e.printStackTrace();
		// TODO: handle exception
	}finally {
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			stmt = null;
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			conn = null;
		}
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			rs = null;
		}
	}
}

5.5 CRUD——查询一条记录

代码语言:javascript代码运行次数:0运行复制
@Test
//查询一条记录
public void Demo5() {
	Connection conn = null;
	Statement stmt = null;
	ResultSet rs = null;
	try {
		//注册驱动
		Class.forName("com.mysql.jdbc.Driver");
		//获得链接
		conn = DriverManager.getConnection("jdbc:mysql://ip:3306/web_test3", "root", "password");
		//执行操作
		//创建执行SQL语句的对象
		stmt = conn.createStatement();
		//编写SQL
		String sql = "select * from user where id =4";
		//执行SQL
		rs = stmt.executeQuery(sql);
		if (rs.next()) {
			System.out.println(rs.getInt("id")+ " "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("nickname")+" "+rs.getInt("age"));				
		}
	} catch (Exception e) {
		e.printStackTrace();
		// TODO: handle exception
	}finally {
		if (stmt != null) {
			try {
				stmt.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			stmt = null;
		}
		if (conn != null) {
			try {
				conn.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			conn = null;
		}
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			rs = null;
		}
	}
}

5.6 提取抽象类

把数据连接、数据释放封装成一个类

新建一个utils包,包下新建一个JDBCUtils.java类(下面程序的代码都是基于这个类)

代码语言:javascript代码运行次数:0运行复制
package com.itheima.jdbc.utils;
/*JDBC工具类*/

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;

/**
 *注册驱动的方法 
 **/
public static void loadDriver() {
	try {
		Class.forName(driverClassName);
	} catch (ClassNotFoundException e) {
		// TODO 自动生成的 catch 块
		e.printStackTrace();
	}
}
/**
 *获得链接的方法 
 **/
public static Connection getConnection() {
	Connection conn=null;
	try {
		//将驱动注册
		loadDriver();
		//获得链接
		conn = DriverManager.getConnection("jdbc:mysql://ip:3306/web_test3", "root", "password");
	} catch (SQLException e) {
		// TODO 自动生成的 catch 块
		e.printStackTrace();
	}
	return conn;
}

/**
 *资源释放的方法 
 **/
public static void release(Statement stmt,Connection conn) {
	if (stmt != null) {
		try {
			stmt.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		stmt = null;
	}
	if (conn != null) {
		try {
			conn.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		conn = null;
	}
}
public static void release(ResultSet rs,Statement stmt,Connection conn) {
	if (stmt != null) {
		try {
			stmt.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		stmt = null;
	}
	if (conn != null) {
		try {
			conn.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		conn = null;
	}
	if (rs != null) {
		try {
			rs.close();
		} catch (SQLException e) {
			// TODO 自动生成的 catch 块
				e.printStackTrace();
			}
			rs = null;
		}
	}

}

5.7 读取配置文件中的数据

将数据库ip、用户名、密码等数据写在配置文件中,这样当数据库发生改变时,不需要修改源代码即可实现。

①src目录下新建db.properties文件,采用键值对的形式书写。

代码语言:javascript代码运行次数:0运行复制
driverClassName=com.mysql.jdbc.Driver
url = jdbc:mysql://ip:3306/web_test3
username= root
password = 密码

②在 JDBCUtils.java 类中加入以下内容

代码语言:javascript代码运行次数:0运行复制
public class JDBCUtils {
	private static final String driverClassName;
	private static final String url;
	private static final String username;
	private static final String password;
	
	static {
		//获取属性文件中的内容
		Properties properties = new Properties();
		try {
			properties.load(new FileInputStream("src/db.properties"));
		} catch (FileNotFoundException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		} catch (IOException e) {
			// TODO 自动生成的 catch 块
			e.printStackTrace();
		}
		
		driverClassName= properties.getProperty("driverClassName");
		url= properties.getProperty("url");
		username= properties.getProperty("username");
		password= properties.getProperty("password");
	}

六、SQL注入漏洞及解决

6.1代码演示

创建一个java类,命名为UserDao.java

代码语言:javascript代码运行次数:0运行复制
package com.itheima.jdbc.demo4;
/*
 * 基本登录功能
 * */
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import com.itheima.jdbc.utils.JDBCUtils;

public class UserDao {
	public boolean login(String username,String password) {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		//定义一个变量
		boolean flag = false;
		try {
			//获得连接
			conn = JDBCUtils.getConnection();
			//完成登录功能
			//创建执行SQL语句的对象
			stmt = conn.createStatement();
			//编写SQL语句
			String sql = "select * from user where username= '"+username+"' and password = '"+password+"'";
			//执行SQL语句
			rs=stmt.executeQuery(sql);
			if (rs.next()) {
				//说明根据用户名和密码可以查询到这条记录
				flag = true;
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally {
			JDBCUtils.release(rs, stmt, conn);
		}
		return flag;
		
	}
}

登录测试

代码语言:javascript代码运行次数:0运行复制
package com.itheima.jdbc.demo4;
/*
 * SQL注入漏洞
 * */
import org.junit.Test;

public class JDBCDemo4 {
	@Test
	/*注入漏洞演示*/
	public void demo1() {
		UserDao userDao = new UserDao();
//		boolean flag = userDao.login("aaa'or'1=1", "123123");
//		boolean flag = userDao.login("aaa'-- ", "123123");
		boolean flag = userDao.login("aaa'-- ", "123123");
		if (flag) {
			System.out.println("登陆成功!");
		}else {
			System.out.println("登陆失败!");
		}
	}
}

用户名为aaa' or ' 1=1或者aaa' -- 即使随意输入密码也会登录成功。

6.2解决方法

使用preparedstatement方法, UserDao.java 改为:

代码语言:javascript代码运行次数:0运行复制
public boolean login(String username,String password) {
	Connection conn = null;
	PreparedStatement pstmt = null;
	ResultSet rs = null;
	boolean flag=false;
	try {
		//获得连接
		conn = JDBCUtils.getConnection();
		//编写SQL
		String sql = "select * from user where username = ? and password = ?";
		//预编译SQL
		pstmt = conn.prepareStatement(sql);
		//设置相关参数
		pstmt.setString(1, username);
		pstmt.setString(2, password);
		//执行SQL
		rs = pstmt.executeQuery();
		if (rs.next()) {
			//说明根据用户名和密码可以查询到这条记录
			flag = true;
		}
	} catch (Exception e) {
		// TODO: handle exception
			e.printStackTrace();
		}finally {
			JDBCUtils.release(rs, pstmt, conn);
		}
		return flag;
	}
}

七. PrepareStatement的CRUD操作

直接放代码

代码语言:javascript代码运行次数:0运行复制
package com.itheima.jdbc.demo2;
/*JDBC的增删改查*/

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

import org.junit.Test;

public class JDBCDemo2 {
	@Test
	//查询一条记录
	public void Demo5() {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			//注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			//获得链接
			conn = DriverManager.getConnection("jdbc:mysql://43.226.152.21:3306/web_test3", "root", "Qq1991101313");
			//执行操作
			//创建执行SQL语句的对象
			stmt = conn.createStatement();
			//编写SQL
			String sql = "select * from user where id =4";
			//执行SQL
			rs = stmt.executeQuery(sql);
			if (rs.next()) {
				System.out.println(rs.getInt("id")+ " "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("nickname")+" "+rs.getInt("age"));				
			}
		} catch (Exception e) {
			e.printStackTrace();
			// TODO: handle exception
		}finally {
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				stmt = null;
			}
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				conn = null;
			}
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				rs = null;
			}
		}
	}
	@Test
	//查询多条记录
	public void Demo4() {
		Connection conn = null;
		Statement stmt = null;
		ResultSet rs = null;
		try {
			//注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			//获得链接
			conn = DriverManager.getConnection("jdbc:mysql://43.226.152.21:3306/web_test3", "root", "Qq1991101313");
			//执行操作
			//创建执行SQL语句的对象
			stmt = conn.createStatement();
			//编写SQL
			String sql = "select * from user";
			//执行SQL
			rs = stmt.executeQuery(sql);
			while (rs.next()) {
				System.out.println(rs.getInt("id")+ " "+rs.getString("username")+" "+rs.getString("password")+" "+rs.getString("nickname")+" "+rs.getInt("age"));				
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				stmt = null;
			}
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				conn = null;
			}
			if (rs != null) {
				try {
					rs.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				rs = null;
			}
		}
	}
	
	@Test
	//删除操作
	public void Demo3() {
		Connection conn = null;
		Statement stmt = null;
		try {
			//注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			//获得链接
			conn = DriverManager.getConnection("jdbc:mysql://43.226.152.21:3306/web_test3", "root", "Qq1991101313");
			//执行操作
			//获得对象
			stmt = conn.createStatement();
			//编写SQL
			String sql = "delete from user where id = 6";
			//执行SQL
			int num = stmt.executeUpdate(sql);
			if (num > 0 ) {
				System.out.println("删除成功!");
			}else {
				System.out.println("删除失败");
			}
		} catch (Exception e) {
			e.printStackTrace();
			// TODO: handle exception
		}finally {
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				stmt = null;
			}
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}
	
	@Test
	//修改操作的代码实现
	public void Demo2() {
		Connection conn = null;
		Statement stmt = null;
		try {
			//注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			//获得链接
			conn = DriverManager.getConnection("jdbc:mysql://43.226.152.21:3306/web_test3", "root", "Qq1991101313");
			//执行操作
			//创建对象
			stmt = conn.createStatement();
			//编写sql
//			String sql = "update user set password= 'abc',nickname='旺财' where id =5";
			String sql = "update user set password= 'abc',nickname='旺财' where id =5";
			//执行SQL
			int num = stmt.executeUpdate(sql);
			if (num>0) {
				System.out.println("修改信息成功!");
			}else {
				System.out.println("修改失败!");
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally {
			if (stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				stmt = null;
			}
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}
	
	@Test
	//保存操作的代码实现
	public void demo1() {
		//1.定义
		Connection conn = null;
		Statement stmt = null;
		try {
			//注册驱动
			Class.forName("com.mysql.jdbc.Driver");
			//获得链接
			conn = DriverManager.getConnection("jdbc:mysql://43.226.152.21:3306/web_test3", "root", "Qq1991101313");
			//执行操作:
			//创建执行SQL语句的对象
			stmt = conn.createStatement();
			//编写SQL
			String sql = "insert into user values (null,'eee','123','阿黄','21')";
			//执行SQL
			int num = stmt.executeUpdate(sql);
			if(num>0) {
				System.out.println("保存用户成功!");
			}else {
				System.out.println("失败!");
			}
		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally {
			if(stmt != null) {
				try {
					stmt.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				stmt = null;
			}
			if(conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
					// TODO 自动生成的 catch 块
					e.printStackTrace();
				}
				conn = null;
			}
		}
	}
}

八. JDBC的批处理操作

8.1 什么是批处理

之前进行JDBC操作的时候,都是一条SQL语句执行。使用批处理,可以将一批SQL一起执行。

8.2 基本使用方法

不使用PreparedStatement方法

代码语言:javascript代码运行次数:0运行复制
public class JDBCDemo6 {
	@Test
	/*
	 *没有使用PreparedStatement方法 
	 *
	 **/
	public void demo1() {
		Connection conn = null;
		Statement stmt = null;
		try {
			//获得连接
			conn = JDBCUtils.getConnection();
			//创建执行批处理的对象:Statement
			stmt = conn.createStatement();
			//编写一批SQL语句
			String sql1 = "create database test1";
			String sql2 = "use test1";
			String sql3 = "create table user(id int primary key auto_increment,name varchar(20))";
			String sql4 = "insert into user values (null,'aaa')";
			String sql5 = "insert into user values (null,'bbb')";
			String sql6 = "insert into user values (null,'ccc')";
			String sql7 = "update user set name = 'mmm' where id =2";
			String sql8 = "delete from user where id =1";
			//添加到批处理
			stmt.addBatch(sql1);
			stmt.addBatch(sql2);
			stmt.addBatch(sql3);
			stmt.addBatch(sql4);
			stmt.addBatch(sql5);
			stmt.addBatch(sql6);
			stmt.addBatch(sql7);
			stmt.addBatch(sql8);
			//执行批处理
			stmt.executeBatch();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			JDBCUtils.release(stmt, conn);
		}
	}
}

使用 PreparedStatement方法

注意默认情况下MySQL的批处理是没有开启的,需要在url后面拼接一个参数 ?rewriteBatchedStatements=true!!

代码语言:javascript代码运行次数:0运行复制
public class JDBCDemo6 {
/*使用PreparedStatement插入*/
	
	//默认情况下MySQL的批处理是没有开启的,需要在url后面拼接一个参数
	@Test
	public void demo2() {
		//记录一下插入数据使用的时间
		//开始时间
		long begin = System.currentTimeMillis();
		Connection conn = null;
		PreparedStatement pstmt = null;
		try {
			//获得连接
			conn = JDBCUtils.getConnection();
			//编写SQL语句
			String sql = "insert into user values (null,?)";
			//预编译SQL
			pstmt = conn.prepareStatement(sql);
			for(int i=1;i<=10000;i++) {
				pstmt.setString(1, "name"+i);
				//添加到批处理
				pstmt.addBatch();
				//注意问题:一次性处理太多数据有可能会导致内存溢出
				//执行批处理,每执行1000次,清除内存
				if (i%1000 == 0) {
					//执行批处理
					pstmt.executeBatch();
					//清空批处理
					pstmt.clearBatch();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			JDBCUtils.release(pstmt, conn);
		}
		long end = System.currentTimeMillis();
		System.out.print("数据插入时间为(单位ms):");
		System.out.println(end-begin);
	}
	
}

九. 事务管理

9.1 事务的概念

事务指的是逻辑上的一组操作,组成这组操作各个逻辑单元要么全都成功,要么全都失败。

9.2 事务环境的准备

  • 创建数据库和表
代码语言:javascript代码运行次数:0运行复制
create database web_test4;
use web_test4;
create table account(
	id int primary key auto_increment,
	name varchar(20),
	money double
);
insert into account values(null,'aaa',10000);
insert into account values(null,'bbb',10000);
insert into account values(null,'ccc',10000);
  • 转账案例代码实现
代码语言:javascript代码运行次数:0运行复制
package com.itheima.trasaction.demo1;

import java.sql.Connection;
import java.sql.PreparedStatement;

import org.junit.Test;

import com.itheima.jdbc.utils.JDBCUtils;

/*
 * 事务管理测试类
 * */
public class TransactionDemo1 {
	@Test
	/*
	 * 完成转账案例
	 * */
	public void demo1() {
		Connection conn = null;
		PreparedStatement pstmt = null;
		try {
			//获取连接
			conn = JDBCUtils.getConnection();
			//编写SQL
			/*转账代码,一个账户扣钱,一个账户加钱:用aaa账号给 bbb账号转1000
			 * */
			String sql = "update account set money = money +? where name = ?";
			//预编译SQL
			pstmt = conn.prepareStatement(sql);
			//设置参数
			pstmt.setDouble(1, -1000);
			pstmt.setString(2, "aaa");
			//执行SQL:扣除aaa账号1000
			pstmt.executeUpdate();
			/* ########################################################## */
			//给bbb增加1000
			pstmt.setDouble(1, 1000);
			pstmt.setString(2, "bbb");
			pstmt.executeUpdate();
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			JDBCUtils.release(pstmt, conn);
		}
	}
}

此时如果认为在###处增加一个错误,那么会发生以下情况:aaa的钱被转走了,但是bbb的钱没有增加

  • 添加事务管理
代码语言:javascript代码运行次数:0运行复制
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.junit.Test;

import com.itheima.jdbc.utils.JDBCUtils;

/*
 * 事务管理测试类
 * */
public class TransactionDemo1 {
	@Test
	/*
	 * 完成转账案例
	 * */
	public void demo1() {
		Connection conn = null;
		PreparedStatement pstmt = null;
		try {
			//获取连接
			conn = JDBCUtils.getConnection();
			//开启事务
			conn.setAutoCommit(false);
			//编写SQL
			/*转账代码,一个账户扣钱,一个账户加钱:用aaa账号给 bbb账号转1000
			 * */
			String sql = "update account set money = money +? where name = ?";
			//预编译SQL
			pstmt = conn.prepareStatement(sql);
			//设置参数
			pstmt.setDouble(1, -1000);
			pstmt.setString(2, "aaa");
			//执行SQL:扣除aaa账号1000
			pstmt.executeUpdate();
			/* #######################人为发生异常########################## */
			int i =1/0;
			/* ########################################################## */
			//给bbb增加1000
			pstmt.setDouble(1, 1000);
			pstmt.setString(2, "bbb");
			pstmt.executeUpdate();
			
			//提交事务
			connmit();
		} catch (Exception e) {
			//发生异常时回滚
			try {
				conn.rollback();
			} catch (SQLException e1) {
				// TODO 自动生成的 catch 块
				e1.printStackTrace();
			}
			e.printStackTrace();
		}finally {
			JDBCUtils.release(pstmt, conn);
		}
	}
}

此时在在中间发生异常之后,aaa的钱也不会减少。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2021-04-07 ,如有侵权请联系 cloudcommunity@tencent 删除后端入门eclipsejdbcnull

本文标签: JavaWeb后端入门1