原生的JDBC

1、JDBC连接数据的步骤

  1. 加载驱动
  2. 根据URL、用户名和密码建立连接
  3. 创建处理快,有静态处理快(Statement)和预处理块(PreparedStatement)
  4. 执行数据库语句
  5. 处理得到的结果
  6. 释放资源

2、连接

2.1、准备工作

  1. 导入驱动包
    在这里插入图片描述

  2. 构建路径 build path

  3. 测试用户是否正确登录

2.2、建立连接

  1. 连接字符串
    1. 加载驱动: oracle.jdbc.driver.OracleDriver
    2. URL:jdbc:oracle:thin:@db 服务器地址:端口:实例
    3. 连接URL:jdbc:oracle:thin:@localhost:1521:orcl
    4. 用户名和密码:SCOTT TIGER
  2. 编写测试类
    1. 加载驱动
    2. 建立连接:Connection con =DriverManager.getConnection(“jdbc:oracle:thin:@locahost:1521:orcl”,“scott”,“tiger”)

3、处理块

3.1、静态处理块

​ Statement 是 Java 执行数据库操作的一个重要接口,用于在已经建立数据库连接的基础上,向数据库发送要执行的 SQL 语句。Statement 对象,用于执行不带参数的简单 SQL 语句。 执行静态 SQL 语句并返回它所生成结果的对象。

特点:

  • 处理 不变的静态的 sql 语句
  • 优点: 直接查看sql ,方便处理错误
  • 缺点:性能不高、拼接 sql 麻烦、可能存在 sql 注入

方法的使用:

  • 增删改使用executeUpdate( )函数,返回一个int值,表示影响的行数。
  • 查询使用executeQurey()函数,返回一个ResultSet对象,该对象中封装着查询的信息
    • ResultSet对象必须先试用.next()函数判断是否有值,才能使用getInt/getString/getBoolean等方法获取到值(可以简单的使用getObject()方法获取到任意类型的数据),如果不使用.next()函数判断是否有值就直接获取值,则会出现java.sql.SQLException: 未调用 ResultSet.next异常。

代码:

/*
 * JDBC基本流程:
 * 	1.加载驱动 (选择哪一个数据库)
 * 	2.获取连接 (与数据库连接上)
 * 	3.准备sql
 * 	4.获取处理块(打包发送)
 * 	5.接收结果集
 * 	6.处理结果数据
 * 	7.关闭
 */

public class Demo01JDBC {
	
	public static void main(String[] args) throws Exception {
		
		//1.加载驱动 (选择哪一个数据库)
		Class.forName("oracle.jdbc.OracleDriver");
	  	//2.获取连接 (与数据库连接上)
		Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "SCOTT", "TIGER");
	  	//3.准备sql
		String sql = "select * from dept";
	  	//4.获取处理块(打包发送)
		Statement sta = conn.createStatement();
	  	//5.接收结果集
		ResultSet result = sta.executeQuery(sql);
	  	//6.处理结果数据
		while(result.next()){
			int deptno = result.getInt("deptno");
			String dname = result.getString("dname");
			String loc = result.getString("loc");
			System.out.println(deptno+"--->:"+dname+"--->"+loc);
		}
	  	//7.关闭资源
		result.close();
		sta.close();
		conn.close();
		
		
	}
}

注意:

  • 释放资源时,先打开的后关闭。

**优化:**可以将加载数据库驱动和获取数据库连接的操作放在静态代码块中,类只需要加载一次即可,不需要重复加载。

public class Demo02JDBC {
	// 声明连接数据库的对象
	public static Connection conn;
	static{
		// 加载数据库
		try {
			Class.forName("oracle.jdbc.OracleDriver");
			// 和数据库建立连接
			conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "SCOTT", "TIGER");
			// 准备sql语句
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void main(String[] args)throws Exception {
		// 准备sql语句
		String sql = "select * from dept where deptno=10";
		// 获取处理块
		Statement sta = conn.createStatement();
		// 执行sql语句
		ResultSet result = sta.executeQuery(sql);
		// 处理数据
		while(result.next()){
			int deptno = result.getInt(1);
			String dname = result.getString(2);
			String loc = result.getString(3);
			System.out.println(deptno+"--->"+dname+"--->"+loc);
		}
		//7.关闭资源
		result.close();
		sta.close();
		conn.close();
		
	}
}

3.2、预处理块

​ PreparedStatement 接口继承了 Statement,并与之在两方面有所不同:有人主张,在 JDBC 应用中,如果你已经是稍有水平开发者,你就应该始终以PreparedStatement 代替 Statement.也就是说,在任何时候都不要使用 Statement。

由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象。因此,多次执行的 SQL 语句经常创建为 PreparedStatement 对象,以提高效率。

特点:

  • 处理 不变的静态的 sql 语句 |可变的 sql 语句 带 ? 的 sql
  • 优点:性能高,方便编写sql 不存在sql注入 安全
  • 缺点:不能直接打印sql语句 不方便处理错误

例如要查询的sql语句为:select * from users where name=? and pwd=?,要查询的内容使用?做占位符。

使用的方法:

  • 设置值:为sql语句中的?设置值**setInt(字段名|字段的序号)/setString()/setBolean()等设置响应的值,也可以简单的使用setObject(字段名|字段的序号)**设置任意类型的值。
  • 获取值:从获取到的结果集中拿数据,使用函数getInt(字段名|字段的序号)/getSting()/getBoolean(),也可以简单的使用**getObject(字段名|字段的序号)**获取任意类型的值。
  • 序号是从1开始的。

代码:

/**
 * 使用预处理块查询数据库的数据
 *
 */
public class Demo05 {
	
	public static void main(String[] args) throws Exception{
		// 加载数据库驱动
		Class.forName("oracle.jdbc.OracleDriver");
		// 获取数据库的连接
		Connection conn =DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "SCOTT", "TIGER");
		// 准备sql语句(根据用户名和密码查询用户信息)
		String sql = "select * from users where name=? and pwd=?";
		// 获取预处理块,对查询数据的sql语句进行预编译
		PreparedStatement ps = conn.prepareStatement(sql);
		// 为sql语句设置值
		ps.setObject(1, "张万里");
		ps.setObject(2, "1314");
		// 执行sql语句
		ResultSet result = ps.executeQuery();
		// 处理获取到的数据
		while(result.next()){
			System.out.println("id"+"\tname"+"\tpwd"+"\tbirthday");
			System.out.println(result.getObject(1)+"\t"+result.getObject(2)+"\t"+result.getObject(3)+"\t"+result.getObject(4));
		}
		
	}

}

3.3、使用db.properties配置文件

db.properties的配置文件

driver=oracle.jdbc.OracleDriver
url=jdbc:oracle:thin:@localhost:1521:xe
uname=SCOTT
pwd=TIGER

使用配置文件获取数据库的连接:

/**
 * 数据库工具类,获取数据库的Connection连接对象
 */
public class DBUtil {
	
	// 获取资源配置文件对象
	private static Properties p = null;
	
	static{
		p = new Properties();
		try {
			// 获取配置文件
p.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
		} catch (IOException e) {
			System.out.println("加载配置文件失败");
			e.printStackTrace();
		}
		
		try {
			// 加载数据库
			Class.forName(p.getProperty("driver"));
		} catch (ClassNotFoundException e) {
			System.out.println("加载数据库失败");
			e.printStackTrace();
		}
	}
	
	/**
	 * 获取数据库的连接
	 */
	public static Connection getConnection() throws SQLException{
		Connection conn = null;
		conn = DriverManager.getConnection(p.getProperty("url"), p.getProperty("uname"), p.getProperty("pwd"));
		return conn;
	}

3.3.1、模拟注册账户

使用上述的工具类

/**
	 * 注册
	 */
	public static boolean login(){
		Scanner sc = new Scanner(System.in);
		System.out.print("用户名:");
		String name = sc.next();
		System.out.print("密码:");
		String pwd = sc.next();
		Connection conn = null;
		try {
			// 获取数据库的连接
			conn = DBUtil.getConnection();
		} catch (SQLException e) {
			System.out.println("连接数据库失败");
			e.printStackTrace();
		}
		
		boolean flag = true;
		// 循环检测要注册的账户是否存在
		while(flag){
			if(check(name, pwd,conn)){
				System.out.println("该用户已经存在,请重输入!");
				System.out.print("用户名:");
				name = sc.next();
				System.out.print("密码:");
				pwd = sc.next();
			}else{
				flag = false;
			}
		}
		
		// 准备sql语句
		String sql2 = "insert into users values(quecreate_users_id.nextval,?,?)";
		PreparedStatement ps = null;
		// 操作数据库影响的行数
		int rows = 0;
		try {
			ps = conn.prepareStatement(sql2);
			ps.setObject(1, name);
			ps.setObject(2, pwd);
			// 返回影响的行数
			rows = ps.executeUpdate();
		} catch (SQLException e) {
			System.out.println("向数据库插入数据异常");
			e.printStackTrace();
		}finally{
			// 关闭资源(自己封装的方法)
			DBUtil.close(ps, conn);
		}
		
		// 更改标志位
		if(rows>0){
			System.out.println("注册成功");
			return true;
		}else{
			System.out.println("注册失败");
			return false;
		}
	}

3.3.2、模拟登录账户

/**
	 * 登录
	 */
	public static void enter(){
		if(user!=null){
			System.out.println("不要重复登录!");
			start();
			return;
		}
		Scanner sc = new Scanner(System.in);
		System.out.print("用户名:");
		String name = sc.next();
		System.out.print("密码:");
		String pwd = sc.next();
		// 连接数据库
		Connection conn  = null;
		ResultSet result = null;
		PreparedStatement sta = null;
		try {
			conn = DBUtil.getConnection();
			
			boolean flag = true;
			while(flag){
				// 准备sql语句
				String sql = "select * from users where name=? and pwd=?";
				sta = conn.prepareStatement(sql);
				sta.setObject(1, name);
				sta.setObject(2, pwd);
				// 执行sql语句
				result = sta.executeQuery();
				if(result.next()){
					System.out.println("登录成功");
					flag = false;
				}else{
					System.out.println("用户名或密码错误,请重新输入完成登录");
					System.out.print("用户名:");
					name = sc.next();
					System.out.print("密码:");
					pwd = sc.next();
				}
			}
			
		} catch (SQLException e) {
			System.out.println("登录异常");
			e.printStackTrace();
		}finally {
			DBUtil.close(result, sta, conn);
		}
		user = new User(name,pwd);
		start();
	}

3.3.3、模拟修改密码

/**
	 * 修改密码
	 */
	public static void modify(){
		if(user == null){
			System.out.println("登录后才能修改数据");
			start();
			return;
		}
		Scanner sc = new Scanner(System.in);
		
		// 检测两次输入的密码
		boolean flag = true;
		String newpwd = null;
		while(flag){
			System.out.print("新密码:");
			newpwd = sc.next();
			System.out.println("请再次输入新密码:");
			String againPwd = sc.next();
			if(!newpwd.equals(againPwd)){
				System.out.println("两次密码不一致,请重新输入");
			}else{
				flag = false;
			}
		}
		
		Connection conn = null;
		PreparedStatement sta = null;
		// 执行sql影响的记录数
		int rows = 0;
		try {
			// 获取数据库的连接
			conn = DBUtil.getConnection();
			// 准备sql语句
			String sql = "update users set pwd=? where name=?";
			sta = conn.prepareStatement(sql);
			sta.setObject(1, newpwd);
			sta.setObject(2, user.getName());
			// 执行sql语句
			rows = sta.executeUpdate();
		} catch (SQLException e) {
			System.out.println("操作数据库失败");
			e.printStackTrace();
		}
		
		// 判断时是否修改成功
		if(rows > 0){
			System.out.println("修改密码成功!");
			user = null;
			start();
		}
	}

3.3.4、模拟注销用户

/**
	 * 注销用户
	 */
	public static void delete(){
		if(user == null){
			System.out.println("请先登录!");
			start();
		}
		Connection conn = null;
		PreparedStatement sta = null;
		// 数据库操作影响的行
		int rows =0;
		try {
			// 连接数据库
			conn = DBUtil.getConnection();
			// 准备sql语句
			String sql = "delete from users where name=? and pwd=?";
			sta = conn.prepareStatement(sql);
			// 设置参数
			sta.setObject(1, user.getName());
			sta.setObject(2, user.getPwd());
			// 执行删除操作
			rows = sta.executeUpdate();
			
		} catch (SQLException e) {
			System.out.println("注销用户异常");
			e.printStackTrace();
		}finally {
			DBUtil.close(sta, conn);
		}
		// 判断是否删除数据成功
		if(rows > 0){
			System.out.println("注销账户成功!");
			user = null;
			start();
			return;
		}
	}

4、事务问题

当涉及到事务问题时可以使用的方法有:

  • 使用**conn.setAutoCommit(false)**方法设置手动提交事务
  • 使用方法**conn.commit()**提交事务
  • 使用方法**conn.rollback()**回滚事务。

模拟转账:

/**
	 * 模拟转账
	 */
	public static void change(){
		Connection conn = null;
		PreparedStatement sta = null;
		try {
			// 获取数据库的连接
			conn = DBUtil.getConnection();
			// 设置手动提交
			conn.setAutoCommit(false);
			// 准备sql语句
			String sql1 = "update emp set sal = 2000 where empno = 7369";
			sta = conn.prepareStatement(sql1);
			int rows1 = sta.executeUpdate();
			
			// 准备sql语句
			String sql2 = "update emp set sal = 10000 where empno = 7839";
			sta = conn.prepareStatement(sql2);
			int rows2 = sta.executeUpdate();
			
			if(rows1 > 0 && rows2 > 0){
				// 提交事务
				conn.commit();
				System.out.println("修改工资成功");
			}else{
				// 事务回滚
				conn.rollback();
				System.out.println("修改工资失败");
			}
			
		} catch (SQLException e) {
			System.out.println("修改工资异常");
			e.printStackTrace();
		}finally{
			// 关闭资源
			DBUtil.close(sta, conn);
		}
	}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章