JDBC 简介及基本使用
一:jdbc简介:
1:定义:
JDBC是一套协议,是JAVA开发人员和数据库厂商达成的协议,也就是由Sun定义一组接口,由数据库厂商来实现,并且为java开发人员提供调用接口方法。是java 访问数据库的唯一的,统一的,底层的API
2:产生的背景和原因:
(1)由java从小设备应用发展到通用语言,跟企业打交道一定要和数据库打交道,这就是java为联结数据库发明API的原因
(2):java的平台无关性,就需要自己重新开发一套平台无关的联结数据库语言,
(3):java希望所用的代码都在虚拟机中运行,以保证安全性。
3:数据库驱动的概念:
驱动本质上是一个某个数据库厂商实现的jdbc接口的类库,
注意:数据库驱动不是一定要实现这个类库中的所有接口,但是必须实现java.sql.Driver接口。
二:jdbc中常使用的接口
1:Driver:驱动
2:DriverManager:辅助管理驱动
3:Connection :数据库联接
4:Statement :对数据库的操作对象(通过SQL语句操作)
5:ResultSet: 结果集
三.JDBC应用步骤
1,注册加载一个driver驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
2,创建数据库连接(Connection)
String url="jdbc:oracle:thin:@192.168.0.23:1521:tarena" ;
String user="openlab";
String password="open123";
con=DriverManager.getConnection(url,user,password);
3,创建一个Statement(发送sql)
String sql="select first_name,id from s_emp";
state=con.createStatement();
4,执行sql语句
ResultSetrs=state.executeQuery(sql)
5,处理sql结果(select语句,关闭rs)
while(rs.next()){
System.out.print(rs.getInt("id"));
System.out.println(""+rs.getString("first_name")); }
6,关闭Statementstate.close()
7,关闭连接Connection con.close()
注意:
(1)关闭对象的步骤势必须要做的,因为这些资源是不会自动释放的,必须要自己关闭
(2)要按先ResultSet结果集,后Statement,最后Connection的顺序关闭资源,因为Statement和ResultSet是需要连接时才可以使用的,所以在使用结束之后有可能其他的Statement还需要连接,所以不能先关闭Connection。
四:细节知识点
1: 常用驱动类
(1)Oracle的Driver
oracle.jdbc.driver.OracleDriver
(2)mysql的Driver
com.mysql.jdbc.Driver
(3)SQLServer的Driver的全名com.microsoft.jdbc.sqlserver.SQLServerDriver2:
2:常用的url书写格式
(1)Oracle URL的格式
例:jdbc:oracle:thin:@192.168.0.20:1521:tarenadb
(2)MySql URL的写法
例: jdbc:mysql://localhost:3306/tarena
(3)SQLServer URL的写法
例:jdbc:microsoft:sqlserver://localhost:1433/test
3:statement的方法作用和区别
excute():任何语句都可以
executeUpdate():增,删,改,创建
executeQuery():查询
4:固定驱动(了解)
如果想要用固定的driver 而不是要让驱动管理器一个一个的找,那么需要明确的driver ,可以通过new 的方式,显式的创建driver
例如:
Driver drv = new oracle.jdbc.driver.OracleDriver();
DriverManager.registerDriver(drv);
5:激发驱动类加载的方式
(1) 直接在获得连接的代码中调用Class.forName(“”);
(2)直接在静态代码块中调用Class.forName(“”);
(3) 通过命令行参数传入,(本质上传入的是字符串)
Class.forName(args[0]);
(4)通过虚拟机参数传入
终端命令行传入,
例如Java-Djdbc.drivers=oracle.jdbc.driver.OracleDriver FristJdbc.java
在eclipse中加入虚拟机参数的方式。
6:PreparedStatement的使用(从Statement继承而来)
同构SQL:SQL语句基本一样,只是具体参数值不同.
异构SQL:SQL语句完全不一样.
Statement不足:
1.效率比较低;
2.对字段类型的支持比较差;
3.语法含义不清晰.(结构不清楚)
由于编译时不需要参数,PreparedStatement 可以使用"?"来替代sql语句中的某些参数,它先将不带参数的sql语句发送到数据库,进行预编译,然后PreparedStatement会再将设置好的参数发送给数据库。
在使用PreparedStatement设置相应参数时,要指明参数的位置和类型,以及给出参数的具体值。(注意:参数的位置从1开始)
根据不同的参数类型使用不同的setXXX(参数的位置,参数值)来设置参数
如:
String sql = "update XXXset x=? where XXX;"; //?
PreparedStatement ps =con.prepraredStatement(SQL);//SQL语句已经送到数据库去编译了,即预编译
ps.setXXX(参数的位置,参数值)
ps.executeUpdate();
五:元数据
1:概念和作用:
用来描述对象信息的对象
2:分类
(1):resultSetMetaData:用来描述结果集的信息
ResultSetMetaDatamd=ResultSet.getMetaData();
(2):DatabaseMetaData:用来描述数据库的信息
DatabaseMetaDatemd=Connection.getMetaData();
结果集元数据中常用的方法:
1.获得字段个数
2.获得字段名称
3.获得字段类型
如:
ResultSet rs=ps.executeQuery(sql);
ResultSetMetaData m=rs.getMetaData();
getColumnCount(),获得实际列数
getColumnName(int colnum),获得指定列的列名
getColumnType(int colnum),获得指定列的数据类型(Types里面的类型,存放的是整数)
getColumnTypeName(int colnum),获得指定列的数据类型名
事务
一:事务(Transaction)
原子操作:不可再分的操作,一个操作不能再分成比它更细小的操作.
事务是针对原子操作的,要求原子操作不可再分,并且必须同时成功同时失败。
事务就是把一些非原子操作,变成原子操作,由应用服务器来提出要求,由数据库服务器来执行操作.
二:jdbc中使用事务的基本步骤
在JDBC中默认是自动提交的【但是Hibernate默认不是自动提交的】,如果要想使用事务,需要按以下步骤执行:
1.要调用con.setAutoCommite(false)方法,把自动提交(commit)置为false。
2.进行正常的数据库操作
3.如果操作成功了可以选择con.commit(),或者操作失败时选择con.roolback();
注意:打开事务就要关闭自动提交,当不需要再使用事务的时候调用setAutoCommite(true).
三:事务并发产生的问题
三种并发产生的后果:
1,脏读:一个事务读取到了另外一个事务没有提交的数据。
2,重复读:一个事务读取到了另外一个事务提交的数据。它是要保持在同一时间点上读取到的数据相同,希望在一段时间内的数据是不变的。
3,幻读:一个事务读取到了另外一个事务提交的数据。用同样的操作读取两次,得到的记录数不相同。
四:事务五种控制级别:
TRANSACTION_NONE不使用事务。
TRANSACTION_READ_UNCOMMITTED允许脏读。
TRANSACTION_READ_COMMITTED防止脏读,最常用的隔离级别,并且是大多数数据库的默认隔离级别
TRANSACTION_REPEATABLE_READ可以防止脏读和不可重复读,
TRANSACTION_SERIALIZABLE可以防止脏读,不可重复读取和幻读,(事务串行化)会降低数据库的效率
五:定义事务的隔离级别
以上的五个事务隔离级别都是在Connection类中定义的静态常量,使用setTransactionIsolation(intlevel) 方法可以设置事务隔离级别。
如:con.setTransactionIsolation(Connection.REPEATABLE_READ);
Jdbc 新特性
一.结果集的可滚动特性和可更新特性
JDBC1.0中是指游标的移动的方向和方式是单向,单步(相对)移动,功能比较简单.
JDBC2.0中游标可以双向,相对或者绝对移动.
可滚动结果集:这种结果集不但可以双向滚动,相对定位,绝对定位,并且还可以修改数据信息。
基本语法:
Statement st=null;
st=con.createStatement(ReusltSet.TYPE_SCROLL_INSENSITIVE,ResuleSet.CONCUR_UPDATABLE)
在创建Statement的时候就要指定这两个参数,使用Statement,第一个参数代表滚动特性常量,第二个代表更新特性常量
1:滚动特性
(1).滚动特性常量:
●:TYPE_FORWARD_ONLY
该常量表示指针只能向前移动ResultSet 对象的类型。(默认)
●:TYPE_SCROLL_INSENSITIVE
该常量指示可滚动但通常不受其他更改影响的 ResultSet 对象的类型。
●:TYPE_SCROLL_SENSITIVE
该常量指示可滚动并且通常受其他更改影响的 ResultSet 对象的类型。(也即数据库改变,结果集改变)
(2)常用方法
定位方法:
boolean absolute(int row)定位到指定的记录位置。成功返回true,否则返回false。
void afterLast() ,把游标移动到最后一条记录的后面(逻辑位置)。
void beforeFirst() ,把游标移动到第一条记录的前面(逻辑位置)。
//由于第一条记录的前面和最后一条记录的后面这两个位置肯定存在,所以无需判断是否存在,返回值设为void.
boolean first(),把游标定位到第一条记录。
boolean last(),把游标定位到最后一条记录。
//当结果集为空的时候,这两个方法会返回false.
boolean next(),此方法是使游标向下一条记录移动。
boolean previous() ,此方法可以使游标向上一条记录移动,前提是前面还有记录。
boolean relative(int rows) ,相对定位方法,参数值可正可负,参数为正,游标从当前位置向后移动指定值条记录,参数为负,游标从当前位置向前移动指定值条记录。
判断方法:
ifBeforeFirst()判断是否在在第一条记录之前.
ifAfterLast()判断是否在在最后一条记录之后.
ifFirst()判断是否为第一条记录.
ifLast()判断是否为最后一条记录.
2:可更新特性
(1).更新特性常量:
●:CONCUR_READ_ONLY 只读结果集(默认)
●:CONCUR_UPDATABLE 可更新结果集
(2)更新特性的常用方法
a.moveToInsertRow();记录当前游标位置,将游标移到和结果集结构类似的缓冲区;
b.使用updateXxx(int column,columnTypevalue)方法来更新指定列数据;
c.使用insertRow() 方法插入记录;
d.将游标指回原位,moveToCurrentRow() 。
3:滚动特性和更新特性的使用限制
(1)能否使用JDBC2.0 ResultSet的新特性,要看使用的数据库驱动是否支持.
(2)还有只能用于单表且表中有主键字段(可能会是联合主键),不能够有表连接,
可更新操作还必须满足以下条件:
a.查询只能引用一张表.
b.不能包含任何连接操作.
c.必须把完整的主键查到结果集里面;
d.保证所有字段为非空字段并且没有默认值。
二.批量更新
优势:
1.节省传递时间
2.并发处理
PreparedStatement:
1.addBatch() 将一组参数添加到 PreparedStatement对象内部
2.executeBatch() 将一批参数提交给数据库来执行,如果全部命令执行成功,则返回更新计数组成的数组。
注意:PreparedStatement中使用批量更新时,要先设置好参数后再使用addBatch()方法加入缓存。
批量更新中只能使用更新或插入语句
三.SQL3中的数据类型-大对象
1:优点:
(1)理论上大小没有上限,受制于数据库表空间的大小.
(2)流式读取.
2:大对象的分类:
(1)Blob:大的二进制数据文件对象。
(2)Clob:大的文本文件对象。
3:使用大对象的步骤:
(1)先插入一个空的占位对象empty_blob()(oracle的函数):insert into t_blobvalues(?,?,empty_blob());
(2)获得大对象:select blob_data from t_blobwhere name = ? for update;
(3)获取流进行写入:blob.setBinaryStream(0);
(4)通过流来获取blob中存储的数据:blob.getBinaryStream()
二.JDBC2.0扩展(目前大概了解)
1.JNDI(JAVA命名目录接口)也用于存储数据,但是他所存储的是一些零散的信息,只提供简单的API进行读取,需要有命名服务器。
最有价值的是提供了一种访问网络上各种不同资源的一致,标准的方法。
2.数据源:
最重要的好处是隐藏了数据库的链接的细节信息,而只需要知道这个数据源在jdni中的名称。一旦获得数据源对象,就可以通过数据源的getConnection()方法来获得数据库连接。
Jndi和datasource的使用时绑定在一块的。
bind(String name, Object obj) 将名称绑定到对象资源,建立指定的字符串和对象资源的关联
lookup(String name) ,通过指定的字符串获得之前绑定的资源
3.连接池:
保持连接池中有指定个数的连接,并在程序使用过之后不关闭连接,再放回连接池中等待其他的程序在需要时来取用,这样可以大量的节省销毁和创建连接的资源消耗。
4.分布式的事务:
分布式事务是针对多个不同数据库同时操作,要保证原子操作的不可分,事务的提交和回滚交给中间服务器来处理。
(两阶段提交),也就是在中间服务器发送sql语句等待数据库回应,都回应操作成功才提交,否则同时回滚。
5.RowSet:
行集:增强了ResultSet的功能,通过RowSet可以获得数据源,并且它还可以使用RowSet的方法。
CachedRowSet能够自动得到连接和断开连接.
6.CallableStatement:
CallableStatement是可以用非sql语句来访问数据库,他是通过调用存储过程(PL/SQL)来访问数据库的,这样保证安全.
可以使用com.prepareCall(存储过程名)方法,来执行这个存储过程。
缺点:
1.可移植性差
2.速度上的优势并不明显
三.Object-Relational-Mapping(重点理解)
1.实体映射关系对应
类应当对应到表,
属性对应到字段,
对象对应到记录,
类之间的关系对应到表之间的关系.