JDBC的一些简单介绍
JDBC是什么?
JDBC(Java Data Base Connection)可以为多种关系数据库提供统一访问,它由一组用Java编写的类和接口组成。JDBC提供了一种基准,据此可以构建更高级的工具和接口,使数据库开发人员能够编写数据库应用程序,同时,JDBC也是个商标名。
关于JDBC的设计
从一开始Sun公司就Java在数据库应用方面的巨大潜力。数据库开发商们认为,Sun公司要是提供一套纯Java API再提供一个数据驱动管理器就非常有用了,数据库供应商提供驱动程序,并插入到驱动管理器中,另外需要一套简单的机制,使驱动程序能在驱动管理中注册,关键的问题是所有的驱动程序必须满足驱动管理器的API提出的要求。最后Sun公司制定了两套接口,一套是JDBC API给开发人员使用,一套是JDBC驱动API给数据库供应商使用。
如下图,JDBC到数据库的通信路径
数据库url
一般格式jdbc:subprotocol:other stuff
subprotocol用于指明连接数据库的特定驱动程序
other stuff参数格式随subprotocol的不同而不同
如Oracle数据库的url jdbc:oracle:thin:@localhost:1521:orcl
熟悉以下API
首先,src下新建一个配置文件database.properties
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.user=scott
jdbc.password=tiger
jdbc.url=jdbc:oracle:thin:@localhost:1522:orcl
再来读取配置信息,连接数据库,根据上面的介绍,我们需要注册驱动,然后获取连接之后就能操作数据库了。
package com.company.jdbc;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Properties;
public class JDBCTest1 {
public static void main(String[] args) {
//注册驱动程序
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
//获取连接
Connection con=getConnection();
//操作数据库
try {
PreparedStatement ps = con.prepareStatement("select * from dept");
ResultSet rs=ps.executeQuery();
ResultSetMetaData md=rs.getMetaData();
while(rs.next()){
System.out.println(rs.getString(2));
System.out.println(rs.getInt("deptno"));
}
//获取元数据,查看ResultSet对象中列的类型和属性信息的对象
int n=md.getColumnCount();
for (int i = 1; i <= n; i++) {
System.out.println(md.getColumnName(i));
}
} catch (SQLException e) {
e.printStackTrace();
}
}
//获取连接
public static Connection getConnection(){
Properties pro=new Properties();
Connection con=null;
try {
pro.load(new FileInputStream(new File("src/database.properties")));
String driver=pro.getProperty("jdbc.driver");
String user=pro.getProperty("jdbc.user");
String password=pro.getProperty("jdbc.password");
String url=pro.getProperty("jdbc.url");
try {
con=DriverManager.getConnection(url,user,password);
} catch (SQLException e) {
e.printStackTrace();
}
} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
return con;
}
}
封装BaseDao
思路是这样的:
一个配置文件工具类PropertiesUtil,负责从配置文件中读取配置信息,获取连接,以及释放资源
一个类DataBaseUtil,封装Connection、Statement和PreparedStatement对象,也就可以执行静态sql和动态绑定sql执行了即Statement和PreparedStatement都能使用
最后就是BaseDao,定义了增删改查的方法
DataBaseUtil调用PropertiesUtil的方法获取连接、释放资源,BaseDao通过DataBaseUtil对象可以进行对数据库的crud操作
首先,src下新建一个配置文件database.properties
jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.user=scott
jdbc.password=tiger
jdbc.url=jdbc:oracle:thin:@localhost:1522:orcl
配置文件工具类PropertiesUtil
package com.company.jdbc.util;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/**
*数据库工具类,负责:
*1.读取配置文件中的数据库连接信息
*2.获取连接
*3.关闭资源
*/
public class DBUtil {
private static Properties properties=null;
//加载配置文件,使用类的相对路径
static{
properties=new Properties();
InputStream is=null;
try {
is=Thread.currentThread().getContextClassLoader().getResourceAsStream("database.properties");
properties.load(is);
} catch (IOException e1) {
e1.printStackTrace();
}
}
/**
* 获取连接
*/
public static Connection getConnection(){
if(null==properties){
System.out.println("配置文件无效,创建连接失败");
return null;
}
String driver=properties.getProperty("jdbc.driver");
String user=properties.getProperty("jdbc.user");
String password=properties.getProperty("jdbc.password");
String url=properties.getProperty("jdbc.url");
//加载驱动
Connection con=null;
try {
Class.forName(driver);
con=DriverManager.getConnection(url, user, password);
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return con;
}
/**
* 释放所有资源
* @param rs 结果集
* @param stmt 预编译语句块
* @param con 连接
*/
public static void closeAll(ResultSet rs,Statement stmt,Connection con){
try {
if(rs!=null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(stmt!=null){
stmt.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if(con!=null){
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
DataBaseUtil
package com.company.jdbc.util;
import java.sql.Connection;
import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
* 封装connection和Statement和PreparedStatement对象:
* 处理静态的sql语句---->Statement 执行时传入sql
* 处理动态的sql语句---->PreparedStatement 创建对象时传入sql,预编译
*/
public class DataBaseUtil {
private Connection connection;
private Statement statement;
private PreparedStatement preStatement;
public DataBaseUtil(){
try {
connection=PropertiesUtil.getConnection();
statement=connection.createStatement();
} catch (SQLException e) {
e.printStackTrace();
}
}
public DataBaseUtil(String sql){
try {
connection=PropertiesUtil.getConnection();
preStatement=connection.prepareStatement(sql);
} catch (SQLException e) {
e.printStackTrace();
}
}
//填充值
//将指定参数设置为给定 Java double 值。
public void setDouble(int parameterIndex, double x) throws SQLException{
preStatement.setDouble(parameterIndex, x);
}
//将指定参数设置为给定 Java float 值。
public void setFloat(int parameterIndex, float x) throws SQLException{
preStatement.setFloat(parameterIndex, x);
}
//将指定参数设置为给定 Java int 值。
public void setInt(int parameterIndex, int x) throws SQLException{
preStatement.setInt(parameterIndex, x);
}
//将指定参数设置为给定 Java long 值。
public void setLong(int parameterIndex, long x) throws SQLException{
preStatement.setLong(parameterIndex, x);
}
//将指定参数设置为给定 Java String 值。
public void setString(int parameterIndex, String x) throws SQLException{
preStatement.setString(parameterIndex, x);
}
//使用给定对象设置指定参数的值。
public void setObject(int parameterIndex, Object x) throws SQLException{
preStatement.setObject(parameterIndex, x);
}
//使用运行应用程序的虚拟机的默认时区将指定参数设置为给定 java.sql.Date 值。
public void setDate(int parameterIndex, Date x) throws SQLException{
preStatement.setDate(parameterIndex, x);
}
//Statement查询
public ResultSet executeQuery(String sql) throws SQLException{
return statement.executeQuery(sql);
}
//PreparedStatement查询
public ResultSet executeQuery() throws SQLException{
return preStatement.executeQuery();
}
//Statement update insert delete
public int executeUpdate(String sql) throws SQLException{
return preStatement.executeUpdate(sql);
}
//PreparedStatement update insert delete
public int executeUpdate() throws SQLException{
return preStatement.executeUpdate();
}
//Statement DDL
public boolean execute(String sql) {
boolean flag =true;
try {
preStatement.execute(sql);
} catch (SQLException e) {
e.printStackTrace();
flag =false;
}
return flag;
}
//PreparedStatement DDL
public boolean execute() {
boolean flag =true;
try {
preStatement.execute();
} catch (SQLException e) {
e.printStackTrace();
flag =false;
}
return flag;
}
/**
* 关闭连接
*/
public void close(){
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 释放所有资源
*/
public void closeAll(ResultSet rs){
PropertiesUtil.closeAll(rs, statement!=null?statement:preStatement, connection);
}
}
封装的Dao层
package com.company.jdbc.util;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 基础的CRUD 约定大于配置
*/
public class BaseDao {
private DataBaseUtil oracle =null;
/**
* 查询
* @throws SQLException
* @throws ClassNotFoundException
*/
public ResultSet retreive(String sql,Object ...values) throws SQLException, ClassNotFoundException{
if(null==values ||values.length<1){ //静态sql
oracle =new DataBaseUtil();
return oracle.executeQuery(sql);
}else{ //动态绑定值
oracle =new DataBaseUtil(sql);
for(int i=0;i<values.length;i++){
oracle.setObject(i+1, values[i]);
}
return oracle.executeQuery();
}
}
/**
* 获取单行单列的值
* 如查询主键或 获取记录数调用该方法
* @throws SQLException
*/
public Object retreiveSingle(String sql,Object...values) throws SQLException{
ResultSet rs=null;
Object object=null;
try {
rs = retreive(sql,values);
if(null!=rs&&rs.next()){
object=rs.getObject(1);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
oracle.closeAll(rs);
return object;
}
/**
* 增删改
* @param sql
* @param values
* @return
* @throws SQLException
*/
public int cud(String sql,Object...values) throws SQLException{
int flag;
if(null==values||values.length<1){// 静态sql
oracle=new DataBaseUtil();
flag = oracle.executeUpdate(sql);
}else{// 动态绑定值
oracle=new DataBaseUtil(sql);
for(int i=0;i<values.length;i++){
oracle.setObject(i+1, values[i]);
}
flag=oracle.executeUpdate();
}
oracle.close();
return flag;
}
}
测试代码,愉快地增删改查起来吧:
package com.company.jdbc;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.company.jdbc.util.BaseDao;
public class JDBCTest2 {
public static void main(String[] args) {
BaseDao baseDao=new BaseDao();
try {
ResultSet rs=baseDao.retreive("select * from dept where deptno=?", 10);
while(rs.next()){
System.out.println("第一列部门号: "+rs.getInt(1));
}
Object obj=baseDao.retreiveSingle("select count(*) from dept where deptno>?",10);
System.out.println("部门号大于10的部门个数"+obj.toString());
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}