JDBC总结

目  录


一、 JDBC概述 1

1.1 什么是JDBC 1

1.2什么是驱动 1

1.3 SQL lite 1

1.4如何使用Java连接某种数据库 1

1.5连接数据库并操作 1

1.6连接数据库时常见的错误 1

二、 JDBC核心API 2

2.1 Connection 2

2.2 Statement 2

2.3 ResultSet 2

2.4 DriverManager 2

2.5 UUID 3

2.6案例:使用JDBC连接数据库,并操作SQL语句 3

2.7案例:通过JDBC创建表 4

2.8案例:使用JDBC向表中插入数据 4

2.9遍历Student_chang表 5

三、 JDBC核心API:PreparedStatement 6

3.1Statement的缺点 6

3.2PreparedStatement的优点 6

3.3案例详见第五章StudentDAO类 6

四、 Connection封装 7

五、 DAO 8

5.1持久类封装 8

5.2 DAO层 8

5.3 Properties类 8

5.4案例:注册系统 8

六、 批处理 12

6.1批处理的优点 12

6.2 JDBC批处理API 12

6.3案例:详见8.4案例step7 12

七、 事务处理 13

7.1事务特性ACID 13

7.2 JDBC中对事务的支持(API) 13

八、 DAO事务封装 14

8.1ThreadLocal原理 14

8.2原理图 14

8.3ThreadLocal核心API 14

8.4案例:登录系统(使用ThreadLocal实现连接共享) 14

九、 分页查询 17

9.1分页查询的基本原理 17

9.2为何使用分页查询 17

9.3 Oracle分页查询SQL语句 17

9.4 MySQL分页查询SQL语句 17

9.5“假”分页 17

9.6案例:分页查询 18



一、JDBC概述

1.1 什么是JDBC

1)Java的设计者希望使用相同的方式访问不同的数据库。

2)JDBC是Java用于统一连接数据库并操作数据库的一组通用接口定义(即通过一系列接口定义了访问数据库的通用API)。

3)JDBC是连接数据库的规范,不同的数据库厂商若想让Java语言可以对其操作,就需要实现一组类,这组类需要实现Java提供的这组用于连接数据库的接口,并实现其中定义的相关方法。那么不同的数据库厂商根据各自数据库的特点,去提供对JDBC的实现(实现类包),那么这组类就是该数据库的驱动包了。

4)原理图:

1.2什么是驱动

简单的说就是让软件知道如何去操作硬件。

1.3 SQL lite

是轻量级的数据库,常用于嵌入式。

1.4如何使用Java连接某种数据库

需要两个部分:1)使用JDBC连接数据库(导入某数据库的.jar包)。

  2)提供对该数据库的驱动包(使用静态方法Class.forName注册驱动)。

1.5连接数据库并操作

1)打开与数据库的连接(使用DriverManager.getConnection获取连接)。

2)执行SQL语句(使用Statement或者PreparedStatement)。

3)得到结果。

1.6连接数据库时常见的错误

1)报错ClassNotFoundException则有两种情况:

①驱动包没导入。

②Class.forName()中的字符串拼写有误。

2)报错port number,应注意:

①连接数据库时输入数据库路径时没有添加端口号。

②Oracle数据库的完整写法应为:jdbc:oracle:thin:@IP地址:端口号:数据库名

u 注意事项:Oracle数据库默认端口号1521。MySql数据库默认端口号为3306

二、JDBC核心API

2.1 Connection

接口,需导入java.sql.Connnection包,与特定数据库进行连接(会话)。

2.2 Statement

接口,需导入java.sql.Statement包,用于执行静态SQL语句并返回它所生成结果的对象。

1)ResultSet executeQuery(String sql) throws SQLException方法:执行给定的SQL语句(通常为静态SQL SELECT语句),该语句返回单个ResultSet对象。 

2)boolean execute(String sql) throws SQLException方法:执行给定的SQL语句,该语句可能返回多个结果。如果第一个结果为ResultSet对象,则返回true;如果其为更新计数或者不存在任何结果,则返回false。详细介绍请看2.6案例注释。

3)int executeUpdate(String sql) throws SQLException方法:执行给定SQL语句,该语句可能为INSERT、UPDATE、DELETE(DML语句),或者不返回任何内容的DDL语句。返回值:①对于数据操作语句(DML语句),返回行计数。②对于DDL语句,返回0。

4)boolean execute(String sql)方法:返回结果为true、false,常用与执行表级操作的SQL语句,如建表、删表等,创建表若失败实际上是会直接抛出异常的。false:为建表成功的标志。

5)exectue()方法:原则上可以执行任意SQL语句。返回true:若执行结果为一个结果集(ResultSet)。返回false:为其他信息(如影响表数据总条数等)。所以我们通常不会使用execute去执行查询语句。

6)int executeUpdate(String sql) throws SQLException方法:返回值int,返回值为当前执行的SQL语句影响了数据库数据的总条数;该方法常用与执行insert、update、delete语句。

7)在底层一定会用到网络Socket和流,但我们不用关心使用字符还是字节接收,都由Statement做了。

2.3 ResultSet

接口,表示数据库结果集的数据表(很像一个集合),通常通过执行查询数据库的语句生成。

1)ResultSet特点:按行遍历,按字段取值。

2)它的next()方法包含了是否有下一条记录的hasnext()方法。

3)按字段取值时,getString(int)方法中的int,代表结果集的第几列,

u 注意事项:这里的int从1开始,和Java对索引的习惯不同。

2.4 DriverManager

它是管理一组JDBC驱动程序的类。

1)Connection getConnection(String url,String user,String password)方法:静态方法,建立与给定数据库URL的连接(DriverManager试图从已注册的JDBC驱动程序集中选择一个适当的驱动程序)。 

2)DriverManager如何知道某种数据库已注册的?

例如:oracle.jdbc.driver.OracleDriver类在Class.forName()的时候被载入JVM;

而OracleDriver是JDBC中Driver的子类,它被要求在静态初始化的时候要将自身驱动的信息通过DriverManager的静态方法注册进去,这样DriverManager就知道应该如何通过OracleDriver去连接该数据库了。所以之后就可以通过DrvierManager的另一个静态方法:getConnection()来根据之前注册的驱动信息获取连接了:

  Connection conn=DriverManager.getConnetion("","","");

2.5 UUID

UUID为通用唯一标识码(Universally Unique Indentifier)对于大数据量的表来说,UUID是存放ID最好的方式。

1)Java提供的支持

UUID类:UUID.randomUUID().toString():获得一个36位不重复的字符串。

2)Oracle提供的支持

函数sys_guid():获取一个32位不重复的字符串。

2.6案例:使用JDBC连接数据库,并操作SQL语句

/** 连接数据库一定要捕获异常的 */

Connection conn=null;//定义在try外面是用于在finally块中关闭它,同时局部变量在使用前,一定要初始化!!

try{ /** 与数据库进行连接分为两步:1)注册驱动:不同的数据库实现不尽相同,所以要使用不同数据库厂商提供的驱动包。连接不同数据库,传入的字符串不尽相同,但是目的相同,都是注册驱动。而对于驱动包路径,名字是固定的,基本上不会变的!2)根据数据库的位置(路径)以及用户名和密码进行连接 */

Class.forName("oracle.jdbc.driver.OracleDriver");

/** 路径:不同数据库连接的路径写法不尽相同,Oracle的写法:                          jdbc:oracle:thin:@HOST:DB_NAME

       其中HOST包含两部分:IP地址和端口号;本机则使用localhost或127.0.0.1 */

conn=DriverManager.getConnection("jdbc:oracle:thin:@192.168.0.20:1521:tarena",

"jsd1304","jsd1304");

/** 使用SQL语句来操作数据库,若想执行SQL语句,我们需要使用一个专门处理SQL语句的类,这个类叫做Statement */

Statement state=conn.createStatement();

/** user_tables是Oracle用于存储当前用户创建的所有表的信息,其中一个字段叫做table_name用户保存的表名 */

String sql="SELECT table_name FROM user_tables";

/** 通过Statement执行查询语句,当查询完毕后,数据库会将查询结果返回,Statement会将查询结果存储到ResultSet中 */

ResultSet rs=state.executeQuery(sql);

while(rs.next()){ //按行遍历,包含了是否有下一条记录的方法hasnext()

/** 按字段取值;整数参数:结果集的第几列。注意:这里从1开始,和Java对索引的习惯不同 */

String tableName=rs.getString(1);

System.out.println(tableName);

}

/** 底层一定会用到网络socket和流,但我们不用关心使用字符还是字节接收,都由Statement做了 */

rs.close();

state.close();

}catch(Exception e){

e.printStackTrace();

}finally{

if(conn!=null){

try {

conn.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

}

u 注意事项: 养成良好的编码习惯:所有SQL关键字用纯大写,其他内容用纯小写 。

2.7案例:通过JDBC创建表

Connection conn=null;

try{ //1 注册驱动

Class.forName("oracle.jdbc.driver.OracleDriver");

//2 打开连接,支持import java.sql.*,但全导入较耗费性能

conn=DriverManager.getConnection(

"jdbc:oracle:thin:@192.168.0.20:1521:tarena","jsd1304","jsd1304");

//3 创建用于执行SQL语句的Statement

Statement state=conn.createStatement();

//创建建表语句

String sql="CREATE TABLE Student_chang(" +

"id varchar2(36) PRIMARY KEY," +"name varchar2(30)," +

"age number(2)," + "sex varchar2(2)" + ")";

//execute()方法详见2.2节

if(!state.execute(sql)){ System.out.println("创建表成功!");

}else{ System.out.println("创建失败!"); }

state.close();

}catch (Exception e){ e.printStackTrace();

}finally{ if(conn!=null){   try {  conn.close();  } catch (SQLException e) {

         e.printStackTrace();   }   } }

2.8案例:使用JDBC向表中插入数据

Connection conn=null;

try{ Class.forName("oracle.jdbc.driver.OracleDriver");

conn=DriverManager.getConnection(

"jdbc:oracle:thin:@192.168.0.20:1521:tarena","jsd1304","jsd1304");

Statement state=conn.createStatement();

//UUID详见2.5

String uuid=UUID.randomUUID().toString(); System.out.println(uuid);

String sql="INSERT INTO Student_chang VALUES('"+uuid +"','Chang',22,'1')";

    //或String sql="INSERT INTO Student_chang VALUES(sys_guid(),'chang',23,'1')";

//判断insert语句是否成功,看返回值是否大于0,executeUpdate方法详见2.2

if(state.executeUpdate(sql)>0){ System.out.println("插入数据成功"); }

state.close();

}catch(Exception e){ e.printStackTrace();

}finally{ if(conn!=null){  try { conn.close(); } catch (SQLException e) {

    e.printStackTrace(); } } }

2.9遍历Student_chang表

Connection conn=null;

try{ Class.forName("oracle.jdbc.driver.OracleDriver");

conn=DriverManager.getConnection(

"jdbc:oracle:thin:@192.168.0.20:1521:tarena","jsd1304","jsd1304");

Statement state=conn.createStatement();

String sql="SELECT * FROM Student_chang";

ResultSet rs=state.executeQuery(sql);

while(rs.next()){ String id=rs.getString(1);

String name=rs.getString("name");//不知第几列也可写列名

int age=rs.getInt("age");

String sex=rs.getString(4).equals("1")?"男":"女";

System.out.println(id+","+name+","+age+","+sex); }

rs.close(); state.close();

}catch(Exception e){ e.printStackTrace();

}finally{ if(conn!=null){  try {  conn.close(); } catch (SQLException e) {

 e.printStackTrace(); }  } }

三、JDBC核心API:PreparedStatement

3.1Statement的缺点

1)用Statement操作时代码的可读性和可维护性差,编写SQL语句复杂。

2)Statement操作SQL语句,每执行一次都要对传入的语句编译一次,效率比较差。

3)不安全可能出现SQL注入攻击,详见9.6案例step3。

4)扩展:XSS攻击、html代码注入攻击、struts2 OGNL存在可以远程执行底层操作系统命令的漏洞。

3.2PreparedStatement的优点

1)PreparedStatement实例包含已编译的SQL语句。包含于PreparedStatement对象中的SQL语句可具有一个或多个IN参数。IN参数的值在SQL语句创建时未被指定。该语句为每个IN参数保留一个问号(“?”)作为占位符,不考虑类型。每个问号的值必须在该语句执行之前,通过适当的setString、setInt、setDouble……等方法来提供。

2)由于PreparedStatement对象已预编译过,所以其执行速度要快于Statement对象。因此,多次执行的SQL语句经常创建为PreparedStatement对象,以提高效率。

3)PreparedStatement继承于Statement,其中三种方法:execute、executeQuery、executeUpdate都已被更改为不再需要参数了。因为我们在获取PreparedStatement时已经将SQL语句传入了。所以执行就可以,不需要再传入SQL。

4)PreparedStatement可以进行批量处理。

5)可以防止SQL注入攻击。

u 注意事项:

v 使用预编译语句,你传入的任何内容就不会和原来的语句发生任何匹配的关系,只要全使用预编译语句,你就不用对传入的数据作任何的过滤。

v 对一个表只作一个操作用PreparedStatement,效率高、方便

v 对表进行2种及以上的操作用Statement。

3.3案例详见第五章StudentDAO类

……………………

……………………



五、DAO

5.1持久类封装

对象关系映射(ORM)使用描述对象和数据库之间映射的元数据,将Java程序中的对象自动持久化到关系数据库中。1)表和类对应。2)表中的字段和类的属性对应。3)记录和对象对应。

5.2 DAO层

1)DAO:数据连接对象(DataAccessObjects)

2)作用:将数据库中的数据转化为Java的对象并返回(即读数据),将Java的对象转化为数据库中表的一条数据(即写数据)。

3)Java对象在这里就是所谓的实体entity,DAO要达到的目的:对数据库数据的操作面向对象化。

4)实体:用Java中的对象去描述数据库中的某表中的某一条记录。

比如:Student表有字段id、name、age、sex,则对应的Java类中有Student类,属性有id、name、age、sex

5)实体类:用于对应数据库中的表。通常实体类的名字和数据库中表的名字一致。

u 注意事项:实体类代表表,属性代表字段,对象代表一条数据。

5.3 Properties类

用于读取“.properties”文本文件的类,导入java.util.Properties包。

1)“.properties”文件是一个纯文本文件,里面定义的内容格式有要求,必须是key=value的形式,并且以行为单位。一行只记录一条数据!

2)Properties类可以方便的读取properties文件,并将内容以类似HashMap的形式进行读取。

3)db.properties文件里的内容如下:

  jdbc.driver=oracle.jdbc.driver.OracleDriver

  jdbc.url=jdbc:oracle:thin:@192.168.0.20:1521:tarena

  jdbc.user=jsd1304

  jdbc.pwd=jsd1304

u 注意事项:读取的都是字符串!不用写双引号,无空格!

4)getProperty(String key)方法:该方法可以从properties文件中获取数据,如:jdbc.driver=oracle.jdbc.driver.OracleDriver。获取方式是将jdbc.driver以key作为参数调用方法。返回的就是等号右面的值oracle.jdbc.driver.OracleDriver了。

5.4案例:注册系统

  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值