欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JDBC课程笔记

程序员文章站 2022-07-13 21:38:10
...

JDBC_day01_am

1.










2.解耦合
                   3.驱动分类
  a.JDBC-ODBC桥驱动
    application-->jdbc-->桥-->odbc-->数据库
    1.效率低;
    2.安全性低;
  b.部分Java、部分本地代码驱动;
    application-->jdbc-->java|native(调用操作系统功能的代码)---->数据库
   
 

    速度相对较快,但安全性不好;

   c.纯Java网络服务器驱动(pure java,net Server Driver)
  app-->JDBC--pure Java--中间协议-->netServer--本地协议-->数据库
  效率底;
   d.纯Java本地协议驱动(pure java,native protocol)
   app-->jdbc-->pure Java—本地协议-->数据库
 
   虽然工作量大,但是效率高,更安全;
4.JDBC协议
  java.sql.*;(主要\核心特性包)
  javax.sql.*;(宽展功能包)
5.java.sql.*中的接口和类
Driver   代表驱动程序
DriverManager  辅助工具类-管理驱动程序
Connection    代表DB连接(某种意义上代表DB)
Statement
PreparedStatement     代表DB操作对象(SQL)
CallableStatement
 
ResultSet  代表查询结果
DatabaseMetadata
ResultSetMetadata   元数据对象
Types   定义用于标识一般 SQL 类型(称为 JDBC 类型)的常量的类。


 
 

JDBC_day01_pm
1.JDBC操作步骤
  a.注册/加载驱动 首先导包:classpath环境变量中配置或eclipse中构建工程path
  b.建立连接;写URL(包括:网络协议;主机地址(ip:port);资源名称)
  c.创建执行对象
  d.执行SQL语句
  e.处理结果集
  f.关闭资源

数据库中URL的格式:
    jdbc:mysql://127.0.0.1:3306/test
    
   

     其他的数据库与上面的格式类似
    而oracle的url比较特殊:
          jdbc:oracle:thin:@172.18.9.6:1521:tarena


2.OracleDriver内部实现机制,使用静态块加载Driver给DriverManager

package tang.jdbc;

import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
public class OracleDriver {

    static {
    Driver driver=new oracle.jdbc.driver.OracleDriver();
       try {
DriverManager.registerDriver(driver);
} catch (SQLException e) {
e.printStackTrace();
}
   
    }
}

3.数据库连接实例
package tang.jdbc;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class Lab1 {

/**
* @param args
*/
public static void main(String[] args) {

String driver="oracle.jdbc.driver.OracleDriver";
String url="jdbc:oracle:thin:@172.18.9.6:1521:tarena";
String user="scott";
String password="tiger";
try {
Class.forName(driver);
Connection conn=DriverManager.getConnection(url,user,password);
Statement stmt=conn.createStatement();
ResultSet rs=stmt.executeQuery("select * from userinfo");
while(rs.next()){
System.out.println(rs.getString(1)+"\t"+rs.getString(2));

}
System.out.println("successfully!");
if(null!=rs){
rs.close();
}
if(null!=stmt){
stmt.close();
}
if(null!=conn){
conn.close();
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}catch(SQLException e){
e.printStackTrace();
}
}
}
结果:
tang 123456
zhi 123456
qiang 123456
tangzhiqiang tangzhiqiang
yangyi 123456
successfully!
一个可以执行创建数据库的实例(注意执行时的输入信息)
package tang.jdbc;
import java.sql.*;
public class CreateTable {
public static void main(String[] args) {
String url = "jdbc:oracle:thin:@172.18.9.6:1521:tarena";
String user = "scott";
String pwd = "tiger";
Driver driver = new oracle.jdbc.driver.OracleDriver();
Connection conn = null;
Statement stmt = null;
  String sql=null;
if (null == args[0]) {
System.out
.println("执行格式为:java CreateTable 表名   执行命令(如,create\\drop)");
  return;
}
if (null == args[1]) {
System.out
.println("执行格式为:java CreateTable 表名   执行命令(如,create\\drop)");
return;
}
String tablename =args[0];
String command=args[1];
if("create".equals(command)){
sql = "create table " + tablename + "("
+ " ID number(12) primary key,"
+ "    PWD varchar(10) not null)";
}else if("drop".equals(command)){
sql="drop table "+tablename;
}
try {
DriverManager.registerDriver(driver);
conn = DriverManager.getConnection(url, user, pwd);
stmt = conn.createStatement();

int result = stmt.executeUpdate(sql);
System.out.println(result);
} catch (SQLException e) {
e.printStackTrace();

}
}
}











JDBC_day02_am

1.结果集遍历
  a.游标指向的记录叫当前记录,只有当前记录值可读;
  数据库中的行和列的索引都是从“1”开始
  b.游标可移动(rs.next())
  c.默认的 ResultSet 对象不可更新,仅有一个向前移动的光标,游标的最终位置是最后一条记录后面(单向)afterlast,若要使游标可来回移动可使用下面方法(以下代码片段(其中 con 为有效的 Connection 对象)演示了如何生成可滚动且不受其他更新影响的可更新结果集):
 
Statement stmt = con.createStatement(
                                      ResultSet.TYPE_SCROLL_INSENSITIVE,
                                      ResultSet.CONCUR_UPDATABLE);
       ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");

   d.游标的最初位置beforefirst
  
2.将具有相同或重复性的代码进行封装
 
package tang.jdbc;
import java.sql.*;
public class JdbcUtil {
// 静态加载驱动,只需要加载一次就可以
static {
      /* 直接使用此段代码也可加载驱动,oracle.jdbc.driver.OracleDriver类中的static自动加载
Driver driver = new oracle.jdbc.driver.OracleDriver();*/
try {
// load Driver
String driver = "oracle.jdbc.driver.OracleDriver";
Class.forName(driver);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
/*
* 直接在命令行中使用java -D jdbc.drivers=oracle.jdbc.driver.OracleDriver
* 直接加载环境变量中的驱动
*/
}
public static Connection getConnection() {
Connection conn = null;
try {
String url = "jdbc:oracle:thin:@172.18.9.6:1521:tarena";
String user = "scott";
String password = "tiger";
conn = DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
}
return conn;
}
  //注意"有连接"的关闭顺序
public static void close(ResultSet rs, Statement stmt, Connection con) {
if (null != rs) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != stmt) {
try {
stmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (null != con) {
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
   public static int toInt(String str){
   return Integer.parseInt(str);
   }
}

3.DriverManager的工作原理(若内存中有多个驱动,它如何进行选择)





























JDBC_day02_pm
1.PreparedStatement(预编译后的SQL执行类型)
批量处理SQL
   



         sql=”insert into sd091202 values(?,?)”;
         sp=con.prepareStatement(sql);
         sp.setInt(1,10);
         sp.setString(2,”xiaohegn”);
         sp.executeUpdate();
        
老师建议:面试笔试时使用PreparedStatement,显得有经验
PreparedStatement的小实例:
package tang.jdbc;
import java.sql.*;
public class PreparedStatementTest {
public static void main(String[] args) {
Connection conn=null;
PreparedStatement ps=null;
conn=JdbcUtil.getConnection();//此处的JdbcUtil是上面的封装类
   try {
    conn.setAutoCommit(false);
ps=conn.prepareStatement("insert into sd091202 values(?,?)");
ps.setInt(1, 2);
ps.setString(2, "bbbb");
conn.commit();
int result= ps.executeUpdate();
System.out.println(result);
} catch (SQLException e) {
e.printStackTrace();
try {
conn.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
JdbcUtil.close(null, ps, conn);
}
}


JDBC_day03_am

1.DatabaseMetaData通过Connection获取对象,从而获取数据库的相关信息;
ResultSetMetaData通过ResultSet获取对象,从而获取表的有关信息(如列名,列数目等)
2.事务处理(Transaction)
  原子操作:一组相关操作,要么全成功,要么全失败!

JDBC_day03_pm

1.事务处理
   a.在执行操作之前调用Connection的setAutoCommit(false)方法;
   b.在事务处理成功且完成后再手动提交事务,此时调用Connection的commit()方法;
   c.若事务处理失败(如出现异常)则调用Connection的rollback()方法,执行会滚操作,撤销上一次commit()的状态;数据库将保存在其他地方的原数据进行恢复(rollback 操作是将 rollback segment/undo segment 的数据返回)

2.对所读数据正确度的影响因素
   a.事务中的dirty read(脏读。何为脏数据:未保存或未提交的数据):一个事务处理到了未保存或未提交的数据;
   b.事务中unrepactable read(不可重复读):第一更新丢失
   c.事务中的phantom read(幻读):读到的数据量不一致;
如何处理上诉的影响因素:
  设置事务隔离: getTrasactionIsolation
                  Connection.setTransactionIsolation(Connection的静态变量)
               
3.增强的结果集
  设置结果集游标是否可滚动和可更新等,默认的游标只能单向移动且不可更新;
  单向只读(默认);双向只读;双向可更新(在生成结果集之前声明,即在创建Statement时设置)如,
Statement stmt = con.createStatement(
                                      ResultSet.TYPE_SCROLL_INSENSITIVE,
                                      ResultSet.CONCUR_UPDATABLE);
       ResultSet rs = stmt.executeQuery("SELECT a, b FROM TABLE2");


4.JNDI使用的类javax.naming.*;
  获取数据源:Context ctx=new InitialContext();
               ctx.lookup(name);














JDBC_day04_am
1.使用PreparedStatement进行批处理过程,如出路1万条,用循环控制:
for(int i=1;i<=10000;i++){
ps.set(1,x);
ps.set(2,y);
.....................
ps.set(n,z);
ps.addBatch();
  if(i%100==0){
    ps.executeBatch();
  }
}

下面为一个具体的实例:
package tang.jdbc;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class PreparedStatementTest {

/**
* @param args
*/
public static void main(String[] args) {

Connection conn=null;
PreparedStatement ps=null;
conn=JdbcUtil.getConnection();
try {
ps=conn.prepareStatement("insert into aaa values (?,?)");
long start=System.currentTimeMillis();
        //位置1
for(int i=1;i<=10000;i++){
ps.setInt(1, i);
ps.setString(2, "tang");
ps.executeUpdate();
//System.out.println(i);
}
     //位置2
// for(int i=1;i<=10000;i++){
// System.out.println(i);
// ps.setInt(1, i);
// ps.setString(2, "zhi");
// ps.addBatch();
// if(i%100==0){
// ps.executeBatch();
// }
// }

long end=System.currentTimeMillis();
System.out.println("执行的时间为: "+(end-start)+" 毫秒");
} catch (SQLException e) {
e.printStackTrace();
}

}

}
结果:
位置1:执行的时间为: 85555 毫秒
位置2:执行的时间为: 2210 毫秒
2.连接池(提高连接的效率):池--》可重复使用的资源(资源的特点:有用且稀缺)
特点:用完收回(重复);实现建好;
3.Blob-->Binary Large Object(常用的类型,二进制文件的使用稍多,如:mp3,jpg,zip,exe等)
Clob-->Character Large Object(纯文本[字符串],如text,而pdf等不可存)
主要讲解java.sql.Blob接口:

使用PreparedStatement的setBinaryStream可以将二进制存入数据库;
从数据库中取:使用ResultSet可以获得Blob类性的对象;

Blob数据存入数据库:
package tang.jdbc;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Blob_Save_to_DB_Test {

/**
* 将文件保存进数据库
*/
public static void main(String[] args) {

Connection conn=null;
  PreparedStatement ps=null;
 
  conn=JdbcUtil.getConnection();
  try {
ps=conn.prepareStatement("insert into table_blob values(?,?)");
File file=new File("/home/soft01/oracle.jar");
InputStream is;
  is = new FileInputStream(file);
ps.setInt(1, 2);
  ps.setBinaryStream(2, is,is.available());

ps.executeUpdate();
System.out.println("success!");
} catch (SQLException e) {
e.printStackTrace();
}catch (FileNotFoundException e) {
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
  JdbcUtil.close(null, ps, conn);
}

}
将blob类型取出数据库并保存
package tang.jdbc;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Blob_Get_from_DB_Test {

/**
* 将文件取出数据库
*/
public static void main(String[] args) {

Connection conn=null;
  PreparedStatement ps=null;
    ResultSet rs=null;
    Blob blob=null;
    FileOutputStream fos=null;
  conn=JdbcUtil.getConnection();
    try {
ps=conn.prepareStatement("select file_content from table_blob where id=?");
ps.setInt(1, 1);
rs=ps.executeQuery();
if(rs.next()){
blob=rs.getBlob(1);
}
InputStream is=blob.getBinaryStream();
try {
fos=new FileOutputStream("/home/soft01/jdbcproject/day03/src/tang/jdbc/desk.gif");
byte b[]=new byte[1024];
try {
while(is.read(b)!=-1){
fos.write(b);
}
fos.close();
is.close();
System.out.println("success");
} catch (IOException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
}

} catch (SQLException e) {
e.printStackTrace();
}
 
 
  JdbcUtil.close(rs, ps, conn);


}