JDBC的自我学习(自用,自我回顾知识时观看)

JDBC

1.概述

JDBC(Java DataBase Connectivity)Java数据库连接(技术),也就是能够通过java代码连接到数据库,并可以使用SQL语句,对数据库进行各种操作

最早连接数据库的标准还有 ODBC(Open Database Connectivity),开放式数据库连接。使用C语言实现。

它提供了一套连接并操作数据库的API接口,使得程序员可以使用同一套标准的代码,去访问不同数据库,而不需要改变代码。

在这里插入图片描述

1.1程序连接数据库的关键:


也就是说,如果我们想连接xxx数据库,就把xxx数据库驱动注册到驱动管理器中即可,驱动管理器通过注册进来的驱动获取到数据库的连接,然后就可以正常使用SQL语句对数据库进行操作了。


jdbc 不过是 odbc 的java实现版本
JDBC就相当于Java版本的ODBC
在这里插入图片描述

2.连接

在使用JDBC连接数据库之前,需要先获取到数据库的连接对象,而获取连接对象之前,需要先注册驱动到驱动管理器中,而注册驱动之前,需要先加载驱动到内存中。

  1. 加载驱动类
  2. 将驱动类注册到驱动管理器中(可以自动完成)
  3. 通过驱动管理器获取数据库连接对象

2.1加载驱动

java.sql.Driver是JDBC中提供的驱动接口,每一种数据库的驱动类都要实现这个接口。

ava.sql.DriverManager是JDBC中提供的驱动管理器(类),注册驱动后,可通过它获取到数据库连接对象。

在这里插入图片描述

可以看出,驱动管理器可以从注册的驱动中依次尝试,是否可以通过该驱动获得数据库连接对象,如果可以则返回,如果不可则尝试一下个驱动。

2.2加载驱动类的三种方式

常用的三种方式有:

	@Test
	public void testGetConnection() throws Exception {
		// forName方式加载驱动类
		Class.forName("oracle.jdbc.OracleDriver");
	}
	@Test
	public void testRegistryDriver() throws Exception {
		//创建出驱动对象
		OracleDriver driver = 
				new OracleDriver();
		// OracleDriver()  是在oracle.jdbc.driver包底下
		//或者 oracle.jdbc 包底下
	}
	@Test
	public void testRegistryDriver4() throws Exception{
		//设置环境变量
		//jdbc.drivers=oracle.jdbc.driver.OracleDriver
		//驱动管理器会自动加载该驱动类
		System.setProperty("jdbc.drivers", "oracle.jdbc.OracleDriver");
	}

注意,驱动类使用oracle.jdbc.driver.OracleDriver或者oracle.jdbc.OracleDriver都是可以的

2.3获得连接

驱动类已经加载,那么接下来就可以使用驱动管理器获取数据库连接对象了

把驱动类注册到驱动管理器中,可以手动完成,也可以自动完成oracle.jdbc.driver.OracleDriver驱动类,被加载之后,会自动注册到驱动管理器中。

DriverManager中会通过各种方式,加载并初始化驱动类,同时提供了getConnection方法,可以给我们返回数据库连接对象。

我们通过 DriverManger.getConnection 获得连接 。
但是获取数据库连接对象,需要三个参数:

  • url,需要连接数据库的地址
  • user,登录数据库的用户名
  • password, 登录数据库的密码

连接不同数据库的时候,url地址是不用的,如果是oracle数据库,则url地址如下:

String url = "jdbc:oracle:thin:@127.0.0.1:1521:XE";

其中:

  • thin是oracle的一种连接方式
  • 后边必须有数据库所在的主机的ip和端口号
  • XE表示连接的数据库的名字
@Test
	public void testGetConnection() throws Exception {
		//1.注册驱动
		Class.forName("oracle.jdbc.OracleDriver");
		//2.通过驱动管理器获取与数据库的连接
		// url  jdbc: 数据库厂商的名字 连接方式:@ip地址 :数据库占用端口  : 数据库的名字 ;
		String url ="jdbc:oracle:thin:@127.0.0.1:1521:XE";
		String user="wpj";
		String password ="wpj";
		//获取连接
		Connection connection = DriverManager.getConnection(url, user, password);
	}

在获取到数据库连接对象之后,就可以对数据库进行各种操作了

2.4通过封装获取连接数据库的信息

通过Properties(); 对象可以完成对 Properties格式的文件 进行解析。 Properties 本身继承了 hashtable,所以拥有哈希表的特性, 用k与v存储数据。 用于分割的符号多种多样。个人推荐使用 等号 “=” 更方便于k值与v值的分割

jdbc.driver=oracle.jdbc.OracleDriver
jdbc.url=jdbc:oracle:thin:@localhost:1521:xe
jdbc.user:user
jdbc.password:password

可以使用 Properties的load方法 将文件传入。load方法传入的是一个输入字节流。 load调用了load0方法 load0 具体实现了k值v值的分割与存储。

我们一般 是这样在传入

	Properties properties = new Properties();
	properties.load(new FileInputStream("src/datasource.properties"));

这是代表 datasource.properties文件在项目的src包底下。
但是这有一个问题
当我们把项目打包之后,jar包中将不存在src目录,那文件又将何处去寻找呢?

当项目打包之后 该文件将与项目底下的第一个包同级。
一个类的加载的时候,从第一个包开始加载,说明 该文件与加载路径同级。
类名.getClass()得到Class类型对象
类名.getClass().getClassLoder(); 得到Class类型 类加载器
类名.getClass().getClassLoder().getResoure(“文件名”);得到文件路径
类名.getClass().getClassLoder().getResoureAsStream(“文件名”);这个是在src底下的文件,省去src不写 然后可以得到这个文件的流 。

    Properties properties = new Properties();
	properties.load(类名.getClass.getClassLoder().getResourceAsStream("datasource.properties"));

此时properties对象里面已经存储着 datasource文件的信息
通过properties.getProperty()方法传k获取value
driverClassName= properties.getProperty(“jdbc.driver”);

driverClassName 存储着 驱动类的名字 用于后面注册驱动。

url=properties.getProperty(“url”);

3.通用步骤

使用JDBC 对数据库进行操作的通用步骤,应该包括以下几个步骤:

  1. 注册驱动
  2. 获取连接
  3. 创建数据库连接对象(statement对象或其子类对象)
  4. 执行SQL语句
  5. 处理结果集(一般是查询语句才需要处理)
  6. 资源关闭

其中,java.sql.Statement接口或者子类型接口,可以用来执行sql语句,常用的方法有:

  • boolean execute(String sql) throws SQLException;
    执行sql,返回 Boolean类型数据
    true表示返回的结果是一个ResultSet
    flase 表示返回结果是一个数据更新的条数或者没有返回结果
  • int executeUpdate(String sql ) throws SQLException;

执行sql,返回int类型数据
返回0 ,则表示没有结果返回
返回其他数字,则返回操作了几条数据。

  • ResultSet executeQuery(String sql ) throws SQLException;
    执行sql,返回ResultSet类型结果
    一般查询语句使用该方法,可以返回结果集ResultSet,然后再遍历结果集,拿到每条数据
  • int executeBatch ) throws Exception;
    执行批处理操作,返回每条sql命令的执行结果,放到int数字中。

其中,java.sql.ResultSet接口,专门用来表示select查询语句返回的结果集,表示当前sql的查询结果。

3.1 DDL与DML

实现:

@Test
	public void createTableTest() throws Exception {

		// 1.注册驱动
		Class.forName(driverClassName);
		// 2.获取连接
		Connection connection = DriverManager.getConnection(url, user, password);
		// 3.创建Statement
		Statement st = connection.createStatement();
		// 4.执行sql
		String sql = "create table kk(" + 
		"id number primary key," + 
				"name varchar2(25) constraint kk_name_nn not null"+
		")";
		/*
		 *  exctue(sql) boolean 代表执行这条sql有没有结果集
		 *  executeUpdate(sql)
		 *  	int 代表影响表的记录数
		 *  executeQuery(sql)
		 *  	Resultset 返回查询的结果集
		 *   
		 * */
			st.execute(sql);
		// 5.关闭资源
			st.close();
			connection.close();
			System.out.println("执行成功");
	}

创建,修改以上大同小异,只需要修改sql语句和statement对象的方法就行。结果没什么区别。修改使用的是
statement.executeUpdate 多一个int返回结果。可以利用,也可以不利用。

3.2 DQL

而查询就较为复杂些,需要处理结果集:

@Test
	public void selectTest() {
		//1.注册驱动
		System.setProperty("jdbc.drivers",driverClassName);
		//2.获取连接
		try {
			Connection connection = DriverManager.getConnection(url,user,password);
		//3.创建搬运工
			Statement ste =connection.createStatement();
		//4.执行sql语句
			String sql= "select * from kk";
		//查询的所有的结果都在这里面
			ResultSet resultSet = ste.executeQuery(sql);
			
		//5.处理结果集
			// 如果有下一个结果  指针就往下走
			// 如果有下一行数据返回true  否则返回false
			while(resultSet.next()) {
				//获取第几列的数据  从1开始
				long id = resultSet.getLong(1);
				String name = resultSet.getString(2);
				System.out.println(id+":"+name);
				//获取指定(列名是查询出来数据的列名)列名的数据 如果没有这个名字就会报列名无效
				long id = resultSet.getLong("id");
				String name = resultSet.getString("name");
				System.out.println(id+":"+name);
			}
			//6.关闭资源
			resultSet.close();
			ste.close();
			connection.close();		
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

ResultSet对象提供了 get+数据类型(); 的方法 可以传入列的序号,来表示获取第几列的数据,注意,从1开始。也根据可以查询结果中的字段名来查询,例如查询结果中有一列为 IDS , 那我们则可以get+数据类型("IDS");去获取数据。假设IDS 为int类型 则完整语句为:

	int  ids = resultSet.getInt("IDS");

由此获得IDS字段的值。

3.2 Batch

获取到数据库对象之后,可以进行批处理

@Test
	public void testBatch() throws Exception {
		Class.forName(driverClassName);
		Connection connection = DriverManager.getConnection(url, user, password);
		Statement statement = connection.createStatement();
		String sql ="insert into kk values(kk_seq.nextval,'花好')";
		String sql1 = "delete from kk where id >2";
		String sql2 ="update kk set name ='liuNeng' where id =1";
		statement.addBatch(sql);
		statement.addBatch(sql2);
		statement.addBatch(sql1);
		int[] is = statement.executeBatch();
		for (int i : is) {
			System.out.println(i);
		}
		statement.close();
		connection.close();
	}

4.statement

java.sql.statement 接口,是专门用来 执行SQL语句的,该接口还有俩个子接口:

  • java.sql.PreparedStatement
  • java.sql.CallableStatement
  • CallableStatement接口继承了PreparedStatement接口
  • PreparedStatement接口又继承了Statement接口

4.1 PrepareStatement

PrepareStatement 接口,简称ps,它除了拥有Statement的功能特点之外,它还有有着自己的特点:可以对sql语句进行预处理。
Statement,是每次执行一个sql语句,就要把一个完成的sql语句发送给数据库进行执行,然后取回返回的结果。

PrepareStatement,可以把一个sql语句的结构,提前发送给数据库进行预处理,然后在专门给发送要操作的具体的值,在数据量大的时候,这种方式会大大提高执行效率。

4.1.1 使用

@Test
	public void testPS() throws Exception {
	// 注册驱动
		Class.forName(driverClassName);
	// 获取连接,这里我提前设置好了静态变量url,user,password ,并未他们附过值。
	// getConnection方法需要一些连接数据库的数据
	// url=jdbc:oracle:@localhost:1521:xe;
	// user与password 就是数据库的用户名和密码
		Connection connection = DriverManager.getConnection(url, user, password);
	// 在PreparedStatement 中 该Statement子类对象 是先将sql语句传入数据库中进行校验,校验无误之后再传变量具体的值
	// 所以sql语句中的变量值可以用占位符来先进行代替,暂时不写具体的内容是什么。
	// 如下
		String sql ="insert into kk values(kk_seq.nextval,?)";// 该插入语句values中的第二列数据暂时不写,用一个问号作为占位符表示之后再写。
		// 只要成功创建ps,ps对象就会把sql语句发送数据库进行预处理
		PreparedStatement ps = connection.prepareStatement(sql);
			long start = System.currentTimeMillis();
		for (int i = 1000; i < 2000; i++) {
			//给sql语句替换占位符  
			// 添加String类型的数据 setString
			// 第一个问号,具体是“陈卓璇”拼接i
			ps.setString(1, "陈卓璇"+i);
			// 执行
			ps.execute();
		}
			long end = System.currentTimeMillis();
		System.out.println(end - start);
		ps.close();
		connection.close();
	}

4.1.2 批处理

同样的PrepareStatement 也有批处理的方法:

public void testPsBatch() throws Exception {
		Class.forName(driverClassName);
		Connection connection = DriverManager.getConnection(url, user, password);
		// 表面本身不能用占位符  只有数据可以
		String sql ="insert into kk values(?,?,?,?)";
		PreparedStatement ps = connection.prepareStatement(sql);
		for (int i = 0; i < 20; i++) {
			ps.setInt(1, i);
			ps.setString(2, "dy"+i);
			ps.setInt(3, i);
			ps.setDate(4, new Date(System.currentTimeMillis()));
			// 结构相同,值不同
			// 将sql语句具体赋值之后的语句存入类似语句池一样的批处理池,等待执行。
			ps.addBatch();
			if(i%200==0){
			// 每俩百条执行一次
			ps.executeBatch();
			}
		}
		// 将批处理池中剩余的所有的sql语句全部执行
		ps.executeBatch();
		ps.close();
		connection.close();
	}

4.2 CallableStatement

CallableStatement接口,简称CS,它除了拥有俩个父接口的功能特点之外,它还有有着自己的特点:可以调用数据库中的存储过程。(了解即可)

5.线程池

5.1 概述

池技术在一定程度上可以明显优化服务器应用程序的性能,提高程序执行效率和降低系统资源的开销。

例如,数据库连接池,在系统初始化时创建一定数量数据库连接对象,需要时直接从池中取出一个空闲对象,用完后并不直接释放掉对象,而是再放到对象池中,以便下一次对象请求可以直接复用。

这样可以消除对象创建和销毁所带来的延迟,从而提高系统的性能。

在当前数据库环境下,创建出一定数据的数据库之后,就无法再创建新的对象了。

而数据库连接池,就可以在种情况下,预先创建出一批数据库连接对象,然后对它们进行管理,并反复使用,这样就不需要频繁的销毁和创建了,提供了资源的利用率。

5.2 druid

druid 是阿里巴巴开源的数据库连接池项目

javax.sql.DataSource是Java中定义的一个数据源标准的接口,通过它获取到的数据库连接对象,如果调用close()方法,不会再关闭连接,而是归还连接到连接池中。
相比 之前 DateSource.properties;
有驱动类名 url 用户名 用户密码 还多了 连接池 默认连接数(initialSize)和 最大连接数(MaxActive) (MaxActive不超过18 原则上 尽量远离18 占用太多可能会导致其他程序用不了而出错)。
当然还有一些其他的设置,如最大等待时间等。
具体druid中的配置信息的key是固定的,com.alibaba.druid.pool.DruidDataSourceFactory类中定义了静态常量,记录了这些key的名字。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值