1.使用Statement弊端
需要拼写SQL语句,并且有sql注入问题
2.解决sql注入问题:
只要用PreparedStatement(从Statement扩展而来)取代Statement
3.ClassLoader.getSystemClassloader()作用:
获取类加载器
jdbc连接数据库
1.新建配置文件
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);
对数据库进行操作
预编译sql语句
//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();
}
}
}
利用Utils工具类实现PreparedStatement的通用增删改操作
注意:
-
由于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);
}
}
}
}
结果测试:
正常:
执行添加操作
执行修改操作
执行删除操作