使用JDBC进行数据库操作步骤:
1. 加载驱动:加载 JDBC 驱动需调用 Class 类的静态方法 forName(),向其传递要加载的 JDBC 驱动的类名。
- Class.forName(“com.mysql.jdbc.Driver”);
通过配置文件获取连接必需的4个因素,实现代码和数据的分离,可直接在配置文件中修改配置信息。
user=root
password=1214
url=jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true
driverClass=com.mysql.jdbc.Driver
2. 获取数据库连接对象Connection
通过驱动管理类获取数据库连接,将获取连接封装到JDBCUtils类中,使用时调用方法。
public class JDBCUtils {
public static Connection getConnection() throws Exception{
//读取配置文件中的四个基本信息
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
//加载驱动
Class.forName(driverClass);
//获取连接
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
3. 实例化PreparedStatement对象,执行sql语句
//获取连接
Connection conn = JDBCUtils.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
for (int i = 0; i <args.length ; i++) {
ps.setObject(i+1,args[i]);
}
//执行,获取结果集
ResultSet rs = ps.executeQuery();
4. 遍历结果集,通过结果集获取元数据,通过元数据得到列数。
//获取结果集的元数据
ResultSetMetaData rsmd = rs.getMetaData();
//通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount();
if(rs.next()){
T t = clazz.newInstance();
//处理结果集一行数据中的每一个列
for (int i = 0; i <columnCount ; i++) {
//获取列值
Object columValue = rs.getObject(i + 1);
//获取每个列的列名
String columnLabel = rsmd.getColumnLabel(i + 1);
//给cust对象指定的columnName属性,赋值为columValue,通过反射
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t,columValue);
}
return t;
5. 关闭资源,释放连接,将关闭方法封装在JDBCUtils类中
//针对查询操作关闭方法参数列表有结果集的关闭,增删改操作没有结果集
public static void closeResource(Connection conn, Statement ps,ResultSet rs){
try {
if (ps!=null)
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (conn!=null)
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
try {
if (rs!=null)
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
数据库通用的增删改操作
//通用的增删改操作
public void update(String sql,Object ...args){ //sql中占位符的个数应该与可变形参个数一致
Connection conn = null;
PreparedStatement ps = null;
try {
//1.获取连接
conn = JDBCUtils.getConnection();
//2.预编译sql语句,返回PreparedStatement的实例
ps = conn.prepareStatement(sql);
//3.填充占位符
for (int i = 0; i <args.length ; i++) {
ps.setObject(i+1,args[i]);//小心参数声明错误
}
//4.执行
ps.execute();
} catch (Exception e) {
e.printStackTrace();
} finally {
//5.资源的关闭
JDBCUtils.closeResource(conn,ps);
}
}
数据库通用的查询操作
public <T> T getInstance(Class<T> clazz,String sql,Object ...args){
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
//加载驱动,获取连接
conn = JDBCUtils.getConnection();
//预编译sql语句,得到PrepareStatement实例
ps = conn.prepareStatement(sql);
for (int i = 0; i <args.length ; i++) {
ps.setObject(i+1,args[i]);
}
//执行得到结果集
rs = ps.executeQuery();
//获取结果集的元数据
ResultSetMetaData rsmd = rs.getMetaData();
//通过ResultSetMetaData获取结果集中的列数
int columnCount = rsmd.getColumnCount();
if(rs.next()){
T t = clazz.newInstance();
//处理结果集一行数据中的每一个列
for (int i = 0; i <columnCount ; i++) {
//获取列值
Object columValue = rs.getObject(i + 1);
//获取每个列的列名
String columnLabel = rsmd.getColumnLabel(i + 1);
//给cust对象指定的columnName属性,赋值为columValue,通过反射
Field field = clazz.getDeclaredField(columnLabel);
field.setAccessible(true);
field.set(t,columValue);
}
return t;
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//资源的关闭
JDBCUtils.closeResource(conn,ps,rs);
}
return null;
}
使用PreparedStatement 替代 Statement 的好处:
PreparedStatement会对sql语句进行预编译,能提升性能防止sql注入问题。
PreparedStatement可以实现对Blob类型字段的操作。
PreparedStatement因为预编译的特性,所以进行批量操作效率更高。