javaweb学习笔记(十五):JDBC(1)

版权声明:转载请注明出处: https://blog.csdn.net/qq_34774655/article/details/83746469

目录

1.概念

2 JDBC接口的核心API

例1:jdbc连接数据库

 例2:Statement对象演示

例3:PreparedStatement对象演示

例4:CallableStatement对象演示


1.概念

SUN公司为了简化、统一对数据库的操作,定义了一套Java操作数据库的规范,称之为JDBC。

JDBC全称为:Java Data Base Connectivity(java数据库连接),它主要由接口组成。组成JDBC的2个包:java.sql、javax.sql。开发JDBC应用需要以上2个包的支持外,还需要导入相应JDBC的实现类,即数据库驱动。

Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet, Statement和Connection对象。特别是Connection对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。

为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。

2 JDBC接口的核心API

Driver接口: 表示java驱动程序接口。所有的具体的数据库厂商来实现此接口。

connect(url, properties):  连接数据库的方法。

其中参数url: jdbc协议:数据库子协议://主机:端口/数据库

常用数据库URL地址的写法:

Oracle写法: jdbc:oracle:thin:@localhost:1521:sid

SqlServer写法jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sid

MySql写法: jdbc:mysql://localhost:3306/sid

properties一般至少包括:

user: 数据库的用户名

password: 数据库用户密码

DriverManager类: 驱动管理器类,用于加载驱动,并创建与数据库的链接DriverManager.registerDriver(driver): 注册驱动类对象

Connection DriverManager.getConnection(url, user, password);  获取连接对象

注:在实际开发中并不推荐采用registerDriver方法注册驱动。原因有二:

一、查看Driver的源代码可以看到,如果采用此种方式,会导致驱动程序注册两次,也就是在内存中会有两个Driver对象。二、程序依赖mysql的api,脱离mysql的jar包,程序将无法编译,将来程序切换底层数据库将会非常麻烦。

推荐方式:Class.forName(“com.mysql.jdbc.Driver”);

采用此种方式不会导致驱动对象在内存中重复出现,并且采用此种方式,程序仅仅只需要一个字符串,不需要依赖具体的驱动,使程序的灵活性更高。

Connection接口: 表示java程序和数据库的连接对象。客户端与数据库所有交互都是通过connection对象完成的

Statement createStatement() : 创建Statement对象

PreparedStatement prepareStatement(String sql) 创建PreparedStatement对象

CallableStatement prepareCall(String sql) 创建CallableStatement对象

 

Statement接口: 用于执行静态的sql语句

int executeUpdate(String sql)  : 执行静态的更新sql语句(DDL,DML)

ResultSet executeQuery(String sql)  :执行的静态的查询sql语句(DQL)

PreparedStatement接口:Statement的子接口用于执行预编译sql语句

int executeUpdate() : 执行预编译的更新sql语句(DDL,DML)

ResultSet executeQuery()  : 执行预编译的查询sql语句(DQL)

 

Statement VS PreparedStatement:

1.PreperedStatement可以避免SQL注入的问题。

2.Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement 可对SQL进行预编译,从而提高数据库的执行效率。oracle、SQL Server支持数据库缓冲区,MySQL并不支持数据库缓冲区

3.PreperedStatement对于sql中的参数,允许使用占位符的形式进行替换,简化sql语句的编写。

CallableStatement接口:PreparedStatement的子接口。用于执行存储过程的sql语句(call xxx)

ResultSet executeQuery()  : 调用存储过程的方法

ResultSet接口:用于封装查询出来的数据

Jdbc程序中的ResultSet用于代表SQL语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式。ResultSet 对象维护了一个指向表格数据行的游标,初始的时候,游标在第一行之前,调用ResultSet.next() 方法,可以使游标指向具体的数据行,进行调用方法获取该行的数据。

ResultSet提供的都是用于获取数据的get方法,可以使用列的索引编号(从1开始)或列的名称(不区分大小写)获取值:

例: getString(int index)

getString(String columnName)

常用的数据类型转换表:

1jdbc连接数据库

package day1105;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.util.Properties;
import org.junit.Test;
public class Connect {
	private String url="jdbc:mysql://localhost:3306/xiaohua";
	private String user="root";
	private String password="root";
	@Test
	//第一种方法
	public void test1() throws Exception{
		// 1.创建驱动程序类对象
		Driver driver=new com.mysql.jdbc.Driver();
		
		Properties props=new Properties();
		props.setProperty("user", user);
		props.setProperty("password", password);
		//2.连接数据库,返回连接对象
		Connection conn=driver.connect(url, props);
		System.out.println(conn);
	}
	@Test
	//第二种方法,使用驱动管理器类(注册了两次,没必要)
	public void test2() throws Exception{
		Driver driver=new com.mysql.jdbc.Driver();
		//注册驱动程序(可注册多个)
		DriverManager.registerDriver(driver);
		//连接具体的数据库
		Connection conn=DriverManager.getConnection(url, user,password);
		System.out.println(conn);
	}
	@Test
	//第二种的改进,使用驱动管理器类(推荐)
	public void test3() throws Exception{
		//通过得到字节码对象的方式加载静态代码块,从而注册驱动程序
		Class.forName("com.mysql.jdbc.Driver");
		Connection conn=DriverManager.getConnection(url, user,password);
		System.out.println(conn);
		
	}	
}

其中:properties:

url=jdbc:mysql//localhost:3306/xiaohua
user=root
password=root
driverClass=com.mysql.jdbc.Driver

 例2:Statement对象演示

jdbcUtil.java文件:

package util;

import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
 * jdbc工具类
 * */
public class jdbcUtil {
	private static String url=null;
	private static String user=null;
	private static String password=null;
	private static String driverClass=null;
	
	//静态代码块,只加载一次
	static {
		try {
			//读取properties文件
			Properties props=new Properties();
			/**
			 *  . 代表java命令运行的目录
			 *  在java项目下,. java命令的运行目录从项目的根目录开始
			 *  在web项目下,  . java命令的而运行目录从tomcat/bin目录开始
			 *  所以不能使用点.
			 */
			//FileInputStream in = new FileInputStream("./src/db.properties");
			/**
			 * 使用类路径的读取方式
			 *  / : 斜杠表示classpath的根目录
			 *     在java项目下,classpath的根目录从bin目录开始
			 *     在web项目下,classpath的根目录从WEB-INF/classes目录开始
			 */
			InputStream in=jdbcUtil.class.getResourceAsStream("/db.properties");
			
			props.load(in);//加载文件
			//读取信息
			url=props.getProperty("url");
			user=props.getProperty("user");
			password=props.getProperty("password");
			driverClass=props.getProperty("driverClass");
			//注册驱动程序
			Class.forName(driverClass);
		}catch(Exception e) {
			e.printStackTrace();
			System.out.println("驱动程序注册出错");
		}
		
	}
	//获取连接对象的方法
	public static Connection getConnection() {
		try {
			Connection conn=DriverManager.getConnection(url,user,password);
			return conn;
		}catch(SQLException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	//释放资源的方法
	public static void close(Connection conn,Statement stmt) {
		if(stmt!=null) {
			try {
				stmt.close();
			}catch(SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
		if(conn!=null) {
			try {conn.close();
			}catch(SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
	//释放资源的方法
	public static void close(Connection conn,Statement stmt,ResultSet rs){
		if(rs!=null) {
			try {
				rs.close();
			} catch (SQLException e1) {
				e1.printStackTrace();
				throw new RuntimeException(e1);
			}
		}
		if(stmt!=null){
			try {
				stmt.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
		if(conn!=null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}
		}
	}
	

	
}

statement对象操作DDL、DML、DQL语句:


import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import org.junit.Test;
import util.jdbcUtil;
public class StatementDemo {
	@Test
	public void test1() {
		Connection conn=null;
		Statement stmt=null;
		try {
			//1.获取连接对象
			conn=jdbcUtil.getConnection();
			//2.创建statement对象
			stmt=conn.createStatement();
			//3.静态SQL语句
			//DDL语句
			//String sql = "CREATE TABLE student(id INT PRIMARY KEY AUTO_INCREMENT,NAME VARCHAR(20),gender VARCHAR(2))";
			//DML语句
			String sql = "INSERT INTO student(NAME,gender) VALUES('小华','男')";
			//4.发送SQL语句,执行
			int count=stmt.executeUpdate(sql);
			System.out.println("影响了"+count+"行");
			
		}catch(Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}finally {
			//5.关闭连接(先开后关)
			jdbcUtil.close(conn, stmt);
		}
		
	}
	@Test
	public void test2() {
		Connection conn=null;
		Statement stmt=null;
		try {
			//1.获取连接对象
			conn=jdbcUtil.getConnection();
			//2.创建statement对象
			stmt=conn.createStatement();
			//3.静态SQL语句
			//DQL语句
			String sql="SELECT * FROM student";
			//4.发送SQL语句,执行
			ResultSet rs=stmt.executeQuery(sql);
			//遍历取值
			while(rs.next()) {
				int id=rs.getInt("id");
				String name=rs.getString("name");
				String gender=rs.getString("gender");
				System.out.println(id+","+name+","+gender);
			}
		}catch(Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}finally {
			//5.关闭连接(先开后关)
			jdbcUtil.close(conn, stmt);
		}
		
	}
}

 DDL的结果:

 

DML的结果:

DQL的结果:

 

例3:PreparedStatement对象演示

package day1105;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import org.junit.Test;

import util.jdbcUtil;

public class PreparedStatementDemo {
	@Test
	public void test1() {
		Connection conn=null;
		PreparedStatement stmt=null;
		try {
			//1.获取连接
			conn=jdbcUtil.getConnection();
			//2.准备预编译的SQL语句
			String sql = "INSERT INTO student (NAME,gender) VALUES(?,?)"; //?表示一个参数的占位符
			//3.创建PreparedStatement对象,执行预编译语句
			stmt=conn.prepareStatement(sql);
			//4.设置参数,参数位置从1开始。
			stmt.setString(1,"小娜");
			stmt.setString(2, "女");
			//5.发送参数,执行SQL。
			int count=stmt.executeUpdate();
			System.out.println("影响了"+count+"行");
		}catch(Exception e){
			e.printStackTrace();
			throw new RuntimeException(e);
		}finally {
			jdbcUtil.close(conn, stmt);
		}	
	}
	@Test
	public void test2() {
		Connection conn=null;
		PreparedStatement stmt=null;
		ResultSet rs=null;
		try {
			//1.获取连接
			conn=jdbcUtil.getConnection();
			//2.准备预编译的SQL语句
			String sql = "SELECT * FROM student"; 
			//3.创建PreparedStatement对象,执行预编译语句
			stmt=conn.prepareStatement(sql);
			//4.发送参数,执行SQL。
			rs=stmt.executeQuery();
			while(rs.next()) {
				int id=rs.getInt("id");
				String name=rs.getString("name");
				String gender=rs.getString("gender");
				System.out.println(id+","+name+","+gender);
			}
		}catch(Exception e){
			e.printStackTrace();
			throw new RuntimeException(e);
		}finally {
			jdbcUtil.close(conn, stmt,rs);
		}	
	}
}

DML的结果:

 DQL的结果:

 

例4:CallableStatement对象演示

package day1105;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.ResultSet;
import org.junit.Test;
import util.jdbcUtil;
public class CablleStatementDemo {
	@Test
	//调用带有输入参数的存储过程
	public void test1() {
		Connection conn=null;
		CallableStatement stmt=null;
		ResultSet rs=null;
		try {
			//获取连接
			conn=jdbcUtil.getConnection();
			//准备sql
			String sql="CALL pro_findById(?)";
			//创建CallableStatement对象,并预编译
			stmt=conn.prepareCall(sql);
			//设置输入参数值
			stmt.setInt(1, 1);
			//发送参数
			rs=stmt.executeQuery();
			//遍历结果
			while(rs.next()) {
				int id=rs.getInt("id");
				String name=rs.getString("name");
				String gender=rs.getString("gender");
				System.out.println(id+","+name+","+gender);
			}
			
		}catch(Exception e) {
			e.printStackTrace();
			throw new RuntimeException();
		}finally {
			jdbcUtil.close(conn,stmt,rs);
		}		
	}
	@Test
	//调用带有输入、输出参数的存储过程
	public void test2() {
		Connection conn=null;
		CallableStatement stmt=null;
		ResultSet rs=null;
		try {
			//获取连接
			conn=jdbcUtil.getConnection();
			//准备sql
			//第一个参数是输入参数,第二个参数是输出参数
			String sql="CALL pro_findById2(?,?)";
			//创建CallableStatement对象,并预编译
			stmt=conn.prepareCall(sql);
			//设置输入参数值
			stmt.setInt(1, 1);
			//设置输出参数
			stmt.registerOutParameter(2, java.sql.Types.VARCHAR);
			//发送参数
			stmt.executeQuery();//结果不是返回到结果集ResultSet中,而是输出参数中。
			//得到输出参数的值
			//索引值:预编译SQL中的输出参数的位置
			String result=stmt.getString(2);
			System.out.println(result);	
		}catch(Exception e) {
			e.printStackTrace();
			throw new RuntimeException();
		}finally {
			jdbcUtil.close(conn,stmt,rs);
		}		
	}
}

其中,存储过程函数为:

DELIMITER $
CREATE PROCEDURE  pro_findById(IN eid INT)
BEGIN
	SELECT * FROM student WHERE id=eid;
END $



DELIMITER $
CREATE PROCEDURE  pro_findById2(IN eid INT,OUT vname VARCHAR(20))
BEGIN
	SELECT NAME INTO vname FROM student WHERE id=eid;
END $




CALL pro_findById(1);

CALL pro_findById2(1,@NAME);

SELECT @NAME

 执行结果:

猜你喜欢

转载自blog.csdn.net/qq_34774655/article/details/83746469