一、概念
1、jdbc: java database connectivity 即java与数据库的连接
2、角色分类
服务器 (db): a)、接收 sql b)、执行 sql c)、返回结果
客户端 (java):a)、接收数据 b)、组装sql c)、发送SQL(与数据库建立联系) d)、分析结果
3、面向接口编程
java 制定标准 ,不同的数据库厂商实现 接口即可。java 中提供的接口 java.sql.* 包下,常用接口如下
接口名称 作用
java.sql.Connection 连接
java.sql.Statement 静态处理块
java.sql.PreparedStatement 预处理块
java.sql.ResultSet 结果集
java.sql.ResultSetMetaData 结果集元信息
oracle厂商实现接口 (jar)
F:\app\Administrator\product\11.2.0\dbhome_1\jdbc\lib\ojdbc6.jar 视安装路径而定
二、jdbc 步骤
1、jdbc 步骤类比寄快递
1、选择快递公司
加载驱动(完整路径)
2、与快递公司建立联系(电话号码 唯一信息)
建立连接(url 用户名 密码)
3、快递员 收包裹 创建处理块 Statement PreparedStatement
4、打包 投递
执行: execute(ddl) int executeUpdate(dml) ResultSet executeQuery(select)
5、签收
分析结果 :ddl -->没有异常 dml--->>0 select-->分析 结果集
6、打发走人 释放资源 核
核心为拼接 SQL、分析结果、操作结果
- 导包
在项目中新建一个source folder文件夹,名字为lib
将oracle里的实现接口jar包(app\Administrator\product\11.2.0\dbhome_1\jdbc\lib\ojdbc6.jar 视安装路径而定)复制到lib文件夹中
选择ojdbc6.jar右键选择add build path
- 建立连接
1)、连接字符串
驱动: oracle.jdbc.driver.OracleDriver
url: jdbc:oracle:thin:@db 服务器地址:端口:实例
连接 url:jdbc:oracle:thin:@localhost:1521:orcl
用户名与密码:如 scott tiger
2、简单的JDBC步骤
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Demo01 {
public static void main(String[] args) throws ClassNotFoundException, SQLException {
//1.加载驱动(选择数据库)
Class.forName("oracle.jdbc.driver.OracleDriver");
//2.获取连接(连接数据库)
Connection con=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "SCOTT", "TIGER");
//3.获取静态处理块(构建一个执行和发送SQL 语句的对象)
Statement state =con.createStatement();
//4.创建SQL语句
String str ="select ename,empno from emp";
//5.创建结果集
ResultSet result=state.executeQuery(str);
//6.获取结果
while (result.next()) {
String ename=result.getString(1);
long empno=result.getLong(2);
System.out.println(ename+"->"+empno);
}
//关闭资源
result.close();
state.close();
con.close();
}
}
3、处理块
- 静态处理块
Statement 是 Java 执行数据库操作的一个重要接口,用于在已经建立数据库连
接的基础上,向数据库发送要执行的 SQL 语句。Statement 对象,用于执行不带参数
的简单 SQL 语句。
执行静态 SQL 语句并返回它所生成结果的对象。
1)、创建 : 连接.Connection.createStatement()
2)、执行 :
ddl -->execute(dd语句) -- 通常不会在代码中执行
dml -->executeUpdate(dml语句)
select -->executeQuery(select)
3)、特点:处理 不变的静态的 sql 语句
优点: 直接查看sql ,方便处理错误
缺点:性能不高 拼接 sql 麻烦 可能存在 sql 注入
- 预处理块
PreparedStatement 接口继承了 Statement,并与之在两方面有所不同:有人主张,在 JDBC 应用中,如果你已经是稍有水平开发者,你就应该始终以PreparedStatement 代替 Statement.也就是说,在任何时候都不要使用 Statement。由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象。因此,多次执行的 SQL 语句经常创建为 PreparedStatement 对象,以提高效率。
1)、创建:创建:连接.prepareStatement(sql)
2)、执行:
存在? ,先填充参数再执行
ddl -->execute()
dml -->executeUpdate()
select -->executeQuery()
3)、特点 :处理 不变的静态的 sql 语句 |可变的 sql 语句 带 ? 的 sql
优点:性能高,方便编写sql 不存在sql注入 安全
缺点:不能直接打印sql语句 不方便处理错误
预处理块实例
public static boolean update(String name, String pwd ) {
Connection con = null;
ResultSet result = null;
PreparedStatement ps = null;
// 准备SQL语句
String sql = "update t_user set uname=?,pwd=?";
// 创建连接
try {
con = DBUtils.getConnection();
// 创建预处理块
ps = con.prepareStatement(sql);
// 更新数据
ps.setString(1, name);
ps.setString(2, pwd);
// 执行更新并返回结果
int num = ps.executeUpdate();
if (num <= 0) {
System.out.println("修改失败");
} else {
System.out.println("修改成功");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.close(con, ps, result);
}
return false;
}
6、使用预处理块
public static boolean update(String name, String pwd ) {
Connection con = null;
ResultSet result = null;
PreparedStatement ps = null;
// 准备SQL语句
String sql = "update t_user set uname=?,pwd=?";
// 创建连接
try {
con = DBUtils.getConnection();
// 创建预处理块
ps = con.prepareStatement(sql);
// 更新数据
ps.setString(1, name);
ps.setString(2, pwd);
// 执行更新并返回结果
int num = ps.executeUpdate();
if (num <= 0) {
System.out.println("修改失败");
} else {
System.out.println("修改成功");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.close(con, ps, result);
}
return false;
}
7、使用Properties配置文件
public static void main(String[] args) {
// 获取配置文件
Properties pro = new Properties();
Connection con = null;
PreparedStatement pre = null;
ResultSet result = null;
String ename = null;
long empno = 0;
try {
// 加载配置文件
// db.properties为当前src路径下放入键值对数据的文件
pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("db.properties"));
// 加载驱动
Class.forName(pro.getProperty("driver"));
// 创建连接
con = DriverManager.getConnection(pro.getProperty("url"), pro.getProperty("name"), pro.getProperty("pwd"));
// 创建sql语句
String sql = "select ename,empno from emp where ename=?";
// 获取处理块
pre = con.prepareStatement(sql);
// 站位
pre.setString(1, "SMITH");
// 获取结果
result = pre.executeQuery();
if (result.next()) {
ename = result.getString(1);
empno = result.getLong(2);
System.out.println(empno + "--->" + ename);
}
} catch (IOException e) {
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
if (result != null) {
result.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (pre != null) {
pre.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (con != null) {
con.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
8、自定义通用的操作数据库的类
/*
* 通用的操作数据库的类
*/
public class Base<T> {
// 更新数据
public boolean update(String str, Object[] obj) {
boolean flag = false;
Connection con = null;
PreparedStatement state = null;
con = DBUtils.getConnection();
try {
state = con.prepareStatement(str);
for (int i = 0; i < obj.length; i++) {
state.setObject(i + 1, obj[i]);
}
int num = state.executeUpdate();
if (num > 0) {
flag = true;
System.out.println("操作成功");
} else {
System.out.println("操作失败");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtils.close(con, state);
}
return flag;
}
// 查找数据
public List<T> search(String sql,Object[] obj,Class<T> cls){
List<T> list=new ArrayList() ;
Connection con=null;
ResultSet result=null;
PreparedStatement state=null;
//获取连接
con=DBUtils.getConnection();
try {
//获取预处理块
state=con.prepareStatement(sql);
//循环写入站位
if(obj!=null) {
for (int i = 0; i < obj.length; i++) {
state.setObject(i + 1, obj[i]);
}
}
//执行
result=state.executeQuery();
//ResultSetMetaData类可用于获取关于 ResultSet 对象中列的类型和属性信息的对象
ResultSetMetaData rsmd=state.getMetaData();
//判断结果
//获取结果数量
int count=rsmd.getColumnCount();
System.out.println(count);
while(result.next()) {
//创建用来存放记录的对象
T t=cls.newInstance();
for (int i = 0; i < count; i++) {
//获取字段名
String colName=rsmd.getColumnLabel(i+1);
System.out.println(colName);
//获取字段数据
Object value=result.getObject(i+1);
System.out.println(colName);
//获取字段数据类型
Field field= cls.getDeclaredField(colName);
//开启权限
field.setAccessible(true);
field.set(t, value);
field.setAccessible(false);
System.out.println(t);
}
//添加元素
list.add(t);
System.out.println("操作成功");
}
} catch (SQLException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}finally {
DBUtils.close(con, state,result);
}
System.out.println(list);
return list;
}
}
测试
String sql="insert into t_user values(?,?)";
Base<User> base=new Base<User>();
//String[] obj= {"赵铁柱","qwer"};
//base.update(sql, obj);
sql="select uname \"uname\",pwd \"pwd\" from t_user";
List list=base.search(sql, null, User.class);
System.out.println(list);