Oracle +JDBC

JDBC

JDBC简介

JDBC(Java Data Base Connectivity,java数据库连接)是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序。

我们安装好数据库之后,我们的应用程序也是不能直接使用数据库的,必须要通过相应的数据库驱动程序,通过驱动程序去和数据库打交道。其实也就是数据库厂商的JDBC接口实现,即对Connection等接口的实现类的jar文件。

img

JDBC + Oracle + Eclipse
简介

我们安装的 XE 版本里面就有自带的 Oracle 的官方 JDBC jar 包,位置是:app\oracle\product\11.2.0\server\jdbc\lib

有三个

  • ojdbc5:与jdk1.5 对应的
  • ojdbc6:与jdk1.6 对应的
  • ojdbc6_g:jdk1.6 的编译版本

我们随便选择一个就可以了,文档jdk是11 ,Oracle 是之前有上传过资源 11g XE 版本的

外部JAR包加载到我们项目
  • 在我们的Java 项目下面建立一个文件夹 放入这些外部 jar 包 一般文件名是lib【与src同级】

  • 然后在右键项目名,选择Build Path,如图选择

  • 选择 labiries – 》 ModulePath — 》 Add JARS 选择你创建的lib下面的jar包 —》 应用 确定关闭
    在这里插入图片描述

  • 然后就能看到 lib 同级目录下有个 Referenced Libraries【应用库】 这样就把jdbc引入到你的库里面了

认识结构

这个Jar包下面全是和数据库有关的类,接口等。它和Java.sql 以及 Javax.sql 三者一起来操作数据库 ,这个JDBC 就是一个 java程序操作数据库的中间件,也叫做JDBC驱动

Java程序借助JDBC连接数据库

Java API

JDBC API主要位于JDK中的java.sql包中(之后扩展的内容位于javax.sql包中),主要包括(斜体代表接口,需驱动程序提供者来具体实现):

  • DriverManager:负责加载各种不同驱动程序(Driver),并根据不同的请求,向调用者返回相应的数据库连接(Connection)。
  • Driver:驱动程序,会将自身加载到DriverManager中去,并处理相应的请求并返回相应的数据库连接(Connection)。
  • Connection:数据库连接,负责与进行数据库间通讯,SQL执行以及事务处理都是在某个特定Connection环境中进行的。可以产生用以执行SQL的Statement。
  • Statement:用以执行SQL查询和更新(针对静态SQL语句和单次执行)。
  • PreparedStatement:用以执行包含动态参数的SQL查询和更新(在服务器端编译,允许重复执行以提高效率)。
  • CallableStatement:用以调用数据库中的存储过程
  • SQLException:代表在数据库连接的建立和关闭和SQL语句的执行过程中发生了例外情况(即错误)。
步骤
1.加载数据库驱动

在编程中要连接数据库,必须先装载特定厂商的数据库驱动程序,不同的数据库有不同的装载方法。如:

  • 装载MySql驱动:Class.forName(“com.mysql.jdbc.Driver”);

  • 装载Oracle驱动:Class.forName(“oracle.jdbc.driver.OracleDriver”);

2.创建数据库连接:Connection接口

创建数据库连接要用该接口来操作

Connection conn = DriverManager.getConnection(String url,String username,String userpasswd);

  • DriverManager类下面的方法getConnection()会返回一个 Connection 数据库连接对象,它的参数不固定,最常用d就是这三个
  • url:数据库服务的地址一般都是固定写法
    • Oracle:jdbc:oracle:thin:@ip地址:端口号(1521):XE
    • MySql:jdbc:mysql://ip地址:端口号(3306)/数据库 【好像5.7之后 8.0 需要写时区】
      • jdbc:mysql://localhost:3306/test?&useSSL=false&serverTimezone=UTC
    • SqlServer:jdbc:microsoft:sqlserver://ip地址:端口号;DatabaseName = databasename
  • username:连接的数据库用户
  • userpasswd:数据库用户密码
3.创建sql执行器:Statement 接口

Statement st = conn.createStatement();

4.执行sql
5.处理返回的结果集或者别的操作

有两个常用方法,excuteQuery() 和 excuteUpdata() ,第一个返回结果集,用的是查询sql语句,第二个用增、删、改 的更新语句, 返回整型数据, 大于0则执行成功,否则失败。

一般如果是查询的话返回的都是结果集 ResultSet,后面有详细介绍。有个 next() 方法,返回值是 布尔类型 ,用它去取数据。

6.释放数据库连接资源

释放数据库连接的时候按照先入栈后出栈的顺序去写,然后每个关闭的时候都会有异常,而且还要去做非空判断,不然容易报空指针异常错误。

举例
package com.bigdata.jdbcdemo.oracle;
import java.sql.*;
public class demoSelect {
	public static void main(String[] args) {
		/**
		 *	加载驱动
		 *	创建连接
		 *	建立Statement sql执行对象
		 *	执行sql
		 *	处理返回结果
		 *	释放数据库资源
		 */
		// 先声明  最后关闭的时候好关闭
		Connection conn = null;
		Statement ste = null;
		ResultSet rs = null;
		try {
			// 类找不到异常
			Class.forName("oracle.jdbc.OracleDriver");
			// sql异常
			conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:XE", "SCOTT", "lzyft1030");
			ste = conn.createStatement();
			String sql = "SELECT ENAME,JOB,SAL FROM EMP";
			rs = ste.executeQuery(sql);
			System.out.println("姓名\t工作\t工资");
			while (rs.next()) {
				System.out.println(rs.getString("ENAME")+"\t"+rs.getString("JOB")+"\t"+rs.getInt(3));
			}
		} catch (ClassNotFoundException | SQLException e) {
			
			e.printStackTrace();
		} finally {
			// 做不为null判断 防止NPE【NullPointerException】
				try {
					if (ste != null) {
						ste.close();
					}
					if (conn != null) {
						conn.close();
					}
				} catch (SQLException e) {
					e.printStackTrace();
				}
		}
	}
}
常用接口
Connection接口
Class.forName("oracle.jdbc.OracleDriver");
Connection conn = DriverManager.getConnection(...);
Statement接口

用于执行静态SQL语句并返回它所生成结果的对象。

三种Statement类:

Statement:

createStatement创建,用于发送简单的SQL语句(不带参数的Sql,可以做Sql组合)。

Statement st = conn.createStatement();
String sql = "delete from tablename where id = "5" + "..." "; // 不能有占位符 ?可以组合 所以安全性不高 字符串组合的话 网上改一下字符串或者后面跟别的东西 直接坏起来
int code = st.excuteUpdate(sql);
ResultSet rst = st.excuteQuery(sql);
PreparedStatement :

继承自Statement接口,由prepareStatement创建,用于发送含有一个或多个参数【占位符】的SQL语句。PreparedStatement对象比Statement对象的效率更高,并且可以防止SQL注入,所以我们一般都使用PreparedStatement

【注意接口和创建方法之间的不同:PreparedStatement pst = conn.prepareStatement(sql);

CallableStatement:

继承自PreparedStatement接口,由方法prepareCall创建,用于调用存储过程。

常用Statement方法:
  • execute(String sql):运行语句,返回是否有结果集
  • executeQuery(String sql):运行select语句,返回ResultSet结果集。
  • executeUpdate(String sql):运行insert/update/delete操作,返回更新的行数。
  • addBatch(String sql) :把多条sql语句放到一个批处理中。
  • executeBatch():向数据库发送一批sql语句执行。
ResultSet接口
ResultSet提供检索不同类型字段的方法,常用的有:
  • getString(int index)、getString(String columnName):获得在数据库里是varchar、char等类型的数据对象。
  • getFloat(int index)、getFloat(String columnName):获得在数据库里是Float类型的数据对象。
  • getDate(int index)、getDate(String columnName):获得在数据库里是Date类型的数据。
  • getBoolean(int index)、getBoolean(String columnName):获得在数据库里是布尔类型的数据
  • getObject(int index)、getObject(String columnName):获取在数据库里任意类型的数据。
ResultSet还提供了对结果集进行滚动的方法:
  • next():移动到下一行,返回布尔值
  • previous():移动到前一行
  • absolute(int row):移动到指定行
  • beforeFirst():移动resultSet的最前面。
  • afterLast() :移动到resultSet的最后面。
ResultSetMetaData

用于返回结果集的元数据,ResultSet 的子类,一般方法原型都是ResultSet 的 ,使用的时候可以查看API 去使用

举例
连接和关闭数据库的工具类
package com.bigdata.jdbcdemo.oracle;

import java.sql.*;

public class DBConnection {
	private static Connection conn = null;
	
	/**
	 * 创建Oracle 数据库连接
	 */
	public static Connection getConnectOracle(){
		try {
			Class.forName("oracle.jdbc.OracleDriver");
			conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:XE","SCOTT","123");
		} catch (ClassNotFoundException | SQLException e) {
			e.printStackTrace();
		}
		return conn;
	}
	
	/**
	 * 释放资源
	 */
	public static void closeAll(ResultSet rst, PreparedStatement pst, Connection conn) {
		try {
            if (rst != null) {
                rst.close();
            }
            if (pst != null) {
                pst.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
	}
}
具体练习
package com.bigdata.jdbcdemo.oracle;

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

public class PreparedStatementTest {

	public static void main(String[] args) {
		PreparedStatement pst = null;
		ResultSet  rst = null;
		ResultSetMetaData rstmd = null;
		Connection conn = DBConnection.getConnectOracle();
		String sql = "select ename,job,sal from emp where deptno = ?";
		try {
			pst = conn.prepareStatement(sql);
			pst.setInt(1, 10);
			rst = pst.executeQuery();
			while (rst.next()) {
				System.out.println(rst.getString(1)+"\t"+rst.getString("JOB")+"\t"+rst.getInt(3));
			}
			rstmd = rst.getMetaData();
			System.out.println("列数:"+rstmd.getColumnCount());
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			DBConnection.closeAll(rst, pst, conn);
		}
	}
}

Sql 到 Java 数据类型映射

SQL类型Java类型
CHARjava.lang.String
VARCHARjava.lang.String
LONGVARCHARjava.lang.String
NUMERICjava.math.BigDecimal
DECIMALjava.math.BigDecimal
BITboolean
TINYINTbyte
SMALLINTshort
INTEGERint
BIGINTlong
REALfloat
FLOATdouble
DOUBLEdouble
BINARYbyte[]
VARBINARYbyte[]
LONGVARBINARYbyte[]
DATEjava.sql.Date
TIMEjava.sql.Time
TIMESTAMPjava.sql.Timestamp
BLOBjava.sql.Blob
CLOBjava.sql.Clob
Arrayjava.sql.Array
REFjava.sql.Ref
Structjava.sql.Struct

注:这种类型匹配不是强制性标准,特定的JDBC厂商可能会改变这种类型匹配。例如Oracle中的DATE类型是包含时分秒,而java.sql.Date仅仅支持年月日。

Date转换
  • java.sql.Date
    • Date d = new Date(1900 + year, 1+month, day);
    • int类型的参数
    • PreParedStatement() 中的 sql 的 Date 类型 不可直接 to_date() 需要用这个 Date 对象去传入
  • Oracle 的类型 Date
    • to_date(日期字符串,'格式');:按格式 字符串转日期
    • to_char(date,'格式');:日期转字符串按格式
    • add_month(date,正负数字); :加间日期月份
    • last_day(date); :日期的最后一条
    • date + interval ‘正负数字’ year/month(数字位数,默认2位):给日期按后面的year 或 month 加减数字【±】

用配置文件连接数据库

创建一个文件

创建文件,最好放在同连接数据库的类同级目录下,一般文件命名:date.properties ,格式要写成固定的

classDriver = oracle.jdbc.OracleDriver
url = jdbc:oracle:thin:@127.0.0.1:1521:XE
username = scott
userpasswd = 123
创建类

java.util下面有个键值对集合,Hashtable的子类 Preperties

InputStream 对象读取文件数据

InputStream is = 当前类名.class.getResourceAsStream("data.properties");
Prepareties p = new Prepareties();
p.load(is);
p.getProperty(key);// 取得键值
示例代码
package com.bigdata.jdbcdemo.oracle;

import java.io.IOException;
import java.io.InputStream;
import java.sql.*;
import java.util.Properties;

public class DBConnectByFile {
    // 输入流读取配置文件  用当前类取得资源流 参数是配置文件的相对路径
    private static InputStream is = DBConnectByFile.class.getResourceAsStream("oracleConn.properties");
    private static Properties properties = new Properties();

    /**
     * @return 返回驱动
     */
    public static String getDriverClass() {
        try {
            properties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return properties.getProperty("classDriver");
    }

    /**
     * @return 返回url
     */
    public static String getUrl() {
        try {
            properties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return properties.getProperty("url");
    }

    /**
     * @return username
     */
    public static String getUserName() {
        try {
            properties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return properties.getProperty("username");
    }

    /**
     * @return password
     */
    public static String getPassword() {
        try {
            properties.load(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return properties.getProperty("password");
    }

    public static Connection getConnection () {
        Connection conn = null;
        try {
            Class.forName(getDriverClass());
            conn = DriverManager.getConnection(getUrl(), getUserName(), getPassword());
        } catch (ClassNotFoundException | SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

    public static void closeAll(ResultSet rst, PreparedStatement pst, Connection conn) {

            try {
                if (rst != null) {
                    rst.close();
                }
                if (pst != null) {
                    pst.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }

    }
//    public static void main(String[] args) {
//        Connection conn = getConnection();
//        System.out.println(conn != null);
//    }
}
 rst.close();
            }
            if (pst != null) {
                pst.close();
            }
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }

}

// public static void main(String[] args) {
// Connection conn = getConnection();
// System.out.println(conn != null);
// }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值