1、加载和注册驱动
2、获取数据库连接
3、准备操作执行 SQL 的 Statement 对象
4、执行 SQL
(1)调用 Statement 对象的 executeUpdate(String sql)执行 SQL 语句进行插入、修改、删除操作
(2)调用 Statement 对象的 executeQuery(String sql)执行 SQL 语句进行查询操作
5、处理执行结果
(1)CUD 操作,根据返回的 int 值判断结果
(2)查询操作,根据返回 ResultSet 结果集,获取查询数据
6、释放资源
总结:
(1)加载和注册驱动,整个项目做一次即可
(2)获取数据库连接可以封装到一个方法中
(3)释放资源可以封装到一个方法中
public class JDBCUtils {
private static String drivername;
private static String url;
private static String user;
private static String password;
private static Properties pro = new Properties();
static{
try {
//加载,读取 jdbc.properties 配置的信息
//pro.load 的作用是把 jdbc.properties 文件中配置的信息,一一 put 到 pro 这个 map 中
pro.load(ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties"));
// drivername = pro.getProperty("key")
drivername = pro.getProperty("drivername");
url = pro.getProperty("url");
user = pro.getProperty("user");
password = pro.getProperty("password");
//注册驱动,加载驱动
Class.forName(drivername);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static Connection getConnection()throws SQLException{
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
public static void closeQuietly(Connection conn){
try {
if(conn!=null){
conn.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void closeQuietly(Statement st){
try {
if(st!=null){
st.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void closeQuietly(ResultSet rs){
try {
if(rs!=null){
rs.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
public static void closeQuietly(Statement st,Connection conn){
closeQuietly(st);
closeQuietly(conn);
}
public static void closeQuietly(ResultSet rs,Statement st,Connection conn){
closeQuietly(rs);
closeQuietly(st);
closeQuietly(conn);
}
}
可以通过调用 Connection 对象的 preparedStatement(String sql) 方法获取 PreparedStatement 对象
PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句
(1 )SQL 拼接
(2 )SQL 注入
SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或
命令,从而利用系统的 SQL 引擎完成恶意行为的做法。对于 Java 而言,要防范 SQL 注入,只要用
PreparedStatement 取代 Statement 就可以了。
(3 )处理 Blob 类型的数据
BLOB (binary large object),二进制大对象,BLOB 常常是数据库中用来存储二进制文件的字段类型。
插入 BLOB 类型的数据必须使用 PreparedStatement,因为 BLOB 类型的数据无法使用字符串拼接写的。
MySQL 的四种 BLOB 类型(除了在存储的最大信息量上不同外,他们是等同的)
/*
* Statement:
* 1、SQL 拼接
* 2、SQL 注入
* 3、处理不了 Blob 类型的数据
*/
public class TestStatementProblem {
@Test
public void add() throws Exception{
Scanner input = new Scanner(System.in);
System.out.println("请输入姓名:");
String name = input.nextLine();
System.out.println("请输入领导编号:");
int mid = input.nextInt();
System.out.println("请输入部门编号:");
int did = input.nextInt();
//1、获取连接
Connection conn = JDBCUtils.getConnection();
//2、创建 Statement 对象
Statement st = conn.createStatement();
//3、编写 sql
String sql = "INSERT INTO emp (ename,`mid`,did) VALUES('" + name+"'," + mid + "," + did + ")";
//4、执行 sql
int update = st.executeUpdate(sql);
System.out.println(update>0?"添加成功":"添加失败");
//5、释放资源
JDBCUtils.closeQuietly(st, conn);
}
@Test
public void select()throws Exception{
Scanner input = new Scanner(System.in);
System.out.println("请输入姓名:");
String name = input.nextLine();
//1、获取连接
Connection conn = JDBCUtils.getConnection();
//2、写 sql
//孙红雷 ' or '1' = '1
String sql = "SELECT eid,ename,tel,gender,salary FROM t_employee WHERE ename = '" + name + "'";
System.out.println(sql);
// SELECT eid,ename,tel,gender,salary FROM t_employee WHERE ename = '孙红雷 ' or '1' = '1'
//3、用 Statement 执行
Statement st = conn.createStatement();
//4、执行查询 sql
ResultSet rs = st.executeQuery(sql);
while(rs.next()){
int id = rs.getInt(1);
String ename = rs.getString(2);
String tel = rs.getString(3);
String gender =rs.getString(4);
double salary = rs.getDouble(5);
System.out.println(id+"\t" + ename + "\t" + tel + "\t" + gender + "\t" +salary);
}
//5、释放资源
JDBCUtils.closeQuietly(rs, st, conn);
}
@Test
public void testAddBlob(){
String sql = "INSERT INTO `user` (username,`password`,photo)VALUES('chai','123',没法在String中处理Blob类型的数据);";
}
}
/*
* PreparedStatement:是 Statement 子接口
* 1、SQL 不需要拼接
* 2、SQL 不会出现注入
* 3、可以处理 Blob 类型的数据
*/
public class TestPreparedStatement {
@Test
public void add() throws Exception {
Scanner input = new Scanner(System.in);
System.out.println("请输入姓名:");
String name = input.nextLine();
System.out.println("请输入性别:");
String gender = input.nextLine();
System.out.println("请输入领导编号:");
int mid = input.nextInt();
System.out.println("请输入部门编号:");
int did = input.nextInt();
String sql = "INSERT INTO emp VALUES(NULL,?,?,?,?)";// 参数,占位符,通配符,表示这个地方需要设置值
// 2、获取连接
Connection conn = JDBCUtils.getConnection();
// 3、准备一个 PreparedStatement:预编译 sql
PreparedStatement pst = conn.prepareStatement(sql);// 对带?的 sql 进行预编译
// 4、把?用具体的值进行代替
pst.setString(1, name);
pst.setString(2, gender);
pst.setInt(3, mid);
pst.setInt(4, did);
// 5、执行 sql
int len = pst.executeUpdate();
// 6、释放资源
JDBCUtils.closeQuietly(pst, conn);
}
@Test
public void select() throws Exception {
// 3、写 sql
Scanner input = new Scanner(System.in);
System.out.println("请输入姓名:");
String name = input.nextLine();
// 孙红雷 ' or '1' = '1
String sql = "SELECT eid,ename,tel,gender,salary FROM t_employee WHERE ename = ?";
// 1、注册驱动,注册过了
// 2、获取连接
Connection conn = JDBCUtils.getConnection();
// 3、把带?的 sql 语句进行预编译
PreparedStatement pst = conn.prepareStatement(sql);
// 4、把?用具体的变量的赋值
pst.setString(1, name);
// 5、执行 sql
ResultSet rs = pst.executeQuery();
while (rs.next()) {
int id = rs.getInt("eid");
String ename = rs.getString("ename");
String tel = rs.getString("tel");
String gender = rs.getString("gender");
double salary = rs.getDouble("salary");
System.out.println(id + "\t" + ename + "\t" + tel + "\t" + gender + "\t" + salary);
}
// 6、释放资源
JDBCUtils.closeQuietly(rs, pst, conn);
}
@Test
public void addBlob() throws Exception {
Scanner input = new Scanner(System.in);
System.out.println("请输入用户名:");
String username = input.nextLine();
System.out.println("请输入密码:");
String password = input.nextLine();
System.out.println("请指定照片的路径:");
String photoPath = input.nextLine();
// INSERT INTO `user` VALUES(NULL,用户名,密码,照片)
String sql = "INSERT INTO `user` VALUES(NULL,?,?,?)";
// 1、注册驱动,注册过了
// 2、获取连接
Connection conn = JDBCUtils.getConnection();
// 3、准备一个 PreparedStatement:预编译 sql
PreparedStatement pst = conn.prepareStatement(sql);// 对带?的 sql 进行预编译
// 4、对?进行设置
pst.setString(1, username);
pst.setString(2, password);
pst.setBlob(3, new FileInputStream(photoPath));
// 5、执行 sql
int len = pst.executeUpdate();
System.out.println(len > 0 ? "添加成功" : "添加失败");
// 6、释放资源
JDBCUtils.closeQuietly(pst, conn);
}
}