JDBC课程笔记
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);
}
}
上一篇: Runtime之方法调用和方法转发
下一篇: Jmeter 获取当前目录并创建文件夹