JDBC操作数据库

时间:2022-09-12 15:16:40
package com.lxz;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class StringAndDate2 {
// 创建一个以JDBC连接数据库的方法
public ResultSet getResultSet(String sql) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
String url = "jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8";
String user = "root";
String password = "123456";
try {
// 1.加载驱动类
Class.forName("com.mysql.jdbc.Driver");
// 或 new com.mysql.jdbc.Driver();
// 2.创建连接
conn = DriverManager.getConnection(url, user, password);
// 3.创建PreparedStatement对象
// 要执行sql语句,必须获得java.sql.Statement实例,Statement实例分为以下三种
// (1)执行静态sql语句。通常通过Statement实例实现
// Statement stmt = conn.createStatement();
// (2)执行动态sql语句。通常通过PreparedStatement实例实现
// PreparedStatement ps = conn.prepareStatement(sql);
// (3)执行数据库存储过程。通常通过CallableStatement实例实现
// CallableStatement cs = conn.prepareCall("{CALL demoSp(?,?)}");
ps = conn.prepareStatement(sql);
// 4.执行sql语句
// Statement接口提供了三种执行sql语句的方法,executeQuery,executeUpdate,execute
// (1) ResultSet executeQuery(String sqlString):执行查询数据库的SQL语句,返回一个
// ResultSet对象
// ResultSet rs = ps.executeQuery("SELECT * FROM ...");
// (2) int executeUpdate(String
// sqlString):用于执行INSERT/UPDATE/DELETE语句以及
// sql DDL语句,如: CREATE TABLE和DROP TABLE等
// int rows = ps.executeUpdate("INSERT INTO ...");
// (3) execute(sqlString):用于执行返回多个结果集、多个更新或二者组合的语句
// boolean flag = ps.execute(String sql);
rs = ps.executeQuery();
// 5.处理结果
// (1) 执行更新等操作返回的是本次操作影响到的记录数
// (2) 执行查询返回的结果是一个ResultSet对象
// ResultSet包含sql语句中条件的所有行,通过get进行访问
// while(rs.next()){
// String name = rs.getString("name");
// String pwd = rs.getString(1); //比较高效,从左右到编号,从1开始
// }
} catch (ClassNotFoundException e) {
System.out.println("找不到驱动类");
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 5.关闭jdbc对象
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return rs;
}

// PreparedStatement与Statement的区别?
// 1.代码的可读性和可维护性
// stmt.executeUpdate("insert into tb_test(col1,col2,col3) values('"+var1+"','"+var2+"','"+var3+"')");
// PreparedStatement
// ps = conn.prepareStatement("insert into tb_test(col1,col2,col3) values(?,?,?)");
// ps.setString(1,var1);
// ps.setString(2,var2);
// ps.setString(3,var3);
// 2.PreparedStatement尽最大提高性能
/*每一种数据库都会尽最大努力对预编译语句提供最大的性能优化,因为预编译语句有可能重复调用,所以语句在被数据库
的编译器编译后,执行代码会被缓存下来,那么下次调用时只要是相同的预编译语句就不需要再编译,只要将参数直接传入编译过的
语句执行代码中(相当于一个函数)就会得到执行,这并不是说只有一个Connection中多次执行的预编译语句被缓存,而是对整个
数据库,只要预编译的语句语法和缓存在匹配,那么在任何时候就可以不需要再次编译而可以直接执行。而statement
的语句中,即使是相同的同一操作,而由于每次操作的数据不同,所以使整个语句相匹配的机会极小,几乎不太可能匹配,比如:
insert into tb_test(col1,col2) values('11','22');
insert into tb_test(col1,col2) values('11','23');
即使是相同操作但因为数据内容不一样,所以整个个语句本身不能匹配,没有缓存语句的意义.事实是没有数据库会对普通语句
编译后的执行代码缓存.这样每执行一次都要对传入的语句编译一次.
当然并不是所以预编译语句都一定会被缓存,数据库本身会用一种策略,比如使用频度等因素来决定什么时候
不再缓存已有的预编译结果.以保存有更多的空间存储新的预编译语句.*/
// 3.提高安全性
// String sql = "select * from tb_test where username='"+username+"' and password='"+password+"'";
// 如果把(' or '1'='1)传入,则会查到所有信息
// 甚至把(';drop table tb_test where '1'='1)传入,而恰恰有些数据库中这样就会执行
// 如果使用预编译语句,则传入的任何内容就不会和原来的语句发生任何匹配的关系.(前提是数据库本身支持预编译)
// 另:执行效率:Statement 采取直接编译 SQL 语句的方式,扔给数据库去执行,而 PreparedStatement 则先将 SQL语句预编译一遍,再填充参数,这样效率会高一些。
// JDK文档说:SQL 语句被预编译并且存储在 PreparedStatement 对象中,其后可以使用该对象高效地多次执行该语句。
// Statement 由于可能需要采取字符串与变量的拼接,很容易进行 SQL注入攻击,而 PreparedStatement 由于是预
// 编译,再填充参数的,不存在 SQL 注入问题。
}