JDBC相关

1 what

SUN公司提供的一组API,由类和接口组成,用于操作不同的数据库

2 when

Java操作数据库时需要在Java和数据库之间建立连接,JDBC是桥梁

3 why

Java使用JDBC来操作数据库

4 how

4.1.加载驱动(Load the driver)
什么是驱动

各个数据库厂商针对SUN公司的接口提供的实现类,并将这些类打包成jar文件放在网上共Java程序员下载使用

为什么要导入驱动

SUN公司的jdk里面并未提供数据库的驱动包,而是由世界的各大数据库厂商提供,并且每个厂商提供的驱动包都不一样,所以要加载驱动包,必须将驱动包导入到classpath目录下

为什么要加载驱动

要使用驱动包里面的类,就必须先产生类的ClassLoader,加载驱动实际上就是加载ClassLoader,Java程序运行时首先会在内存中加载各种需要的类,首先加载rt.jar等jre核心包,然后加载静态类的ClassLoader,最后加载扩展包的jar文件,而数据库的驱动包就属于扩展包

为什么要通过反射加载驱动

加载驱动之后要产生对象,而产生对象有4种方式,不可能是反序列化,克隆,只可能是new和反射2种。假如用new的话,如果是sqlServer的数据库的话,Driver driver = new net.sourceforge.jtds.jdbc.Driver(); 但是换成其他数据库的话,各大厂商所用的包名,类名不一样,还要修改源代码,将new后面的代码修改,这不符合Java编程的复用思想,于是想到使用反射来产生对象,但是反射产生对象有3种,首先,不知道类名,所以不能用类名.class产生对象,其次,不可能是对象名. getClass(),本来即要产生对象,那么不需要用这个方法来产生class对象再来产生对象,剩下只有Class.Forname("")方法了,其中传参是字符串,可以通过修改外部文件来更换不同的数据库,从而达到复用的目的
1) Class.forName()|Class.forName().newInstance()|new DriverName()
2) 实例化时自动向DriverManager注册,不需要显示调用DriverManager.registerDriver方法

//从配置文件中读取数据库连接相关信息
String driverName = PropertiesMgr.getProperty("driver");
String url = PropertiesMgr.getProperty("url");
String username = PropertiesMgr.getProperty("username");
String password = PropertiesMgr.getProperty("password");
//声明数据库操作相关对象Connection conn = null;
//加载驱动,获得数据库连接
Class.forName(driverName);
4.2.获得连接(connetc to the database)

Connection conn = DriverManager.getConnection(url, username, password);
url    连接数据库的地址  范例:jdbc:oracle:thin@202.194.158.12:1521:ORCL"
        jdbc:oracle:thin:通讯协议
        202.194.158.12:1521: 数据库服务器的地址,1521表示Oracle的端口号
       ORCL:数据库名
       user  数据库用户名
       password  数据库密码

4.3.使用连接对象创建声明语句对象执行增/删/改/查数据(CreateStatement&execute SQL)

1)Statement stmt = conn.createStatement();
2)Statement.executeQuery()
3)Statement.executeUpdate()

//普通语句
stmt = conn.createStatement();			
String sql = "insert into dept2 values(99,'upc','dy')";
stmt.executeUpdate(sql);

查询:ResultSet rs = stmt.executeQuery(sql);

预处理

PreparedStatement    不需要拼装sql语句    预编译,效率高    防止sql注入

//预处理语句			
pstmt = conn.prepareStatement("insert into dept2 values(?,?,?)");
pstmt.setInt(1, deptno);
pstmt.setString(2, dname);
pstmt.setString(3, loc);
pstmt.executeUpdate();

附:
boolean execute() throws SQLException
在PreparedStatement 对象中执行SQL 语句,该语句可以是任何种类的SQL 语句。一些特别处理过的语句返回多个结果,execute 方法处理这些复杂的语句,executeQuery 和executeUpdate处理形式更简单的语句。
execute 方法返回一个boolean 值,以指示第一个结果的形式。必须调用getResultSet或getUpdateCount 方法来检索结果,并且必须调用getMoreResults 移动到任何后面的结果。
返回:
如果第一个结果是ResultSet 对象,则返回true;如果第一个结果是更新计数或者没有结果,则返回false
抛出:
SQLException - 如果发生数据库访问错误或者为此方法提供一个参数
------------------------------------------------------------------------------------------------------------------------------------------------------
ResultSet executeQuery() throws SQLException
在PreparedStatement 对象中执行SQL 查询,并返回该查询生成的ResultSet 对象。
返回:
包含该查询生成的数据的ResultSet 对象;从不返回null
抛出:
SQLException - 如果发生数据库访问错误或者SQL 语句没有返回一个ResultSet 对象
--------------------------------------------------------------------------------------------------------------------------------
int executeUpdate() throws SQLException
在此 PreparedStatement 对象中执行SQL 语句,该语句必须是一个SQL INSERT、UPDATE或DELETE 语句;或者是一个什么都不返回的SQL 语句,比如DDL语句。
返回:
(1) 对于INSERT、UPDATE或DELETE语句,返回行数
(2) 或者对于什么都不返回的SQL 语句,返回0
抛出:
SQLException - 如果发生数据库访问错误或者SQL 语句返回一个 ResultSet 对象

Statement    批处理
//普通批处理
stmt.addBatch("delete from dept2 where deptno=99");
stmt.addBatch("delete from dept2 where deptno=23");
stmt.addBatch("delete from dept2 where deptno=50");
stmt.executeBatch();

//预处理批处理
pstmt = conn.prepareStatement("insert into dept2 values(?,?,?)");

pstmt.setInt(1, 50);
pstmt.setString(2, "clerk");
pstmt.setString(3, "bj");
pstmt.addBatch();

pstmt.setInt(1, 60);
pstmt.setString(2, "manager");
pstmt.setString(3, "sh");
pstmt.addBatch();

pstmt.setInt(1, 70);
pstmt.setString(2, "assistant");
pstmt.setString(3, "jn");
pstmt.addBatch();

pstmt.executeBatch();
JDBC处理存储过程
//调用带参数的存储过程(3,4为out,124为in),由于存储过程参数默认为in,所以需要显示声明out参数
cstmt = conn.prepareCall("call pp(?,?,?,?)");
cstmt.registerOutParameter(3, Types.INTEGER);
cstmt.registerOutParameter(4, Types.INTEGER);
cstmt.setInt(1, 3);
cstmt.setInt(2, 4);
cstmt.setInt(4, 5);
cstmt.execute();
System.out.println(cstmt.getInt(3));
System.out.println(cstmt.getInt(4));
JDBC事务处理,

--rowback回滚
  AutoCommit默认是true一条transaction起始于一条DML语句,终止于commit或者DDL语句,DCL语句(授权语句),用户正常断开连接,非正常断开自动回滚
--commit提交transaction

//事务处理
conn.setAutoCommit(false);
stmt.addBatch("insert into dept2 values (41, '50', 'ha')");
stmt.addBatch("insert into dept2 values (42, '50', 'ha')");
stmt.addBatch("insert into dept2 values (430, '50', 'ha')");
stmt.executeBatch();
conn.commit();
conn.setAutoCommit(true);
4.4 循环取得结果(retrieve the result data)
//ResultSet类似于游标,可循环取得查询结果
rs = stmt.executeQuery("select * from dept2");
while(rs.next()) {
	System.out.print(rs.getInt(1) + "," + rs.getString("dname") + "," + rs.getString(3));
	System.out.println();
}
可以滚动的结果集
//可滚动的游标
stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
rs = stmt.executeQuery("select * from dept2 order by deptno");
rs.next();
System.out.println(rs.getInt(1));
rs.last();
System.out.println(rs.getString(1));
System.out.println(rs.isLast());
rs.next();
System.out.println(rs.isAfterLast());
rs.previous();
System.out.println(rs.getRow());
System.out.println(rs.getString(1));
rs.absolute(6);
System.out.println(rs.getString(1));
可更新的结果集

(Oracle数据库中,oracle 9i不支持可更新的结果集,并且在后续版本中用select * 会导致该ResultSet强制readonly,需要明确指明字段名称才可更新)

//可更新的结果集
stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
rs = stmt.executeQuery("select deptno,dname,loc from dept2 order by deptno");
rs.next();
//更新一行数据
rs.updateString("dname","AAAAA");
rs.cancelRowUpdates();//取消更新,用在updater metord之后,updateRow之前
rs.updateRow();
System.out.println(rs.getRow());//1
//插入新行,当前光标的位置会备份
rs.moveToInsertRow();
rs.updateInt(1, 11);
rs.updateString("dname","BBBB");
rs.updateString(3, "Bloc");
rs.insertRow();
rs.updateInt(1, 12);
rs.updateString("dname","CCCC");
rs.updateString(3, "Cloc");
rs.insertRow();
//回到插入前光标的位置
rs.moveToCurrentRow();
System.out.println(rs.getRow());//1
//删除行
rs.absolute(2);
rs.deleteRow();
4.5 展示结果(show data)

将数据库中的各种类型转化为Java中的类型(getXXX)方法

4.6 关闭操作对象

rs.close();
st.close();
conn. close();

完整示例代码:

//TestJDBC.java
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
public class TestJDBC1 {
	public static void main(String args[]) {
		//从配置文件中读取数据库连接相关信息,采用反射机制加载驱动
		String driverName = PropertiesMgr.getProperty("driver");
		String url = PropertiesMgr.getProperty("url");
		String username = PropertiesMgr.getProperty("username");
		String password = PropertiesMgr.getProperty("password");
		//声明数据库操作相关对象
		Connection conn = null;
		Statement stmt = null;
		PreparedStatement pstmt = null;
		CallableStatement cstmt = null;
		ResultSet rs = null;
		//获取测试预处理语句时需要的参数
		if(args.length != 3) {
			System.out.println("wrong parameters,please check and input again!");
			System.exit(0);
		}
		int deptno = 0;
		try{
			deptno = Integer.parseInt(args[0]);
		}catch(NumberFormatException e) {
			System.out.println("wrong parameter 0,deptno should be a number");
		}
		String dname = args[1];
		String loc = args[2];		
		
		try{
			//加载驱动,获得数据库连接
			Class.forName(driverName);
			conn = DriverManager.getConnection(url,username,password);
			
			//普通语句
			stmt = conn.createStatement();			
			String sql = "insert into dept2 values(99,'upc','dy')";
			stmt.executeUpdate(sql);
			
			//预处理语句			
			pstmt = conn.prepareStatement("insert into dept2 values(?,?,?)");
			pstmt.setInt(1, deptno);
			pstmt.setString(2, dname);
			pstmt.setString(3, loc);
			pstmt.executeUpdate();
			
			//调用带参数的存储过程(3,4为out,124为in),由于存储过程参数默认为in,所以需要显示声明out参数
			cstmt = conn.prepareCall("call pp(?,?,?,?)");
			cstmt.registerOutParameter(3, Types.INTEGER);
			cstmt.registerOutParameter(4, Types.INTEGER);
			cstmt.setInt(1, 3);
			cstmt.setInt(2, 4);
			cstmt.setInt(4, 5);
			cstmt.execute();
			System.out.println(cstmt.getInt(3));
			System.out.println(cstmt.getInt(4));
			
			//普通批处理
			stmt.addBatch("delete from dept2 where deptno=99");
			stmt.addBatch("delete from dept2 where deptno=23");
			stmt.addBatch("delete from dept2 where deptno=50");
			stmt.executeBatch();
			
			//预处理批处理
			pstmt = conn.prepareStatement("insert into dept2 values(?,?,?)");
			
			pstmt.setInt(1, 50);
			pstmt.setString(2, "clerk");
			pstmt.setString(3, "bj");
			pstmt.addBatch();
			
			pstmt.setInt(1, 60);
			pstmt.setString(2, "manager");
			pstmt.setString(3, "sh");
			pstmt.addBatch();
			
			pstmt.setInt(1, 70);
			pstmt.setString(2, "assistant");
			pstmt.setString(3, "jn");
			pstmt.addBatch();
			
			pstmt.executeBatch();
			
			//事务处理
			conn.setAutoCommit(false);
			stmt.addBatch("insert into dept2 values (41, '50', 'ha')");
			stmt.addBatch("insert into dept2 values (42, '50', 'ha')");
			stmt.addBatch("insert into dept2 values (430, '50', 'ha')");
			stmt.executeBatch();
			conn.commit();
			conn.setAutoCommit(true);
			
			//ResultSet类似于游标,可循环取得查询结果
			rs = stmt.executeQuery("select * from dept2");
			while(rs.next()) {
				System.out.print(rs.getInt(1) + "," + rs.getString("dname") + "," + rs.getString(3));
				System.out.println();
			}
			
			//可滚动的游标
			stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ_ONLY);
			rs = stmt.executeQuery("select * from dept2 order by deptno");
			rs.next();
			System.out.println(rs.getInt(1));
			rs.last();
			System.out.println(rs.getString(1));
			System.out.println(rs.isLast());
			rs.next();
			System.out.println(rs.isAfterLast());
			rs.previous();
			System.out.println(rs.getRow());
			System.out.println(rs.getString(1));
			rs.absolute(6);
			System.out.println(rs.getString(1));
			
			//可更新的游标
			stmt = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
			rs = stmt.executeQuery("select deptno,dname,loc from dept2 order by deptno");
			rs.next();
		    //更新一行数据
		    rs.updateString("dname","AAAAA");
		    rs.cancelRowUpdates();//取消更新,用在updater metord之后,updateRow之前
		    rs.updateRow();
		    System.out.println(rs.getRow());//1
		    //插入新行,当前光标的位置会备份
		    rs.moveToInsertRow();
		    rs.updateInt(1, 11);
		    rs.updateString("dname","BBBB");
		    rs.updateString(3, "Bloc");
		    rs.insertRow();
		    rs.updateInt(1, 12);
		    rs.updateString("dname","CCCC");
		    rs.updateString(3, "Cloc");
		    rs.insertRow();
		    //回到插入前光标的位置
		    rs.moveToCurrentRow();
		    System.out.println(rs.getRow());//1
		    //删除行
		    rs.absolute(2);
		    rs.deleteRow(); 
		}catch(ClassNotFoundException e) {
			System.out.println("加载驱动失败,请检查是正确否引入相关jar文件");
			e.printStackTrace();
		}catch(SQLException e) {
			System.out.println("数据库连接失败,请检查连接字符串及数据库状态");
			e.printStackTrace();
			//用于事务处理,回滚操作
			try{
				if(conn != null) {
					conn.rollback();
					conn.setAutoCommit(true);
				}
			}catch(SQLException e1) {
				e1.printStackTrace();
			}
		} finally {
			try{
				if(rs != null) {
					rs.close();
					rs = null;
				}
				if(cstmt != null) {
					cstmt.close();
					cstmt = null;
				}
				if(pstmt != null) {
					pstmt.close();
					pstmt = null;
				}
				if(stmt != null) {
					stmt.close();
					stmt = null;
				}
				if(conn != null) {
					conn.close();
					conn = null;
				}
			}catch(SQLException e) {
				System.out.println("语句对象或连接关闭异常");
				e.printStackTrace();
			}
		}
	}

}
//PropertiesMgr.java单例模式,读取数据库配置文件
import java.io.IOException;
import java.util.Properties;
public class PropertiesMgr {	
	private PropertiesMgr(){}
	
	private static Properties pro = new Properties();
	
	static{
		try {
			pro.load(PropertiesMgr.class.getClassLoader().getResourceAsStream("config/database.properties"));
		} catch (IOException e) {
			System.out.println("在$classpath/config/下未找到配置文件database.properties");
			e.printStackTrace();
		}
	}
	
	public static String getProperty(String key) {
		return pro.getProperty(key);
	}
}
//config/database.properties
driver=oracle.jdbc.driver.OracleDriver
url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
username=shijin
password=shijin

完整源码下载地址:http://download.csdn.net/detail/shijinupc/4211987

5 分类
5.1 对于Java开发人员

提供了一套统一的接口和方法来操作不同的数据库,从而让Java开发人员不需要关心到底使用那一种数据库,而是关心如何利用数据库实现业务操作,并且 在以后当更换数据库时,不需要更改代码

5.2 对于数据库厂商

厂商实现SUN提供的统一的API,从而达到一个统一Java操作数据库的标准的目的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值