JavaWeb笔记007 jdbc基本使用以及事物基础知识

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lizhengwei1989/article/details/88412040

首先你要有一个Java项目,然后依赖了mysql驱动,过程略,这里介绍一下jdbc的基本使用,实际开发是用不到的,都是Spring结合Mybatis或者Hibernate。

基本使用

public void f2() throws Exception{
	//注册驱动
	//Class.forName("com.mysql.jdbc.Driver");  // 除了Driver是jdbc的类,其余都是Java的类
	DriverManager.registerDriver(new Driver());
	
	//获取连接 		ctrl+o 整理包
	Connection conn=DriverManager.getConnection("jdbc:mysql://localhost:3306/day07", "root", "1234"); // 高版本的有一个警告,用SSL:jdbc:mysql://localhost:3306/test?useSSL=true
	
	//编写sql
	String  sql="select * from category";
	
	//创建语句执行者
	PreparedStatement st=conn.prepareStatement(sql);
	
	//设置参数
	
	//执行sql
	ResultSet rs=st.executeQuery();
	
	//处理结果
	while(rs.next()){
		System.out.println(rs.getString("cid")+"::"+rs.getString("cname"));
	}
	
	//释放资源.
	rs.close();
	st.close();
	conn.close();
}
//插入一条数据  注:JdbcUtils是自己封装的类
public void f3(){
	Connection conn=null;
	ResultSet rs=null;
	PreparedStatement st=null;
	
	try {
		//获取连接
		conn=JdbcUtils.getConnection();
		
		//编写sql
		String sql="insert into  category values(?,?)";
		
		//获取语句执行者
		st=conn.prepareStatement(sql);
		
		//设置参数
		st.setString(1, "c006");
		st.setString(2, "户外");
		
		//执行sql 
		int i=st.executeUpdate();
		
		//处理结果
		if(i==1){
			System.out.println("success");
		}else{
			System.out.println("fail");
		}
		
	} catch (Exception e) {
		e.printStackTrace();
	} finally {
		//释放资源
		JdbcUtils.closeResource(conn, st, rs);
	}
	
}


public class JdbcUtils {
	// 获取连接
	public static Connection getConnection() throws ClassNotFoundException, SQLException {
		// 注册驱动   ctrl+shift+f格式化代码
		Class.forName("com.mysql.jdbc.Driver");

		// 获取连接 ctrl+o 整理包
		Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/day07", "root", "1234");
		return conn;
	}

	/**
	 * 释放资源
	 * @param conn 连接
	 * @param st 语句执行者
	 * @param rs 结果集
	 */
	public static void closeResource(Connection conn, Statement st, ResultSet rs) {
		closeResultSet(rs);
		closeStatement(st);
		closeConn(conn);
	}
	
	/**
	 * 释放连接
	 * @param conn 连接
	 */
	public static void closeConn(Connection conn){
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			conn=null;
		}
		
	}
	
	/**
	 * 释放语句执行者
	 * @param st 语句执行者
	 */
	public static void closeStatement(Statement st){
		if(st!=null){
			try {
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			st=null;
		}
		
	}
	
	/**
	 * 释放结果集
	 * @param rs 结果集
	 */
	public static void closeResultSet(ResultSet rs){
		if(rs!=null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			rs=null;
		}
		
	}
}

jdbc-api详解

所有的包 都是 java.sql 或者 javax.sql

DriverManager:管理了一组jdbc的操作 类
	常用方法:
		了解:注册驱动	
			static void registerDriver(Driver driver) :
				通过查看 com.mysql.jdbc.Driver的源码 有如下代码
					 static {
						try {
							java.sql.DriverManager.registerDriver(new Driver());//这段代码我们已经写过
						} catch (SQLException E) {
							throw new RuntimeException("Can't register driver!");
						}
					}
				驱动注册了两次.我们只需要将静态代码块执行一次,类被加载到内存中会执行静态代码块,并且只执行一次.
				现在只需要将类加载到内存中即可:
					方式1:
						★Class.forName("全限定名");//包名+类名   com.mysql.jdbc.Driver
					方式2:
						类名.class;
					方式3:
						对象.getClass();

		掌握:获取连接
			static Connection getConnection(String url, String user, String password) 
				参数1:告诉我们连接什么类型的数据库及连接那个数据库
							协议:数据库类型:子协议 参数
					mysql:	jdbc:mysql://localhost:3306/数据库名称
					oracle:	jdbc:oracle:thin@localhost:1521@实例
					
				参数2:账户名 root
				参数3:密码
				
				
Connection:连接 接口
	常用方法:
		获取语句执行者:
			(了解)Statement createStatement() :获取普通的语句执行者  会出现sql注入问题
			★PreparedStatement prepareStatement(String sql) :获取预编译语句执行者
			(了解)CallableStatement prepareCall(String sql):获取调用存储过程的语句执行者

		了解:
			setAutoCommit(false) :手动开启事务
			commit():提交事务
			rollback():事务回滚

Statement:语句执行者 接口
PreparedStatement:预编译语句执行者 接口
	常用方法:
		设置参数:
			setXxx(int 第几个问号,Object 实际参数);
				常见的方法:
					 setInt
					 setString
					 setObject
		
		执行sql:
			 ResultSet executeQuery() :执行 r 语句 返回值:结果集
			 int executeUpdate() :执行cud 语句 返回值:影响的行数


ResultSet:结果集 接口
	执行查询语句之后返回的结果
		常用方法:
			boolean next():判断是否有下一条记录,若有返回true且将光标移到下一行,若没有呢则返回false
				光标一开始处于第一条记录的上面
			
			获取具体内容
				getXxx(int|string)
					若参数为int :第几列
					若参数为string:列名(字段名)
				例如:
					获取cname的内容可以通过
						getString(2)
						getString("cname")
				常用方法:
					getInt
					getString 也可以获取int值
					getObject 可以获取任意

事务

事务总结:
	事务的特性:★★★
		ACID
		原子性:事务里面的操作单元不可切割,要么全部成功,要么全部失败
		一致性:事务执行前后,业务状态和其他业务状态保持一致.
		隔离性:一个事务执行的时候最好不要受到其他事务的影响
		持久性:一旦事务提交或者回滚.这个状态都要持久化到数据库中
	不考虑隔离性会出现的读问题(都是对于两个事务来说的)★★
		脏读:在一个事务中读取到另一个事务没有提交的数据
		不可重复读:在一个事务中,两次查询的结果不一致(针对的update操作)
		虚读(幻读):在一个事务中,两次查询的结果不一致(针对的insert操作)
	通过设置数据库的隔离级别来避免上面的问题(理解)
		read uncommitted  	读未提交	上面的三个问题都会出现
		read committed  	读已提交	可以避免脏读的发生
		repeatable read		可重复读	可以避免脏读和不可重复读的发生
		serializable		串行化		可以避免所有的问题
	
	
	了解
		演示脏读的发生:
			将数据库的隔离级别设置成 读未提交
				set session transaction isolation level read uncommitted;
			查看数据库的隔离级别
				select @@tx_isolation;
		避免脏读的发生,将隔离级别设置成  读已提交
			set session transaction isolation level read committed;
			不可避免不可重复读的发生.
		
		避免不可重复读的发生 经隔离级别设置成 可重复读
			set session transaction isolation level  repeatable read;
			
		演示串行化 可以避免所有的问题
			set session transaction isolation level  serializable;
			锁表的操作.
		
	四种隔离级别的效率
		read uncommitted>read committed>repeatable read>serializable
	四种隔离级别的安全性
		read uncommitted<read committed<repeatable read<serializable
		
	开发中绝对不允许脏读发生.
		mysql中默认级别:repeatable read
		oracle中默认级别:read committed

	java中控制隔离级别:(了解)
		Connection的api
			void setTransactionIsolation(int level) 
				level是常量
package com.itheima.utils;

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

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

// 数据库工具另一种封装,使用了第三方连接池
public class DataSourceUtils {
	private static ComboPooledDataSource ds=new ComboPooledDataSource();
	private static ThreadLocal<Connection> tl=new ThreadLocal<>();
	
	/**
	 * 获取数据源
	 * @return 连接池
	 */
	public static DataSource getDataSource(){
		return ds;
	}
	
	/**
	 * 从当前线程上获取连接
	 * @return 连接
	 * @throws SQLException
	 */
	public static Connection getConnection() throws SQLException{
		Connection conn = tl.get();
		if(conn==null){
			//第一次获取 创建一个连接 和当前的线程绑定
			 conn=ds.getConnection();
			 
			 //绑定
			 tl.set(conn);
		}
		return conn;
	}
	
	
	
	/**
	 * 释放资源
	 * 
	 * @param conn
	 *            连接
	 * @param st
	 *            语句执行者
	 * @param rs
	 *            结果集
	 */
	public static void closeResource(Connection conn, Statement st, ResultSet rs) {
		closeResource(st, rs);
		closeConn(conn);
	}
	
	 
	public static void closeResource(Statement st, ResultSet rs) {
			closeResultSet(rs);
			closeStatement(st);
	}

	/**
	 * 释放连接
	 * 
	 * @param conn
	 *            连接
	 */
	public static void closeConn(Connection conn) {
		if (conn != null) {
			try {
				conn.close();
				//和当前的线程解绑
				tl.remove();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			conn = null;
		}

	}

	/**
	 * 释放语句执行者
	 * 
	 * @param st
	 *            语句执行者
	 */
	public static void closeStatement(Statement st) {
		if (st != null) {
			try {
				st.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			st = null;
		}

	}

	/**
	 * 释放结果集
	 * 
	 * @param rs
	 *            结果集
	 */
	public static void closeResultSet(ResultSet rs) {
		if (rs != null) {
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
			rs = null;
		}

	}
	
	/**
	 * 开启事务
	 * @throws SQLException
	 */
	public static void startTransaction() throws SQLException{
		//获取连接//开启事务
		getConnection().setAutoCommit(false);;
	}
	
	/**
	 * 事务提交
	 */
	public static void commitAndClose(){
		try {
			//获取连接
			Connection conn = getConnection();
			//提交事务
			conn.commit();
			//释放资源
			conn.close();
			//解除绑定
			tl.remove();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 事务回滚
	 */
	public static void rollbackAndClose(){
		try {
			//获取连接
			Connection conn = getConnection();
			//事务回滚
			conn.rollback();
			//释放资源
			conn.close();
			//解除绑定
			tl.remove();
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}

public class AccountDao4DB {

	public void accountOut(String fromUser, String money) throws SQLException {
		//创建queryrunner
		QueryRunner qr = new QueryRunner();
		
		//编写sql
		String sql="update account set money =money - ? where name =?";
		
		//执行sql
		qr.update(DataSourceUtils.getConnection(), sql, money,fromUser);
	}

	public void accountIn(String toUser, String money) throws SQLException {
		// TODO Auto-generated method stub
		QueryRunner qr=new QueryRunner();
		String sql="update account set money =money + ? where name =?";
		qr.update(DataSourceUtils.getConnection(), sql, money,toUser);
	}

}


public class AccountService4DB {

	/**
	 * 转账
	 * @param fromUser 转出方
	 * @param toUser 转入方
	 * @param money 金额
	 * @throws Exception 
	 */
	public void account(String fromUser, String toUser, String money) throws Exception {
		AccountDao4DB dao = new AccountDao4DB();
		
		try {
			//0.开启事务
			DataSourceUtils.startTransaction();
			
			//1.转出
			dao.accountOut(fromUser,money);
			
			int i=1/0;
			
			//2.转入
			dao.accountIn(toUser,money);
			
			//3.事务提交
			DataSourceUtils.commitAndClose();
		} catch (Exception e) {
			e.printStackTrace();
			DataSourceUtils.rollbackAndClose();
			throw e;
		}
		
	}

}

猜你喜欢

转载自blog.csdn.net/lizhengwei1989/article/details/88412040
今日推荐