基本知识 1.ODBC的概述: ODBC是Open Database Connect即开放数据库互连的简称,它是由Microsoft 公司于1991 年提出的一个用于访问数据库的统一界面标准,是应用程序和数据库系统之间的中间件。它通过使用相应应用平台上和所需数据库对应的驱动程序与应用程序的交互来实现对数据库的操作,避免了在应用程序中直接调用与数据库相关的操作,从而提供了数据库的独立性。 2.ODBC访问数据库
3.JDBC的概述: Java Data Base Connectivity,(java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组 用Java语言编写的类和接口组成。JDBC为工具/数据库开发人员提供了一个标准的API,据此可以构建更高级的工具和接口,使数据库开发人员能够用纯Java API 编写数据库应用程序,同时,JDBC也是个商标名。 4.JDBC访问数据库
5.JDBC中API的两套接口(在java.sql和javax.sql两个包下面) ①Java应用程序开发者的接口 ②JDBC驱动程序开发商实现的接口 常用的API: java.sql:主要功能的JDBC在Java2平台标准版(J2SE) javax.sql:扩展功能的Java2平台企业版(J2EE) 6.JDBC的四种驱动类型
①第一代驱动:JDBC-ODBC桥 由于早期数据库都支持ODBC 标准,而JAVA本身还不够强大,所以当时各个厂商并未完全实现JDBC规范,所以只能通过JDBC-ODBC桥来与数据库通信;它每次都要把JAVA的调用转换成ODBC相关协议,再与数据库通信;效率低下。 ②第二代驱动:本地API部分Java驱动 要求客户开发机安装目标数据库的客户端代码;缺点:每个客户机都要安装,过于麻烦 ③网络协议驱动 这种驱动实际上是根据我们熟悉的三层结构建立的. jdbc先把对数局库的访问请求传递给网络上的中间件服务器.中间件服务器再把请求翻译为符合数据库规范的调用,再把这种调用传给数据库服务器.如果中间件服务器也是用java开发的,那么在中间层也可以使用1,2型 jdbc驱动程序作为访问数据库的方法. 网络协议驱动---------中间件服务器------数据库Server ④本地协议驱动 这种驱动直接把jdbc调用转换为符合相关数据库系统规范的请求.由于4型驱动写的应用可 本地协议驱动---------数据库Server 7.JDBC调用示意图
8.JDBC开发的接口 ①Driver:当前数据库本身的驱动 ②DriverManager:管理Driver ③Connection:连接数据库 ④Statement:执行sql语句 ⑤PreparedStatement:预编译的Statement ⑥CallableStatement:执行存储过程(封装sql语句) ⑦ResultSet:结果集 ⑧DatabaseMetadata:数据库的元数据,关于数据库的整体综合信息 ⑨ResultSetMetadata:结果集的元数据 ⑩Types:类型 接口和类示图如下:
9.JDBC的工作流
10.JPA: JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中。 11.JDBC的编程步骤 <1>:加载(注册)驱动(Class.forName(类的全限命名)) 注册驱动的三种方式: ①:第一种方式 Class.forName("oracle.jdbc.driver.OracleDriver");//加载驱动 Connection conn = DriverManager.getConnection ("jdbc:oracle:thin:@127.0.0.1:1521:XE", "system", "123456"); System.out.println("conn============>"+conn); ②:第二种方式 Driver driver = new oracle.jdbc.driver.OracleDriver(); DriverManager.registerDriver(driver);//(JDBC2.0以后可以省略,默认操作) Connection conn = DriverManager.getConnection ("jdbc:oracle:thin:@127.0.0.1:1521:XE", "system", "123456"); System.out.println("conn============>"+conn); ③:第三种方式: 在classpath下面加上 oracle驱动的全路径(包含驱动名本身) java -Djdbc.drivers=oracle.jdbc.driver.OracleDriver 类的全路径名 <2>:获得连接(database(url,username,password)) <3>:创建statement <4>:执行sql语句 <5>:处理结果集 <6>:释放资源 oracle驱动名称:oracle.jdbc.driver.OracleDriver url=jdbc:oracle:thin:@127.0.0.1:1521:XE mysql驱动名称:com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/mysql 导入数据库驱动的步骤:工程名--->Properties-->java build path----->Libraries-->Add External JARs Pg:package cn.com.ambow.jdbc.day1; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; public class SelectData { public static void main(String[] args) { Connection conn = null; Statement st = null; ResultSet rs = null; try{ //1:注册驱动 Class.forName("oracle.jdbc.driver.OracleDriver"); //2:获得链接 //mysql的url: jdbc:mysql://ip:端口号/数据库 //jdbc:mysql://localhost:3306/test conn=DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:XE", "system", "4080"); //3:创建statement st = conn.createStatement(); String sql = "select * from users"; //4:执行sql rs = st.executeQuery(sql); //5:处理结果集 while(rs.next()){ /** * rs.next()是获取数据库中每一行的数据 * jdbc中列的序列从1开始,而在hibernate中以0开始 */ System.out.println(rs.getString(1)); //1表示列的序列,这里是指id System.out.println(rs.getString(2));
System.out.println(rs.getString(3));
/*System.out.println(rs.getString("id")); //"id"是列的名称 System.out.println(rs.getString("name"));
System.out.println(rs.getString("password"));*/ } }catch(Exception e){ e.printStackTrace(); }finally{ //先开后关 //6:释放资源 try { if(rs != null) rs.close(); if(st != null) st.close(); if(conn != null) conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } } 12.脏读、幻影读和不可重复读
13.jdbc中的事务 ①mysql:默认情况下,建表不支持事务,除非在建表时加上type='INNODB'; 例如:create table student( id int primary key, name varchar(30), password varchar(20) )type='INNODB'; ②oracle: 如果操作过程中没有出现异常,不管你是否设置为手动提交(默认是自动提交),有没有手动提交,oracle都会自动为你提交。 14.callablestatement:存储过程介绍 定义:将常用的或很复杂的工作,预先用SQL语句写好并用一个指定的名称存储起来, 那么以后要叫数据库提供与已定义好的存储过程的功能相同的服务时,只需调用execute,即可自动完成命令。 那么存储过程与一般的SQL语句有什么区别呢? 存储过程的优点: 1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。 2.当对数据库进行复杂操作时(如对多个表进行Update,Insert,Query,Delete时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。 3.存储过程可以重复使用,可减少数据库开发人员的工作量 4.安全性高,可设定只有某此用户才具有对指定存储过程的使用权 存储过程的种类: 1.系统存储过程:以sp_开头,用来进行系统的各项设定.取得信息.相关管理工作,如 sp_help就是取得指定对象的相关信息 2.扩展存储过程 以XP_开头,用来调用操作系统提供的功能 exec master..xp_cmdshell 'ping 10.8.16.1' 3.用户自定义的存储过程,这是我们所指的存储过程 常用格式 Create procedure procedue_name [@parameter data_type][output] [with]{recompile|encryption} as sql_statement 解释: output:表示此参数是可传回的 with {recompile|encryption} recompile:表示每次执行此存储过程时都重新编译一次 encryption:所创建的存储过程的内容会被加密 pg:① import java.sql.CallableStatement; import java.sql.Connection; import java.sql.SQLException;
import cn.com.ambow.jdbc.util.JdbcUtil; /** * * @author user *@desc测试jdbc调用存储过程 *建立存储过程 * * create or replace procedure test_procedure(存储过程名) (param1 in number,param2 in varchar2,param3 in varchar2)as begin insert into student (id,name,password) values(param1,param2,param3); end test_procedure; 其中in表示写入,配合insert into sql语句;如果是select name from student where id=1;那么name对应的属性后跟out,而id对应的属性后跟in create or replace procedure test_procedure (param1 out varchar2,param2 in number)as begin select name into param1 from student where id=param2;//将name传给参数param1 end test_procedure; */ public class TestCall {
public static void main(String[] args) {
Connection conn = null;
CallableStatement cst = null;
try{
conn = JdbcUtil.getConnection();
conn.setAutoCommit(false); //注意下面的sql语句的写法 String sql = "{call test_procedure(?,?,?)}";
cst = conn.prepareCall(sql);
cst.setInt(1, JdbcUtil.getPrimaryKey("test_seq"));
cst.setString(2, "xiaobin");
cst.setString(3, "8888");
int i = cst.executeUpdate();
System.out.println(i+"条记录被影响");
conn.commit(); }catch(Exception e){
e.printStackTrace();
try { conn.rollback(); } catch (SQLException e1) {
e1.printStackTrace(); } }finally{
JdbcUtil.close(null, cst, conn);
} }
} Pg:② package cn.com.ambow.jdbc.day3;
import java.sql.CallableStatement; import java.sql.Connection; import java.sql.SQLException;
import com.sun.org.apache.bcel.internal.generic.Type; import com.sun.xml.internal.ws.wsdl.writer.document.Types;
import cn.com.ambow.jdbc.util.JdbcUtil;
/** * * @author user *@desc测试jdbc调用存储过程 *建立存储过程 * * create or replace procedure test_procedure (param1 out varchar2,param2 in number)as begin select name into param1 from student where id=param2; end test_procedure;
*/ public class TestCall {
public static void main(String[] args) {
Connection conn = null;
CallableStatement cst = null;
try{
conn = JdbcUtil.getConnection();
conn.setAutoCommit(false);
String sql = "{call test_procedure(?,?)}";
cst = conn.prepareCall(sql);
//cst.setInt(1, JdbcUtil.getPrimaryKey("test_seq")); String xia=null;
//cst.setString(1, xia); cst.registerOutParameter(1, java.sql.Types.VARCHAR); cst.setString(2, "23");
//int i = cst.executeUpdate(); cst.executeQuery(); xia=cst.getString(1); System.out.println(xia);
// System.out.println(i+"条记录被影响");
conn.commit(); }catch(Exception e){
e.printStackTrace();
try { conn.rollback(); } catch (SQLException e1) {
e1.printStackTrace(); } }finally{
JdbcUtil.close(null, cst, conn);
} }
} 15.批处理 import java.sql.*;
import cn.com.ambow.jdbc.util.JdbcUtil;
/** * * @author user 测试JDBC的批处理 */ public class TestAddBatch {
/** * @param args */ public static void main(String[] args) {
Connection conn = null;
PreparedStatement pst = null;
try {
conn = JdbcUtil.getConnection();
conn.setAutoCommit(false);
String sql = "insert into student (id,name,password)values(?,?,?)";
pst = conn.prepareStatement(sql);
for (int i = 1; i < 10; i++) {
pst.setInt(1, i);
pst.setString(2, "xiaobin" + i);
pst.setString(3, "xiaobin" + i); // 准备参数放入批处理 pst.addBatch(); } // 执行批处理 pst.executeBatch();
conn.commit(); } catch (Exception e) {
e.printStackTrace();
try { conn.rollback(); } catch (SQLException e1) {
e1.printStackTrace(); } } finally { JdbcUtil.close(null, pst, conn); } } } 16.滚动结果集 要求:1:结果集可以滚动 2:结果集要可更新 默认结果集是不可滚动的,并且只读,游标初始位置在第一行前面 import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException;
import cn.com.ambow.jdbc.util.JdbcUtil;
public class TestScroll {
/** * @param args */ public static void main(String[] args) {
Connection conn = null;
PreparedStatement pst = null;
ResultSet rs = null;
try{
conn = JdbcUtil.getConnection();
conn.setAutoCommit(false); /** * 注意* 的使用 */ String sql ="select id,name,password from student";
//为了结果集可以滚动更新
pst = conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
rs = pst.executeQuery();
//测试delete /* rs.absolute(6);
rs.deleteRow(); //更新 rs.absolute(5);
rs.updateString(2, "scroll");
rs.updateString(3, "scroll");
rs.updateRow();*/ //isnert rs.moveToInsertRow(); // 游标移到插入行 rs.updateInt(1, 88); // updates the // first column of the insert row to be AINSWORTH rs.updateString(2,"icexu"); // updates the second column to be 35 rs.updateString(3, "7474"); // updates the third column to true rs.insertRow();//插入 rs.moveToCurrentRow();//游标复位 conn.commit(); }catch(Exception e){
e.printStackTrace();
try { conn.rollback(); } catch (SQLException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } }finally{
JdbcUtil.close(rs, pst, conn); }
}
}
|
|