JDBC

JDBC六个基础步骤

注册驱动 Class.forName

  • 将驱动类的 class 文件装载到内存中,并且形成一个描述此驱动类结构的 Class 类实例,并且初始化此驱动类,这样 jvm 就可以使用它了,这就是 Class.forName() 方法的含义。
  • 加载过程中如果类中有静态初始化器,JVM 必然会执行该类的静态代码 段。
public class MyJDBCDriver implements Driver { 
    static { 
        DriverManager.registerDriver(new MyJDBCDriver()); 
    } 
} 
  • 任何一个 JDBC Driver 的 Driver 类的代码都必须类似如下,所以加载数据库驱动包的时候不需要调用 newInstance() 方法。
Class.forName("com.mysql.cj.jdbc.Driver");//MYSQL8.0以上
Class.forName("com.mysql.jdbc.Driver");//8.0以下

创建连接 getConnection

conn = DriverManager .getConnection("jdbc:mysql://localhost:3306/database1?serverTimezone=UTC","root","123456");
//数据库url--注意设置时区否则会报错,用户名,密码
conn = DriverManager .getConnection("jdbc:mysql://localhost:3306/database1?serverTimezone=UTC&root&123456");
//可以写成拼接样式

创建传输器 createStatement

stat = DriverManager .getConnection("jdbc:mysql://localhost:3306/tedudemo?serverTimezone=UTC&root&123456").createStatement();
stat = conn.createStatement();

传输SQL executeQuery/executeUpdate

  • executeQuery 仅查询
  • executeUpdate 执行增删改
rs = stat.executeQuery("SELECT * FROM employ");//仅查询
int count = stat.executeUpdate("UPDATE employ SET name = 'lvbu'  ");//执行增删改,返回值是影响的行数

处理结果 ResultSet

  • ResultSet表示数据库结果集的数据表,通常通过执行查询数据库的语句生成。
  • ResultSet 对象具有指向其当前数据行的光标。最初,光标被置于第一行之前。next 方法将光标移动到下一行
  • 该方法在 ResultSet 对象没有下一行时返回 false,可以在 while 循环中使用它来迭代结果集。
几个方法
  • get方法
    • int getInt(int columnIndex) 以 Java 编程语言中 int 的形式获取此 ResultSet 对象的当前行中指定列的值。
    • int getInt(String columnLabel) 以 Java 编程语言中 int 的形式获取此 ResultSet 对象的当前行中指定列的值。
    • Array getArray(int columnIndex) / Array getArray(String columnLabel)
    • 等等
  • 判断光标位置
    • boolean isAfterLast() 获取光标是否位于此 ResultSet 对象的最后一行之后。
    • boolean isBeforeFirst() 获取光标是否位于此 ResultSet 对象的第一行之前。
    • boolean isFirst() 获取光标是否位于此 ResultSet 对象的第一行。
    • boolean isLast() 获取光标是否位于此 ResultSet 对象的最后一行。
  • 移动光标
    • boolean next()
    • boolean previous()
while (rs.next()) {
	int id = rs.getInt("age");
	System.out.println("age" + id);
}

关闭资源

  • 后创建的先关闭
rs.close();
stat.close();
conn.close();

JDBC流程改进

  • 设置properties文件,通过读取配置文件的形式可以实现代码的深层次解耦
  • 封装流程,简化开发

Properties类

  • Properties类表示一组持久的属性,可以保存到流中或从流中加载,属性列表中的每个键及其对应的值都是一个字符串。
  • 这个类是线程安全的:多个线程可以共享一个Properties对象,而不需要外部同步。
getProperty(String key)//使用此属性列表中指定的键搜索属性
public void load(InputStream inStream)//从输入字节流读取属性列表(键和元素对)。
public void load(Reader reader)
public void store(OutputStream out, String comments)//将此属性列表(键和元素对)写入此Properties表中
public void store(Writer writer,String comments)    
public void loadFromXML(InputStream in)//将指定输入流中的XML文档表示的所有属性加载到此属性表中
public void storeToXML(OutputStream os,String comment)

创建配置文件并加载

driver=com.mysql.cj.jdbc.Driver
user=root
password=123456
url=jdbc:mysql://localhost:3306/database1?serverTimezone=UTC

  • 加载器,需要提供流参数
    • 创建流,需要提供文件对象参数
      • 创建文件对象,需要提供路径参数
        • 获取文件路径(字符串类)
  • 所以实际顺序为 获取文件路径→创建文件→创建流→加载器加载
public class PropertiesDemo {

	public static void main(String[] args) throws FileNotFoundException, IOException {
		Properties properties = new Properties();
		//PropertiesDemo.class获取类的字节码对象  getResource/getClassLoader/需要由字节码对象调用
		//getClassLoader()获取类加载器
		//getResource("src目录中的任意文件名")获取配置文件路径
		//getPath()将url类型变为String类型
		URL url = PropertiesDemo.class.getClassLoader().getResource("conf.properties");
		String str = url.getPath();
		System.out.println(url);
		System.out.println(str);
		//创建文件、流、并加载
        properties.load(new FileInputStream(new File(str)));
		properties.list(System.out);
		System.out.println(properties.getProperty("driver"));
	}

}

在这里插入图片描述

.class.getResource() 和 .class.getClassLoader().getResource ()
  • .class.getResource(" "); 以当前包路径为开始
  • .class.getClassLoader().getResource (" ");返回的是classpath的位置–bin 是不是可以说src路径下就相当于bin路径下?
package logindemo;
import java.net.URL;
public class PathDemo {
	public static void main(String[] args) {
		URL u1 = PropertiesDemo.class.getResource("");
		URL u2 = PropertiesDemo.class.getClassLoader().getResource("");
		System.out.println(u1);
		System.out.println(u2);
		URL u1p = PropertiesDemo.class.getResource("conf.properties");
		URL u2p = PropertiesDemo.class.getClassLoader().getResource("conf.properties");
		System.out.println(u1p);
		System.out.println(u2p);
	}
}

在这里插入图片描述

路径内有无 /

可以看到,路径名内有"/"返回的是classpath。

package logindemo;
import java.net.URL;
public class PathDemo {
public static void main(String[] args) {
		URL u1 = PropertiesDemo.class.getResource("/");
		URL u2 = PropertiesDemo.class.getClassLoader().getResource("");
		System.out.println(u1);
		System.out.println(u2);
		URL u1p = PropertiesDemo.class.getResource("/conf.properties");
		URL u2p = PropertiesDemo.class.getClassLoader().getResource("conf.properties");
		System.out.println(u1p);
		System.out.println(u2p);
	}

}

在这里插入图片描述

封装流程

创建连接
public static Connection getConnection() throws Exception{
		
		//读取prop对象身上的参数
		Class.forName(prop.getProperty("driver"));
		//创建数据库连接
		return DriverManager.getConnection(prop.getProperty("url"),
				prop.getProperty("user"), prop.getProperty("password"));
	}	
关闭资源
public static void close(Connection conn,Statement stat,ResultSet rs){
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}finally{
				rs = null;
			}
		}
		
		if(stat !=null){
			try {
				stat.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}finally{
				stat = null;
			}	
		}
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}finally{
				conn = null;
			}
		}
		
	}

完整代码

  • 去耦,去重
package logindemo;

import java.io.File;
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 class JDBCUtils {
	//不允许创建对象
	private JDBCUtils(){
		
	}
	//能够读取properties配置文件的类型
	private static Properties prop = new Properties();
	static{
		//加载配置信息到prop对象身上
		try {
			prop.load(new FileInputStream(new File(
				//JDBCUtils.class获取类的字节码对象
				//getClassLoader()获取类加载器
				//getResource("src目录中的任意文件名")获取当前工程的src目录
				//getPath()将uri类型变为String类型
				JDBCUtils.class.getClassLoader().getResource("conf.properties").getPath()
				)));
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	//通过类调用方法
	//创建连接
	public static Connection getConnection() throws Exception{
		
		//读取prop对象身上的参数
		Class.forName(prop.getProperty("driver"));
		//创建数据库连接
		return DriverManager.getConnection(prop.getProperty("url"),
				prop.getProperty("user"), prop.getProperty("password"));
	}
	//关闭资源
	public static void close(Connection conn,Statement stat,ResultSet rs){
		if(rs != null){
			try {
				rs.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}finally{
				rs = null;
			}
		}
		
		if(stat !=null){
			try {
				stat.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}finally{
				stat = null;
			}	
		}
		if(conn != null){
			try {
				conn.close();
			} catch (SQLException e) {
				e.printStackTrace();
				throw new RuntimeException(e);
			}finally{
				conn = null;
			}
		}
		
	}

	
}

批处理

  • addBatch(" SQL语句 ");
  • executeBatch(); 批量执行语句 添加完执行
package batchOperation;

import java.sql.Statement;
import logindemo.JDBCUtils;
import java.sql.Connection;
import java.sql.SQLException;
/*
 create table t1(id int,name varchar(20))
 insert into t1 values(1,'猪八戒')
 insert into t1 values(2,'沙和尚')
 insert into t1 values(3,'唐三藏')
 insert into t1 values(4,'白龙马')
 insert into t1 values(5,'孙悟空')
 */
public class StateBatchDemo1 {
	public static void main(String[] args) {
		Connection conn = null;
		Statement stat = null;
		try {
			conn = JDBCUtils.getConnection();
			stat = conn.createStatement();
			stat.addBatch("create table t1(id int,name varchar(20))");
			stat.addBatch("insert into t1 values(1,'猪八戒')");
			stat.addBatch("insert into t1 values(2,'沙和尚')");
			stat.addBatch("insert into t1 values(3,'唐三藏')");
			stat.addBatch("insert into t1 values(4,'白龙马')");
			stat.addBatch("insert into t1 values(5,'孙悟空')");
			stat.executeBatch();
			System.out.println("处理完成");
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			JDBCUtils.close(conn, stat, null);
		}
		
	}

}

预编译功能 PreparedStatement

  • 防止SQL注入攻击
  • 预编译 先将SQL语句主干传入到服务器,并保持不变,再传入参数
  • 使用 ? 占位。
package batchOperation;
/*
   缺点 只能执行一种语义sql
  优点  1 预编译功能 
     2 sql主干存储在服务器中,只发送参数,不需要每次都发送主干,执行效率高 
 */
import java.sql.Connection;
import java.sql.PreparedStatement;
import logindemo.JDBCUtils;
//preparedstatement批处理
public class PrepareBatchDemo1 {

	public static void main(String[] args) {
		Connection conn = null;
		PreparedStatement ps = null;
		try {
			conn = JDBCUtils.getConnection();
			ps = conn.prepareStatement("insert into t1 values(?,?)");
			for(int i = 0;i<10000;i++) {
			ps.setInt(1, i);//设置第一列数据 返回值类型是int
			ps.setString(2, "name"+i);//设置第二列数据 返回值类型是String
			ps.addBatch();//添加
			if(i%1000==0) {
				ps.executeBatch();//每到1000个语句执行操作,然后清空
				ps.clearBatch();//清空操作
				System.out.println("第"+i/1000+"批处理完毕");
			}
			}
			ps.executeBatch();

		} catch (Exception e) {
			// TODO: handle exception
			e.printStackTrace();
		}finally {
			JDBCUtils.close(conn, ps, null);
		}

	}

}

在这里插入图片描述

连接池

  • 传统方式中,创建和销毁连接都会消耗大量资源,为了复用连接。
  • 使用完连接还给连接池(不关闭的才可以复用)
DBCP
C3P0

SQL

聚集函数

avg count max min sun

select avg(age) from users;
select avg(age) from users where gender = '男';
//count 不指定列名会计算null行,否则不会计算
 select count(*) from users;
 select count(id) from users;
//max min 忽略null
//sum 忽略null
//组合
select avg(),count(),min() from XXX;
聚集不同的值 DISTINCT

10 10 4

select avg(age) from users; 8
select avg(DISTINCT age) from users; 7

分组 group by + having过滤分组

where可以用having代替

select XXX from XXX 
where XXX 
group by XXX 
having XXX 
order by XXX
limit XXX;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值