一、可用于操作数据库的三个接口
在 java.sql 包中有 3 个接口分别定义了对数据库的调用的不同方式:
①Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。
②PrepatedStatement:SQL 语句被预编译并存储在此对象中,可以使用此对象多次高效地执行该语句。③CallableStatement:用于执行 SQL 存储过程
二、使用Statement操作数据表
-
通过调用 Connection 对象的 createStatement() 方法创建该对象。该对象用于执行静态的 SQL 语句,并且返回执行结果。
-
Statement 接口中定义了下列方法用于执行 SQL 语句:
int excuteUpdate(String sql):执行更新操作INSERT、UPDATE、DELETE
ResultSet executeQuery(String sql):执行查询操作SELECT
复制代码
-
但是使用Statement操作数据表存在弊端:
问题一:存在拼串操作,繁琐
问题二:存在SQL注入问题
-
SQL 注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的 SQL 语句段或命令如
SELECT name, password FROM user WHERE name='a' OR 1 = ' AND password = ' OR '1' ='1'
从而利用系统的 SQL 引擎完成恶意行为的做法。对于 Java 而言,要防范 SQL 注入,只要用 PreparedStatement(从Statement扩展而来) 取代 Statement 就可以了。
代码展示
statement测试类
:简单模拟登陆操作
public class StatementTest {
// 使用Statement的弊端:需要拼写sql语句,并且存在SQL注入的问题
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
System.out.print("用户名:");
String username = scanner.nextLine();
System.out.print("密码:");
String password = scanner.nextLine();
String sql = "select name,password from user where name = '"+username+
"' AND password ='"+password+"'";
// System.out.println(username);
// "select * from sc where sno = '"+sno+"'"
User user = get(sql);
if(user!=null){
System.out.println("登陆成功");
}else{
System.out.println("用户名不存在或密码错误");
}
}
// 使用Statement实现对数据表的查询操作
public static User get(String sql){
User t = null;
InputStream is =null;
Connection conn =null;
Statement statement =null;
ResultSet rs =null;
try {
is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties properties = new Properties();
properties.load(is);
String url = properties.getProperty("url");
String user = properties.getProperty("user");
String password = properties.getProperty("password");
String driverClass = properties.getProperty("driverClass");
//1、注册驱动
Class.forName(driverClass);
//2、获取连接
conn = DriverManager.getConnection(url, user, password);
// System.out.println(conn);
//3、获取statement对象
statement = conn.createStatement();
//4、执行语句
rs = statement.executeQuery(sql);
// System.out.println(rs);
//5、处理结果集
if (rs.next()) {
t = new User();
// t.setname(rs.getString("name"));
// t.setPassword(rs.getString("password"));
t.setname(rs.getString(1));
t.setPassword(rs.getString(2));
System.out.println(t);
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
if(rs!=null)
rs.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(statement!=null)
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(conn !=null)
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if(is !=null)
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return t;
}
}
复制代码
User类
:用于保存查询得到的信息
public class User {
private String name;
private String password;
public User() {
}
public User(String name, String password) {
super();
this.name = name;
this.password = password;
}
@Override
public String toString() {
return "name [name=" + name + ", password=" + password + "]";
}
public String getname() {
return name;
}
public void setname(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
复制代码
三、使用PreparedStatement代替statement
1、PreparedStatement介绍
- 可以通过调用 Connection 对象的 preparedStatement(String sql) 方法获取PreparedStatement 对象
- PreparedStatement 接口是 Statement 的子接口,它表示一条预编译过的 SQL 语句
- PreparedStatement 对象所代表的 SQL 语句中的参数用问号(?)来表示,调用 PreparedStatement 对象的setXxx() 方法来设置这些参数. setXxx() 方法有两个参数,第一个参数是要设置的 SQL 语句中的参数的索引(从 1开始),第二个是设置的 SQL 语句中的参数的值
2、PreparedStatement vs Statement
-
代码的可读性和可维护性。
-
PreparedStatement 能最大可能提高性能:
-
DBServer会对预编译语句提供性能优化。因为预编译语句有可能被重复调用,所以语句在被DBServer的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编译,只要将参数直接传入编译过的语句执行代码中就会得到执行。
-
在statement语句中,即使是相同操作但因为数据内容不一样,所以整个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句编译后的执行代码缓存。这样每执行一次都要对传入的语句编译一次。
-
(语法检查,语义检查,翻译成二进制命令,缓存)
-
-
PreparedStatement 可以防止 SQL 注入
3、Java与SQL对应数据类型转换表
4、使用PreparedStatement实现增删改查操作
JDBCUtiles类
:里面存放连接数据库通用的代码段
public class JDBCUtils {
/**
* 获取连接
*/
public static Connection getConnection() throws Exception {
//1.加载配置文件
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("jdbc.properties");
Properties pros = new Properties();
pros.load(is);
//2.读取配置信息
String user = pros.getProperty("user");
String password = pros.getProperty("password");
String url = pros.getProperty("url");
String driverClass = pros.getProperty("driverClass");
//3.加载驱动
Class.forName(driverClass);
//4.获取连接
Connection conn = DriverManager.getConnection(url,user,password);
return conn;
}
/**
* 关闭资源
*/
public static void closeResource(Connection conn, Statement statement){
try {
if (statement != null)
statement.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
try {
if (conn != null)
conn.close();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
}
复制代码
PreparedStatementTest类
:实现增删改操作
public class PreparedStatementTest {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("请输入用户名:");
String username = scan.nextLine();
System.out.print("请输入密码:");
String password = scan.nextLine();
Insert(username,password);
}
public static void Insert(String username,String userpassword){
Connection connection = null;
PreparedStatement ps = null;
try {
connection =JDBCUtils.getConnection();
String sql = "insert into user values(?,?)";
ps = connection.prepareStatement(sql);
ps.setString(1, username);
ps.setString(2, userpassword);
ps.execute();
} catch (Exception e) {
e.printStackTrace();
} finally {
JDBCUtils.closeResource(connection,ps);
}
}
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END