使用PreparedStatement对象:为什么要使用PreparedStatement
原因:(1)使用Statement需要拼接SQL,太费劲,也容易出错。
String sql = "insert into userinfo" + " values (" + player.getId() + ",‘" + player.getPlayerID() + "‘,‘"+ player.getName() + "‘,‘" + player.getTeam() + "‘,‘" + player.getCity() + "‘," + player.getMaxScore()+ ",‘" +player.getDraftyear() + "‘)";
PreparedStatement 在创建时就可以直接传入一个SQL语句,并且字段使用占位符即可,提供了处理占位符值得方法
PreparedStatement ps = Connection.PreparedStatement(sql);
String sql = insert into userinfo values(?,?,?,?).这样的额SQL语句是不容易出错的,因此我们之前使用Statement做的更新操作,可以用PreparedStatement来代替了
在执行ps.executeUpdate()里面不再需要传入SQL语句
(2)PreparedStatement可以有效的禁止SQL注入
(3) PreparedStatement是Statement的子接口
==============================================================================================================================================================
在JDBCUtils.java中我们可以添加一个方法,实现如下图所示:其中传入了一个SQL语句,还有一个可变参数,因为不知道具体的类型,所以使用了可变参数。。。。
// 使用preparedStatement对象进行更新
public static void updateDataUsePS(String sql, Object... args) {
// 获取连接
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();// 获得连接
ps = conn.prepareStatement(sql); // 创建statement对象
// 获取可变参数的值
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
ps.executeUpdate();
// System.out.println(sql);
System.out.println("SQL执行成功");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtils.closeSource(null, ps, conn);
System.out.println("资源关闭成功");
}
}
然后在实际的操作中调用这个方法:
// 插入一个新的运动员,使用preparedStatement
public void testAddPlayers1(Players player) {
String sql = "insert into userinfo values (?,?,?,?,?,?,?)";
JDBCUtils.updateDataUsePS(sql, player.getId(), player.getPlayerID(), player.getName(), player.getTeam(),
player.getCity(), player.getMaxScore(), player.getDraftyear());
}
//在测试方法中,去调用testAddPlayers1(Players player) 这个方法:
// 测试方法
@Test
public void testAddPlayers() {
Players player = getFromConsole();
testAddPlayers1(player);
// return player;
}
这里就可以使用Junit框架进行测试了,控制台运行截图如下所示:
完整源代码如下所示:
package com.jdbc.basedemo;
import java.io.IOException;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Scanner;
import org.junit.Test;
import com.jdbc.bean.Players;
public class CrudPlayer {
// 添加一个运动员,传入一个运动员对象
public void addPlayers(Players player) {
// 给出一个SQL
String sql = "insert into userinfo" + " values (" + player.getId() + ",‘" + player.getPlayerID() + "‘,‘"
+ player.getName() + "‘,‘" + player.getTeam() + "‘,‘" + player.getCity() + "‘," + player.getMaxScore()
+ ",‘" + player.getDraftyear() + "‘)";
System.out.println(sql);
// 调用更新方法
JDBCUtils.updateData(sql);
}
// @插入一个新的运动员,使用preparedStatement
public void testAddPlayers1(Players player) {
String sql = "insert into userinfo values (?,?,?,?,?,?,?)";
JDBCUtils.updateDataUsePS(sql, player.getId(), player.getPlayerID(), player.getName(), player.getTeam(),
player.getCity(), player.getMaxScore(), player.getDraftyear());
}
// 测试方法
@Test
public void testAddPlayers() {
Players player = getFromConsole();
testAddPlayers1(player);
// return player;
}
// 从控制台获取输入的运动员信息
private Players getFromConsole() {
// TODO Auto-generated method stub
Scanner input = new Scanner(System.in);
Players player = new Players();
System.out.println("请输入球员信息");
// 这里因为主键在数据表中设置了自增,所以拼接的SQL中只获取,而不用再一次输入ID
System.out.print("球员ID:");
player.setPlayerID(input.next());
System.out.print("球员姓名:");
player.setName(input.next());
System.out.print("球队名称:");
player.setTeam(input.next());
System.out.print("球队城市:");
player.setCity(input.next());
System.out.print("个人单场最高分:");
player.setMaxScore(input.nextInt());
System.out.println("选秀年:");
player.setDraftyear(input.next());
return player;
}
// 查询类型
@Test
public void testGetPlayer() {
// 获取查询类型
int searchType = getTypeFromConsole();
// 执行查询
Players players = searchPlayer(searchType);
// 打印运动员信息
printPlayer(players);
// return players;
}
// 打印运动员信息
private void printPlayer(Players players) {
// TODO Auto-generated method stub
if (players != null) {
System.out.println(players);
} else {
System.out.println("查无此人....");
}
}
// 具体查询运动员信息方法
private Players searchPlayer(int searchType) {
// TODO Auto-generated method stub
// select * 的写法不好,这里为了偷懒
String sql = "select * from userinfo" + " where ";
Scanner scanner = new Scanner(System.in);
// 根据确定的type,提示用户输入查询的类型
//// 最终确认SQL语句
if (searchType == 1) {
System.out.print("请输入球员ID编号:");
String playerID = scanner.next();
sql = sql + "playID=‘" + playerID + "‘";
} else {
System.out.print("请输入球员姓名:");
String name = scanner.next();
sql = sql + "username=‘" + name + "‘";
}
// 执行查询
Players player = getPlayer(sql);
return player;
}
// 执行查询的方法,根据SQL语句执行查询
private Players getPlayer(String sql) {
// TODO Auto-generated method stub
Players player = null;
Connection conn = null;
Statement statement = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();
statement = conn.createStatement();
rs = statement.executeQuery(sql);
if (rs.next()) {
player = new Players(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5),
rs.getInt(6), rs.getString(7));
int id = rs.getInt(1);
String playID = rs.getString(2);
String name = rs.getString(3);
String team = rs.getString(4);
String city = rs.getString(5);
int maxScore = rs.getInt(6);
String draftYear = rs.getString(7);
System.out.println("ID:" + id);
System.out.println("playID:" + playID);
System.out.println("名字:" + name);
System.out.println("球队:" + team);
System.out.println("城市:" + city);
System.out.println("个人单场最高分:" + maxScore);
System.out.println("选秀年:" + draftYear);
}
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtils.closeSource(rs, statement, conn);
}
// System.out.println(sql);
return player;
}
// 从控制台读入一个整数,返回1,用球员ID 查询,2,用姓名查询,其他的无效并提示让用户重新输入
private static int getTypeFromConsole() {
// TODO Auto-generated method stub
// 1 根据提示让用户输入查询类型,返回1,用球员ID 查询,2,用姓名查询
System.out.println("请输入查询类型:1.使用球员ID查询,2.使用姓名查询");
Scanner input = new Scanner(System.in);
int type = input.nextInt();
// 判断
if (type != 1 && type != 2) {
System.out.println("输入不合法,请重新输入....");
throw new RuntimeException(); // 中断程序
}
return type;
}
}
=================================================================================================================================================================
JDBCUtils.java的源代码文件:
package com.jdbc.basedemo;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Properties;
/*
* 操作数据库的公共类,里面是一些公共方法
* */
public class JDBCUtils {
// 获取数据库连接
// 连接数据库
public static Connection getConnection() throws ClassNotFoundException, IOException, SQLException {
// 定义相关变量
String driverClass = null;
String jdbcUrl = null;
String user = null;
String password = null;
// 读取配置文件jdbc.properties
InputStream in = JDBCUtils.class.getClassLoader().getResourceAsStream("jdbc.properties");
Properties properties = new Properties();
properties.load(in);
driverClass = properties.getProperty("driver");
jdbcUrl = properties.getProperty("jdbcUrl");
user = properties.getProperty("user");
password = properties.getProperty("password");
// 加载数据库驱动
Class.forName(driverClass);
// 获取连接
Connection conn = DriverManager.getConnection(jdbcUrl, user, password);
return conn;
}
// 释放资源的方法
public static void closeSource(ResultSet rs, Statement statement, Connection conn) {
if (rs != null) {
try {
rs.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
if (statement != null) {
try {
statement.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}
}
// 封装一个通用的更新方法,适用于INSERT,UPDATE,DELETE
public static void updateData(String sql) {
// 获取连接
Connection conn = null;
Statement statement = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();// 获得连接
statement = conn.createStatement(); // 创建statement对象
statement.executeUpdate(sql);
// System.out.println(sql);
System.out.println("SQL执行成功");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtils.closeSource(rs, statement, conn);
System.out.println("资源关闭成功");
}
}
// 使用preparedStatement对象进行更新
public static void updateDataUsePS(String sql, Object... args) {
// 获取连接
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConnection();// 获得连接
ps = conn.prepareStatement(sql); // 创建statement对象
// 获取可变参数的值
for (int i = 0; i < args.length; i++) {
ps.setObject(i + 1, args[i]);
}
ps.executeUpdate();
// System.out.println(sql);
System.out.println("SQL执行成功");
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JDBCUtils.closeSource(null, ps, conn);
System.out.println("资源关闭成功");
}
}
}