1.JdbcUtils工具类:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.sql.*;
import java.util.Properties;
public class JdbcUtils {
private static Properties prop;
static{
//1.读取jdbc.properties文件
try {
FileInputStream is = new FileInputStream("day05-web05/src/jdbc.properties");
prop = new Properties();
prop.load(is);
} catch (Exception e) {
e.printStackTrace();
}
}
//1.获取连接对象
public static Connection getCon(){
try {
//Class.forName("com")
return DriverManager.getConnection(prop.getProperty("url"),prop);
} catch ( Exception e) {
e.printStackTrace();
}
return null;
}
//2.释放资源
public static void close(ResultSet rs,Statement state,Connection con ){
if(rs!=null)try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
if(state!=null)try {
state.close();
} catch (SQLException e) {
e.printStackTrace();
}
if(con!=null)try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
- 注意事项
- 资源用完后一定要释放
- 可能出现的异常
- 读取properties文件可能会出现异常
登录案例:
import java.sql.*;
import java.util.Properties;
import java.util.Scanner;
public class Hello1 {
private static Properties prop;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入用户名:");
String name = sc.nextLine();
System.out.println("请输入密码:");
String psw = sc.nextLine();
/*boolean isLogin = login(name,psw);*/
boolean isLogin = login2(name,psw);
System.out.println(isLogin);
}
//登录案例
private static boolean login(String name, String psw) {
//1.获取连接对象
Connection con = JdbcUtils.getCon();
//2.定义sql
String sql = "select * from users where name ='"+name +"' and psw ='"+psw+ "'";
Statement state = null;
ResultSet rs = null;
try {
//3.获取执行sql对象
state = con.createStatement();
rs = state.executeQuery(sql);
return rs.next();
} catch (SQLException e) {
e.printStackTrace();
}finally {
//关闭资源
JdbcUtils.close(rs,state,con);
}
return false;
}
}
-注意事项
-在sql语句拼接用户名和密码时注意单引号和双引号
- 可能出现的异常
- sql语句拼接不正确会导致sql语法异常
3. 预编译对象优化登录案例
//登录方法--改进版
private static boolean login2(String name, String psw) {
//1.获取连接对象
Connection con = JdbcUtils.getCon();
//2.定义sql
String sql="select * from users where name = ? and psw = ?";
PreparedStatement pstm = null;
ResultSet rs = null;
try {
//3.获取执行sql的对象
pstm = con.prepareStatement(sql);
//3.1 给占位符赋值
pstm.setString(1,name);
pstm.setString(2,psw);
//4.执行sql
rs = pstm.executeQuery();
return rs.next();
} catch (SQLException e) {
e.printStackTrace();
}finally {
JdbcUtils.close(rs,pstm,con);
}
return false;
}
- 注意事项
- 记得给占位符?赋值
-可能出现的异常
-sql语句不要写错
两种实现方式的差异:
1.sql语句不再是拼接参数 ,使用?代替参数
2.在创建stmt对象时,空参 ; 在创建pstm对象时,传入sql模板 --预编译
3.pstm对象还需要为?填充参数值
4.stmt对象执行sql时,需要传入sql ; pstm对象执行sql时,不用再传sql
优点:
1.PreparedStatement对象可以防止sql注入,Statement对象不可以
2.PreparedStatement对象是预编译方式执行sql,会提前检查sql是否有语法错误,因此执行
效率更高
4. 管理事务
事务的操作在jdbc流程中的位置
1.开启 con.setAutoCommit(false); 放在con对象创建后
2.回滚 con.rollback(); 放在catch代码块
3.提交 con.commit(); try的最后一行
代码如下:
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class Hello2 {
public static void main(String[] args) {
//1.获取连接对象
Connection con = JdbcUtils.getCon();
//2.定义sql
String sql1 = "update account set balance=balance-? where id=?";
String sql2 = "update account set balance=balance+? where id=?";
PreparedStatement pstm1 = null;
PreparedStatement pstm2 = null;
try {
//开启事务--设置手动提交
con.setAutoCommit(false);
//3.获取执行sql的对象
pstm1 = con.prepareStatement(sql1);
pstm2 = con.prepareStatement(sql2);
//4.给占位符赋值
pstm1.setDouble(1,500);
pstm1.setInt(2,1);
pstm2.setDouble(1,500);
pstm2.setInt(2,2);
//5.执行sql
pstm1.executeUpdate();
pstm2.executeUpdate();
//提交事务
con.commit();
} catch (SQLException e) {
//回滚事务
try {
con.commit();
} catch (SQLException ex) {
ex.printStackTrace();
}
e.printStackTrace();
}finally {
JdbcUtils.close(null,pstm1,con);
}
}
}
- 注意事项
- 要执行两个sql,所有需要创建两个prepareStatement对象,但只需一个连接对象即可
- 两个prepareStatement对象最后都需要关闭
- 可能出现的异常
- sql语句语法错误会导致异常
- 给两个prepareStatement对象中的sql模板的占位符赋值不要错乱