(一)JDBC连接数据库
JDBC
JDBC(java DataBase Connectivity) Java连接数据库技术的简称,是Java连接各种数据库的能力。
-->Oracle
应用程序-------------->JDBC -------------------> SQLServer
-->MySQL
JDBC的工作原理
应用程序
|
JDBC API
|
驱动管理器
O
RACLE驱动
SQLServer驱动
| |
Oracle数据库 SQLServer
sun提供JDBC API集中在java.sql 和java.sql包中
JDBC API 主要包括:
DriverManager类
Connection接口
Statement接口
ResultSet接口
JDBC驱动是不同数据库厂商对各自数据库进行JDBC实现包。
DriverManager 负责管理加载的驱动
Connection负责对数据库的连接
Statement由Connection产生,负责执行SQL语句
ResultSet保存Statement执行得到的结果。
JDBC的功能只要实现如下处理:
1)将应用程序和数据库进行连接
2)执行SQL语句
3)将执行语句得到的结果返回应用程序
JDBC进行数据库连接的方式主要有ODBC连接和纯Java驱动连接
ODBC需要配置当前系统的数据源并且只能在Windows系统下连接(只做了解)
纯Java驱动连接不依赖环境,直接由驱动获取连接,是我们主要学习连接数据库的方式。
使用JDBC进行数据库访问的步骤:
1、处理数据库驱动,获取数据库连接对象
2、使用数据库连接对象获取处理器对象
3、使用处理器对象执行增删改查语句
4、使用结果集对象读取查询的结果
5、关闭JDBC API对象
纯Java JDBC连接
Class.forName(oracle.jdbc.driver.OracleDriver);
//oracle.jdbc.driver是包名,OracleDriver是该包下的类名
Connection con
=DriverManager.getConnection("jdbc:oracle:thin:@IP:端口:实例名","用户名","密码");
使用处理器执行SQL语句
//使用数据库连接对象获取处理器对象
Statement stmt = con.createStatement();
//executeUpdate(SQL语句)返回int类型
int count = stmt.executeUpdate(SQL语句);
Statement 可以实现但是预处理器不能实现的:
批处理
Statement有一个方法 addBatch(SQL语句)
//创建处理器对象
Statement stmt = con.createStatement();
//批处理
stmt.addBatch("update users set age=25 where userid=34");
stmt.addBatch("insert into users(userid,userName) values(userId.nextval,'tony')");
//获取批处理后的受影响行数
int[] results = stmt.executeBatch();
for(int i : results){
if(i == 1){
System.out.println("执行成功");
}
}
使用结果集获取查询结果
while(rs.next()){
读取行中的每个数据列的值,根据列索引调用getXXX取决数据表的类型。
如果获取时间,使用timestamp类型获取
//获取时间使用timeStamp类型
//Date birthday = rs.getTimestamp(3);
如果记不住索引位置也可以根据列的名称
//根据列的名称获取
//String email = rs.getString("email");
//String sex = rs.getString(5);
}
ResultSet rs = stmt.executeQuery();
while(rs.next()){
rs.getInt(列所在的索引);
rs.getString(列所在的索引);
}
关闭对象
结果集.close();
处理器.close();
连接.close();
预处理 PrepareStatement 继承于Statement
预处理器可以通过?表示参数占位符来注入参数
使用预处理简化参数的注入
创建预处理器,能够对SQL进行预编译,多次执行时有着更高的性能。
PreparedStatement pstmt = con.prepareStatement(SQL语句);
pstmt.executeUpdate();
pstmt.executeQuery();
/**********使用预处理器简化参数的注入**********/
//创建SQL语句
//预处理器可以通过?表示参数占位符来注入参数
String sql = "insert into users(userId,userName,age,sex,birthday) values(userId.nextval,?,?,?,?)";
//创建预处理器,能够对SQL进行预编译,多次执行时有着更高的性能
PreparedStatement pstmt = con.prepareStatement(sql);
//对参数进行注入
pstmt.setString(1, name);
pstmt.setInt(2, age);
pstmt.setString(3, sex);
//获取timestamp类型的时间
Date date = new SimpleDateFormat("yyyy-mm-dd").parse(birthday);
pstmt.setTimestamp(4, new Timestamp(date.getTime()));
//执行新增
pstmt.executeUpdate();
//查询
pstmt.close();
pstmt = con.prepareStatement("select * from users");
ResultSet rs = pstmt.executeQuery();
while(rs.next()){
System.out.println(rs.getInt(1));
System.out.println(rs.getString(2));
}
con.close();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
PreparedStatement 和 Statement的区别
预处理可以将要执行的SQL先进行编译,下次使用时可以直接执行已经编译的代码,普通的处理器每次执行都要重新编译。
预处理使用代码注入的方式增强SQL操作的安全性,防止外部的恶意参数注入。
CallableStatement 继承于 PreparedStatement
是获取执行存储过程的处理器
/***************带有输入参数的存储过程**************/
//获取执行存储过程的处理器
CallableStatement cstmt = con.prepareCall("{call insertUser(?,?,?)}");
//注入参数
cstmt.setInt(1, 40);
cstmt.setString(2, "jerry");
cstmt.setTimestamp(3, new Timestamp(new Date().getTime()));
//执行存储过程
cstmt.execute();
/***************带有输出参数的存储过程**************/
//输入和输出参数都使用占位符
CallableStatement cstmt = con.prepareCall("{call findUserById(?,?,?)}");
//为输入参数注入参数
cstmt.setInt(1, 34);
//注册输出参数
cstmt.registerOutParameter(2, OracleTypes.VARCHAR);
cstmt.registerOutParameter(3, OracleTypes.VARCHAR);
//执行
cstmt.execute();
//获取输出参数的值
String name = cstmt.getString(2);
String sex = cstmt.getString(3);
System.out.println(name+"\t"+sex);
/****************带有输出类型为游标的存储过程过程***************/
CallableStatement cstmt = con.prepareCall("{call findEmpByDepId(?,?)}");
//注入参数
cstmt.setInt(1, 50);
//注册输出参数为游标类型
cstmt.registerOutParameter(2, OracleTypes.CURSOR);
//执行
cstmt.execute();
//获取游标,返回的Object值需要拆箱成ResultSet类型
ResultSet rs = (ResultSet) cstmt.getObject(2);
while(rs.next()){
System.out.println(rs.getString(1));
}