JDBC

JDBC

一、JDBC概述

  1. JDBC(Java Database Connection)为java开发者使用数据库 提供了统一的编程接口,它由一组java类和接口组成。是java 程序与数据库系统通信的标准API。JDBC API 使得开发人员 可以使用纯java的方式来连接数据库,并执行操作。
  2. sun公司由于不知道各个主流商用数据库的程序代码,因此无 法自己写代码连接各个数据库,因此,sun公司决定,自己提 供一套api,凡是数据库想与Java进行连接的,数据库厂商自 己必须实现JDBC这套接口。而数据库厂商的JDBC实现,我们 就叫他此数据库的数据库驱动。
    在这里插入图片描述
  3. JDBC访问数据库流程
    • 加载一个Driver驱动
    • 创建数据库连接(Connection)
    • 创建SQL命令发送器Statement
    • 通过Statement发送SQL命令并得到结果
    • 处理结果(select语句)
    • 关闭数据库资源
      在这里插入图片描述

二、JDBC常用接口

  1. Driver接口
    • Driver接口由数据库厂家提供,对于java开发者而言,只需要使用 Driver接口就可以了。
    • 在编程中要连接数据库,必须先装载特定厂商的数据库驱动程序。不 同的数据库有不同的装载方法。
    • 驱动:就是各个数据库厂商实现的Sun公司提出的JDBC接口。 即对 Connection等接口的实现类的jar文件
    • 装载MySql驱动Class.forName(“com.mysql.jdbc.Driver”);
    • 装载Oracle驱动 Class.forName(“oracle.jdbc.driver.OracleDriver”);
  2. DriverManager接口
    • DriverManager是JDBC的管理层,作用于用户和驱动程序之间。
    • DriverManager跟踪可用的驱动程序,并在数据库和相应的驱动程序 之间建立连接。
  3. Connection接口
    • Connection与特定数据库的连接(会话),在连接上下文中执行 SQL 语句并返回结果。
    • DriverManager的getConnection()方法建立在JDBC URL中定义的数 据库Connection连接上
    • 连接MYSQL数据库:Connection con = DriverManager.getConnection(“jdbc:mysql://host:port/database”,“user”, “password”);
    • 连接ORACLE数据库:Connection con = DriverManager.getConnection(“jdbc:oracle:thin:@host:port:databse”,“us er”,“password”);
  4. Statement接口
    • 用于执行静态 SQL 语句并返回它所生成结果的对象。
    • 三种Statement类
      • Statement: 由createStatement创建,用于发送简单的SQL语句。(不带参数的)
      • PreparedStatement: 继承自Statement接口,由prepareStatement创建,用于发送含有一个或多 个输入参数的sql语句。PreparedStatement对象比Statement对象的效率更 高,并且可以防止SQL注入。我们一般都用PreparedStatement.
      • CallableStatement: 继承自PreparedStatement 。由方法prePareCall创建,用于调用存储过程。
    • 常用的Statement方法:
      在这里插入图片描述
  5. PreparedStatement接口
    1. 它是Statement接口的子接口;
    2. 强大之处:防止SQL攻击、提高代码的可读性、可维护性、提高效率
    3. 用法:
      • 给出SQL模板!
      • 调用Connection的PreparedStatement prepareStatement(String sql模板);
      • 调用pstmt的setXxx()系列方法sql模板中的?赋值!
      • 调用pstmt的executeUpdate()或executeQuery(),但它的方法都没有参数。
    4. 预处理的原理
      • 服务器的工作:
        • 校验sql语句的语法!
        • 编译:把SQL语句变成一个与函数相似的东西!
        • 执行:调用函数
      • PreparedStatement:
        • 前提:连接的数据库必须支持预处理!几乎没有不支持的!
        • 每个pstmt都与一个sql模板绑定在一起,先把sql模板给数据库,数据库先进行校验,再进行编译。执行时只是把参数传递过去而已!
        • 若二次执行时,就不用再次校验语法,也不用再次编译!直接执行!
    5. 什么是SQL攻击
      在需要用户输入的地方,用户输入的是SQL语句的片段,最终用户输入的SQL片段与我们DAO中写的SQL语句合成一个完整的SQL语句!例如用户在登录时输入的用户名和密码都是为SQL语句的片段!
  6. ResultSet接口
    • ResultSet对象是executeQuery()方法的返回值,它被称为结果集,它代表符合SQL语句条件的 所有行,并且它通过一套getXXX方法(这些get方法可以访问当前行中的不同列)提供了对这 些行中数据的访问。
    • ResultSet里的数据一行一行排列,每行有多个字段,且有一个记录指针,指针所指的数据行 叫做当前数据行,我们只能来操作当前的数据行。我们如果想要取得某一条记录,就要使用 ResultSet的next()方法 ,如果我们想要得到ResultSet里的所有记录,就应该使用while循环。
    • ResultSet对象自动维护指向当前数据行的游标。每调用一次next()方法,游标向下移动一行。
    • 初始状态下记录指针指向第一条记录的前面,通过next()方法指向第一条记录。循环完毕后 指向最后一条记录的后面。
    • 处理方法总结
      在这里插入图片描述

三、批处理(Batch)

  1. 对于大量的批处理,建议使用Statement,因为PreparedStatement的预编译空间有限 ,当数据量特别大时,会发生异常。
  2. 使用示例:
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
	//加载驱动类
	Class.forName("com.mysql.jdbc.Driver");
	conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","123456");
			
	conn.setAutoCommit(false);  //设为手动提交
	long start = System.currentTimeMillis();
	stmt = conn.createStatement();
			
	for(int i=0;i<20000;i++){
		stmt.addBatch("insert into t_user (username,pwd,regTime) values ('gao"+i+"',666666,now())");
	}
	stmt.executeBatch();
	conn.commit();  //提交事务
	long end = System.currentTimeMillis();
	System.out.println("插入20000条数据,耗时(毫秒):"+(end-start));
}

四、事物

  1. 事物基本概念

    • 一组要么同时执行成功,要么同时执行失败的SQL语句。是数据库操 作的一个执行单元!

    • 事务开始于: 连接到数据库上,并执行一条DML语句(INSERT、UPDATE或DELETE)。 或者前一个事务结束后,又输入了另外一条DML语句。

    • 事务结束于:

      • 执行COMMIT或ROLLBACK语句。
      • 执行一条DDL语句,例如CREATE TABLE语句;在这种情况下,会自动执 行COMMIT语句。
      • 执行一条DCL语句,例如GRANT语句;在这种情况下,会自动执行 COMMIT语句。
      • 断开与数据库的连接。
      • 执行了一条DML语句,该语句却失败了;在这种情况中,会为这个无效的 DML语句执行ROLLBACK语句。
    • jdbc处理事务的代码格式:

      try {
        con.setAutoCommit(false);//开启事务
        …
        …
        con.commit();//try的最后提交事务
      } catch() {
        con.rollback();//回滚事务
      }
      
      
  2. 事物的四大特点

    • atomicity(原子性):表示一个事务内的所有操作是一个整体,要 么全部成功,要么全失败;
    • consistency(一致性):表示一个事务内有一个操作失败时,所有的更改过的数据都必须回滚到修改 前的状态;
    • isolation(隔离性) :事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态, 要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。
    • durability(持久性):持久性事务完成之后,它对于系统的影响是永久性的。
  3. 三种并发读问题

    • 脏读:读到另一个事务的未提交更新数据,即读取到了脏数据;
    • 不可重复读:对同一记录的两次读取不一致,因为另一事务对该记录做了修改;
    • 幻读(虚读):对同一张表的两次查询不一致,因为另一事务插入了一条记录;
  4. 不可重复读和幻读的区别

    •  不可重复读是读取到了另一事务的更新;
    •  幻读是读取到了另一事务的插入(MySQL中无法测试到幻读);
  5. 四种事物隔离级别
    4个等级的事务隔离级别,在相同数据环境下,使用相同的输入,执行相同的工作,根据不同的隔离级别,可以导致不同的结果。不同事务隔离级别能够解决的数据并发问题的能力是不同的。

    • 读取未提交(Read Uncommitted)
      • 可能出现任何事务并发问题
      • 性能最好
    • 读取已提交(Read Committed)
      • 防止脏读,没有处理不可重复读,也没有处理幻读;
      • 性能比REPEATABLE READ好
    • 可重复读(Repeatable Read)
      • 防止脏读和不可重复读,不能处理幻读问题;
      • 性能比SERIALIZABLE好
    • 序列化(serializable)
      • 不会出现任何并发问题,因为它是对同一数据的访问是串行的,非并发访问的
      • 性能最差
  6. jdbc设置隔离级别
    con. setTransactionIsolation(int level),可选参数如下
    - Connection.TRANSACTION_READ_UNCOMMITTED;
    - Connection.TRANSACTION_READ_COMMITTED;
    - Connection.TRANSACTION_REPEATABLE_READ;
    - Connection.TRANSACTION_SERIALIZABLE。

五、CLOB与BLOB

  1. CLOB
    • 用于存储大量的文本数据

    • 大字段有些特殊,不同数据库处理的方式不一样,大字段的操作常常是以流的 方式来处理的。而非一般的字段,一次即可读出数据。

    • Mysql中相关类型

      • TINYTEXT最大长度为255字符的TEXT列。
      • TEXT[(M)]最大长度为65,535字符的TEXT列。
      • MEDIUMTEXT最大长度为16,777,215字符的TEXT列。
      • LONGTEXT最大长度为4,294,967,295或4GB字符的TEXT列。
    • 使用示例

      PreparedStatement ps = null;
      ResultSet rs = null;
      Reader r  = null;
      try {
      	//加载驱动类
      	Class.forName("com.mysql.jdbc.Driver");
      	conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","123456");
      			
      //	ps = conn.prepareStatement("insert into t_user (username,myInfo) values (?,?) ");
      //	ps.setString(1, "xxxx");
      //	ps.setClob(2, new FileReader(new File("d:/a.txt")));  //将文本文件内容直接输入到数据库中
      //  将程序中的字符串输入到数据库的CLOB字段中
      //	ps.setClob(2, new BufferedReader(new InputStreamReader(new ByteArrayInputStream("aaaabbbbbb".getBytes()))));
      
      
      //  读取数据库中的CLOB数据
      	ps = conn.prepareStatement("select * from t_user where id=?");
      	ps.setObject(1, 101024);
      			
      	rs = ps.executeQuery();
      	while(rs.next()){
      		Clob c = rs.getClob("myInfo");
      		r  = c.getCharacterStream();
      		int temp = 0;
      		while((temp=r.read())!=-1){
      			System.out.print((char)temp);
      		}
      	}
      			
      } 
      
  2. BLOB
    • 用于存储大量的二进制数据

    • 大字段有些特殊,不同数据库处理的方式不一样,大字段的操作常常是以流的 方式来处理的。而非一般的字段,一次即可读出数据。

    • Mysql中相关的类型

      • TINYBLOB最大长度为255字节的BLOB列。
      • BLOB[(M)]最大长度为65,535字节的BLOB列。
      • MEDIUMBLOB最大长度为16,777,215字节的BLOB列。
      • LONGBLOB最大长度为4,294,967,295或4GB字节的BLOB列。
    • 使用示例

      Connection conn = null;
      PreparedStatement ps = null;
      ResultSet rs = null;
      InputStream is  = null;
      OutputStream os = null;
      try {
      	//加载驱动类
      	Class.forName("com.mysql.jdbc.Driver");
      	conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testjdbc","root","123456");
      			
      //	ps = conn.prepareStatement("insert into t_user (username,headImg) values (?,?) ");
      //	ps.setString(1, "xxx");
      //	ps.setBlob(2, new FileInputStream("d:/icon.jpg"));
      //	ps.execute();
      			
      			
      	ps = conn.prepareStatement("select * from t_user where id=?");
      	ps.setObject(1, 101026);
      			
      	rs = ps.executeQuery();
      	while(rs.next()){
      		Blob b = rs.getBlob("headImg");
      		is  = b.getBinaryStream();
      		os = new FileOutputStream("d:/a.jpg");
      		int temp = 0;
      		while((temp=is.read())!=-1){
      			os.write(temp);
      		}
      	}
      			
      }
      

六、处理日期的相关类型:

  1. 数据库类型与java中类型的对应关系:
    DATE->java.sql.Date:表示年月日
    TIME->java.sql.Time:表示时分秒
    TIMESTAMP->java.sql.Timestamp:表示年月日时分秒
  2. 领域对象(domain)中的所有属性不能出现java.sql包下的东西!即不能使用java.sql.Date.但ResultSet#getDate()返回的是java.sql.Date()、PreparedStatement#setDate(int, Date),其中第二个参数也是java.sql.Date
  3. 类型转换:
java.util.Date ->java.sql.Date、Time、Timestamp
		- 把util的Date转换成毫秒值
		- 使用毫秒值创建sql的Date、Time、Timestamp
			java.util.Date date = new java.util.Date();
			long l = date.getTime();
			java.sql.Date sqlDate = new java.sql.Date(l);
		
java.sql.Date、Time、Timestamp ->java.util.Date
这一步不需要处理了:因为java.util.Date是java.sql.Date的父类;
PS:在mysql数据库中可以直接传入字符串形式的时间毫秒值

从proerties配置文件读取连接信息:

static Properties pros = null;   //可以帮助读取和处理资源文件中的信息

static {   
	pros = new Properties();
	try {
		pros.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
	} catch (IOException e) {
		e.printStackTrace();
	}
}
//使用pros.getProperty("key")获取连接的url、driver、username、pwd
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值