1.使用Statement弊端
需要拼写SQL语句,并且有sql注入问题
2.解决sql注入问题:
只要用PreparedStatement(从Statement扩展而来)取代Statement
3.ClassLoader.getSystemClassloader()作用:
获取类加载器
l将数据连接所需要的四个基本信息声明在配置文件中,通过读取配置文件的方式获取 连接
此种方法的好处:
1.实现了数据与代码的分离,实现了解耦
2.如果需要修改配置文件的信息,可以避免程序重新打包
(1)在src下新建一个名为jdbc.properties的配置文件
#user后的值根据自己数据库的用户名进行填写 user=root #password后的值根据自己的数据库登录密码进行进行填写 password=root #jdbc:mysql://localhost:3306/要操作的数据库的名字 url=jdbc:mysql://localhost:3306/test715 #driverClass为Driver驱动 driverClass=com.mysql.jdbc.Driver
(2)读取配置文件信息
//1.获取配置文件信息 InputStream is = ClassLoader.getSystemClassLoader().getSystemResourceAsStream("jdbc.properties"); Properties pro= new Properties(); pro.load(is); String user = pro.getProperty("user"); String password = pro.getProperty("password"); String url = pro.getProperty("url"); String classDriver = pro.getProperty("driverClass");
//2.加载驱动 Class.forName(classDriver);
//3.建立连接 Connection conn = DriverManager.getConnection(url, user, password);
//4.预编译sql语句,返回PreparedStatement的实例 //?代表占位符, String sql = "insert into book values(?,?,?,?,?)"; PreparedStatement ps = conn.prepareStatement(sql);
//5.填充占位符 //根据每个位置上的数据类型填写set数据类型(位置,值),位置从开始 ps.setString(1, "b-1008"); ps.setString(2, "水浒"); ps.setFloat(3,50.00f); ps.setString(4, "2020-11"); ps.setInt(5, 8);
//6.执行操作 ps.execute();
//7.资源关闭 try { if(ps != null) ps.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } try { if(conn != null) conn.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); }
完整代码:
import java.io.IOException; import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Properties; import org.junit.Test; public class jdbcAdd { /* * 普通的获取jdbc连接,并向数据库中添加信息的方法 * * */ @Test public void testAdd() { Connection conn = null; PreparedStatement ps = null; try { //1.获取配置文件信息 InputStream is = ClassLoader.getSystemClassLoader().getSystemResourceAsStream("jdbc.properties"); Properties pro= new Properties(); pro.load(is); String user = pro.getProperty("user"); String password = pro.getProperty("password"); String url = pro.getProperty("url"); String classDriver = pro.getProperty("driverClass"); //2.加载驱动 Class.forName(classDriver); //3.建立连接 conn = DriverManager.getConnection(url, user, password); //4.预编译sql语句,返回PreparedStatement的实例 String sql = "insert into book values(?,?,?,?,?)"; ps = conn.prepareStatement(sql); //5.填充占位符 //根据每个位置上的数据类型填写set数据类型(位置,值),位置从开始 ps.setString(1, "b-1008"); ps.setString(2, "水浒"); ps.setFloat(3,50.00f); ps.setString(4, "2020-11"); ps.setInt(5, 8); //6.执行操作 ps.execute(); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); }finally { //7.关闭资源 try { ps.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } try { conn.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
-——将获取连接和关闭资源封装成一个工具类
因为获取连接和关闭连接的操作在每次增删改查操作中都会使用到,为了简化代码。我们将获取连接和关闭连接的代码封装在一个工具类中
import java.io.InputStream; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.util.Properties; public class JDBCUtils { //获取连接 public static Connection getConnection() throws Exception{ //1.获取配置文件信息 InputStream is = ClassLoader.getSystemClassLoader().getSystemResourceAsStream("jdbc.properties"); Properties pro= new Properties(); pro.load(is); String user = pro.getProperty("user"); String password = pro.getProperty("password"); String url = pro.getProperty("url"); String classDriver = pro.getProperty("driverClass"); //2.加载驱动 Class.forName(classDriver); //3.建立连接 Connection conn = DriverManager.getConnection(url, user, password); return conn; } //关闭连接和Statement操作 public void closeResource(Connection conn,PreparedStatement ps) { try { ps.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } try { conn.close(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
注意:
由于sql语句的占位符个数以及类型都不确定,因此用Object …args代替
sql中占位符的个数应与可变形参的长度相同
主要代码:
//1.获取数据库连接 conn = JDBCUtils.getConnection(); //2.预编译sql语句,返回一个PreparedStatement的实例 ps = conn.prepareStatement(sql); //3.填充占位符 //由于不知道占位符的个数,因此用for循环完成 //sql中占位符的个数应与可变形参的长度相同 for(int i = 0;i<args.length;i++) { //i+1为占位符位置,一定从1开始 //args[i]为占位符的值 ps.setObject(i+1, args[i]);//小心参数声明错误 } //4.执行操作 ps.execute(); //5.关闭资源 JDBCUtils.closeResource(conn, ps);
测试添加代码:
@Test public void testBookAdd() throws Exception { //向book表中添加一条记录 String sql = "insert into book values(?,?,?,?,?)"; update(sql,"b-1010","西游记",35.06,"2000-06",18); }
测试修改代码:
@Test public void testBookUpdate() throws Exception { //将aid为8的书的aid变为4 String sql = "update book set aid=? where aid=?"; update(sql,4,8); }
测试删除代码:
@Test public void testBookdelete() throws Exception { //删除aid为18的记录 String sql = "delete from book where aid=?"; update(sql,18); }
完整代码:
import java.sql.Connection; import java.sql.PreparedStatement; import org.junit.Test; public class PreparedStatementUpdateTest { @Test public void testBookAdd() throws Exception { //向book表中添加一条记录 String sql = "insert into book values(?,?,?,?,?)"; update(sql,"b-1010","西游记",35.06,"2000-06",18); } @Test public void testBookUpdate() throws Exception { //将aid为8的书的aid变为4 String sql = "update book set aid=? where aid=?"; update(sql,4,8); } @Test public void testBookdelete() throws Exception { //删除aid为18的记录 String sql = "delete from book where aid=?"; update(sql,18); } //通用的增删改操作 /* * String sql用于指明sql语句 * 由于sql语句的占位符个数以及类型都不确定,因此用Object ...args代替 * * sql中占位符的个数应与可变形参的长度相同 * * */ public void update(String sql,Object ...args) throws Exception { Connection conn = null; PreparedStatement ps = null; try { //1.获取数据库连接 conn = JDBCUtils.getConnection(); //2.预编译sql语句,返回一个PreparedStatement的实例 ps = conn.prepareStatement(sql); //3.填充占位符 //由于不知道占位符的个数,因此用for循环完成 //sql中占位符的个数应与可变形参的长度相同 for(int i = 0;i<args.length;i++) { //i+1为占位符位置,一定从1开始 //args[i]为占位符的值 ps.setObject(i+1, args[i]);//小心参数声明错误 } //4.执行操作 ps.execute(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { //5.关闭资源 JDBCUtils.closeResource(conn, ps); } } } }
结果测试:
正常:
执行添加操作
执行修改操作
执行删除操作