JDBC
JDBC: java database connectivity,即java与数据库的连接。
JDBC常用API | 作用 |
---|---|
Driver接口 | 所有JDBC驱动程序必须实现的接口,专门提供给数据库厂商使用 |
DriverManager类 | 加载JDBC驱动并创建于数据库的连接 |
Connection接口 | 代表Java与数据库连接的对象,只有获取这个对象才能操作数据库 |
Statement接口 | 用于执行静态SQL语句 |
PreparedStatement接口 | 预处理块,处理SQL语句 |
ResultSet接口 | 保存返回结果的结果集 |
ResultSetMetaData | 结果集元信息(字段名,字段个数等信息) |
JDBC使用流程
public class Demo03 {
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
//1、加载数据库驱动到JVM
Class.forName("oracle.jdbc.OracleDriver");
//2、获取数据库连接对象
//连接数据库的url
String url = "jdbc:oracle:thin:@localhost:1521:XE";
//登陆的用户名和密码
String user = "SCOTT";
String password = "TIGER";
conn = DriverManager.getConnection(url, user, password);
//3、根据连接得到Statement对象
stmt = conn.createStatement();
//4、使用Statement对象执行SQL语句,返回一个结果集
String sql = "select deptno,dname,loc from dept";
rs = stmt.executeQuery(sql);
//5、操作结果集
while(rs.next()) {
System.out.println(rs.getInt(1)+"-->"+rs.getString(2)+"-->"+rs.getString(3));
}
//6、关闭资源
rs.close();
stmt.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
上面代码使用了静态处理块,它的缺点是,性能不高,拼接sql麻烦,可能存在sql注入。因此在JDBC中应该使用预处理块PreparedStatement。
public class Demo04 {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement pstm = null;
ResultSet rs = null;
try {
//1、加载数据库驱动到JVM
Class.forName("oracle.jdbc.OracleDriver");
//2、获取数据库连接对象
//连接数据库的url
String url = "jdbc:oracle:thin:@localhost:1521:XE";
//登陆的用户名和密码
String user = "SCOTT";
String password = "TIGER";
conn = DriverManager.getConnection(url, user, password);
//3、根据连接得到Statement对象,预处理sql语句,可以用?指代参数
String sql = "select deptno,dname,loc from dept where deptno = ?";
pstm = conn.prepareStatement(sql);
//4、使用PreparedStatement对象设置sql里参数,然后执行返回结果集
pstm.setInt(1, 20);
rs = pstm.executeQuery();
//5、操作结果集
while(rs.next()) {
System.out.println(rs.getInt(1)+"-->"+rs.getString(2)+"-->"+rs.getString(3));
}
//6、关闭资源
rs.close();
pstm.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
JDBC的封装
/*
* 封装JDBC的基本功能
*/
public class DBUtils {
//配置文件
private static Properties pro = new Properties();
//静态块加载类时执行一次,加载配置文件并加载数据库驱动
static {
try {
pro.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("jdbc.properties"));
Class.forName(pro.getProperty("className"));
} catch (ClassNotFoundException e) {
System.out.println("数据库驱动加载异常");
} catch (IOException e) {
System.out.println("数据库配置文件加载异常");
}
}
//获取连接
public static Connection getConnection() throws SQLException {
Connection conn = null;
String url = pro.getProperty("url");
String username = pro.getProperty("username");
String pwd = pro.getProperty("pwd");
conn = DriverManager.getConnection(url, username, pwd);
return conn;
}
//关闭资源
public static void close(Connection conn,Statement stmt,ResultSet rs) {
try {
if(conn != null) {
conn.close();
}
if(stmt != null) {
stmt.close();
}
if(rs != null) {
rs.close();
}
}catch(Exception e) {
e.printStackTrace();
}
}
public static void close(Connection conn,Statement stmt) {
close(conn,stmt,null);
}
}
使用反射操作工具类获得对应pojo类的集合
/*
* 用DBUtils类操作数据库,将dept表中数据持久化到pojo类中
*/
public class Demo05<T> {
// 查询数据的方法,返回list集合,储存对象类型由clz确定
public List<T> queryList(String sql, Class<T> clz, Object... objects) {
Connection conn = null;
PreparedStatement pstm = null;
ResultSet rs = null;
List<T> list = new ArrayList<T>();
try {
//获取连接
conn = DBUtils.getConnection();
//获取预处理块
pstm = conn.prepareStatement(sql);
//为sql语句的占位符设值
if (objects != null) {
for (int i = 0; i < objects.length; i++) {
pstm.setObject(i + 1, objects[i]);
}
}
//得到结果集
rs = pstm.executeQuery();
//得到结果集元信息
ResultSetMetaData meta = rs.getMetaData();
//用反射为每行记录创建对象
while(rs.next()) {
T t = clz.getConstructor().newInstance();
int count = meta.getColumnCount();
for(int i=1;i<=count;i++) {
//该行记录的第i个字段的查询结果
Object value = rs.getObject(i);
//该行记录的第i个字段的字段名,注意大小写问题
String columnName = meta.getColumnName(i).toLowerCase();
//获取属性对象并设置值
//oracle数据库number类型默认获取为java中BigDecimal类型
Field fieldName = clz.getDeclaredField(columnName);
fieldName.setAccessible(true);
fieldName.set(t, value);
fieldName.setAccessible(false);
}
//添加对象
list.add(t);
}
} catch (Exception e) {
e.printStackTrace();
}
return list;
}
}
//测试类
public class Demo06 {
public static void main(String[] args) {
Demo05<Dept> d = new Demo05<>();
String sql = "select * from dept where deptno in(?,?,?)";
List<Dept> list = d.queryList(sql, Dept.class,10,20,30);
list.forEach(System.out::println);
}
}
//运行结果:
Dept [deptno=10, dname=ACCOUNTING, loc=NEW YORK]
Dept [deptno=20, dname=RESEARCH, loc=DALLAS]
Dept [deptno=30, dname=SALES, loc=CHICAGO]