JDBC总结:系列笔记之四
[来源] 达内 [编辑] 达内 [时间]2013-08-13
参赛学员:常彦博
获奖奖项:二等奖
说明: (又花了几个小时把JDBC笔记转成了word版!笔记内容真实,都是课上及TTS上内容,不是从网上复制粘贴来的!同时也不会去刷点击率!不想评分的按F5 刷新页面即可!不用选择分数,一旦选择就不能改了! 也 可以拿到电子版后再来评分!Q在下 )
1)此笔记为本人系列笔记之一:Java、Oracle、PL/SQL、JDBC、XML、HTML、CSS、JavaScript、Servlet……
2)笔记内容整理了:JDBC(范传奇老师主讲,占笔记内容100%)。
3) 此笔记已打印出成品,一共 19页!(不包括目录)。 排版格式大部分按照毕业论文做的!有目录、章节、页眉、页脚、缩进、一二三级标题等。同时 排版格式也照顾到了双面打印,所以电子版可直接双面打印,不需要调格式。
因此,本人的系列笔记平均花费20 个小时以上(笔记纯手工输入)!每天的总结、排版很辛苦!之前有很多朋友拿到了我分享的笔记,因此还望各位尊重他人劳动成果(你懂得~~)。
4)评选系统由于不能上传word版,所以格式、布局上不太好看,如文中的注意事项有特殊项目符号,这里显示的是字母u和字母v,有的图片也不能显示!内容太长,老是提交失败!只能一点一点发!
5) 希望大家多多支持,评选结束后,我会找时间统一 分享给大家所有的笔记!之前拿到过的朋友,也可以再要,因为修改、更新了很多内容。
——————————————————&mda sh;————————————————————————————————————————————————
(目录若有链接,先不要点!会打开新页面的~)
目 录
三、 JDBC核心API:PreparedStatement 6
8.4案例:登录系统(使用ThreadLocal实现连接共享) 14
一、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或 */
conn=DriverManager.getConnection("jdbc:oracle:thin:@: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(()){ //按行遍历,包含了是否有下一条记录的方法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:@: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:@: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:@:tarena","jsd1304","jsd1304");
Statement state=conn.createStatement();
String sql="SELECT * FROM Student_chang";
ResultSet rs=state.executeQuery(sql);
while(()){ 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”文本文件的类,包。
1)“.properties”文件是一个纯文本文件,里面定义的内容格式有要求,必须是key=value的形式,并且以行为单位。一行只记录一条数据!
2)Properties类可以方便的读取properties文件,并将内容以类似HashMap的形式进行读取。
3)文件里的内容如下:
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@: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了。
网友评论 已有 0 条评论,查看更多评论»