1. 创建一个获取Connection对象和关闭资源的工具类
在对数据库进行CRUD(①查询数据、②数据插入、③数据修改、④数据删除)操作的时候,每一个操作都需要获取Connection对象,所以我们就可以把获取Connection对象的过程抽离到一个工具类当中,下面是具体代码。
public final class JdbcUtil {
private JdbcUtil() {
}
private static String url = "jdbc:oracle:thin:@127.0.0.1:1521:ORCL";
private static String user = "scott";
private static String password = "tiger";
// 通过静态代码块加载驱动类
static {
try {
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch (ClassNotFoundException e) {
throw new ExceptionInInitializerError("加载驱动类出错!!");
}
}
// 获取连接对象
public static Connection getConnection() throws Exception {
Connection connection = null;
connection = DriverManager.getConnection(url, user, password);
return connection;
}
// 关闭资源
public static void close(Connection connection, ResultSet rs, Statement statement) {
if (rs != null) {
try {
rs.close();
}
catch (SQLException e) {
e.printStackTrace();
}
finally {
if (statement != null) {
try {
statement.close();
}
catch (SQLException e) {
e.printStackTrace();
}
finally {
if (connection != null) {
try {
connection.close();
}
catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
我把url,username,password放在了类中,也可以将这些配置信息放入到配置文件中,一般的做法是放入到配置文件当中,此处就简单些。将加载驱动类的方法放入到static静态代码块当中,当调用getConnection静态方法的时候,static静态代码块会先执行,即会先加载驱动类。close()方法就是关闭Statement,Connection,ResultSet对象的资源。
2. 使用Statement对象和ResultSet对象进行简单CRUD(增删改查)操作
首先看一下Statement接口的文档说明:
用于执行静态SQL语句并返回它所生成的结果的对象。
在默认情况下,同一时间每个Statement对象在只能打开一个ResultSet对象。因此,如果读取一个ResultSet对象与读取另一个交叉,则这两个对象必须是由不同的Statement对象生成的。如果存在某个语句的打开的当前ResultSet对象,则Statement接口中的所有执行方法都会隐式关闭它。
Statement的主要作用就是执行SQL语句并且返回它所生产的结果对象。Statement对象是通过Connection对象进行获取的,通过Connection.createStatement()方法获取Statement对象。通过执行Statement对象的executeQuery()方法进行查询SQL,该语句返回单个ResultSet 对象。
下面是简单的代码示例:
public void read(String id, String password) {
Connection connection = null; // 初始化一个连接对象
Statement statement = null; // 初始化一个语句对象
ResultSet resultSet = null; // 初始化一个结果集对象
try {
connection = JdbcUtil.getConnection();
statement = connection.createStatement();
resultSet = statement.executeQuery("select id, name from student where id = '" + id + "' and password = '" + password + "'");
while (resultSet.next()) {
System.out.println("id = " + resultSet.getInt("id") + ", name = " + resultSet.getString("name"));
}
} catch(SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.close(connection, resultSet, statement);
}
}
模拟了一个简单的查询用户信息的SQL,传入id和password对数据库进行查询,然后输出。SQL语句是通过传入的值拼接而成,所以这样就很容易被SQL注入。当我传入的password值为' or 1 = 1 or '的时候打印出来SQL语句如下:
select id, name from student where id = 'rcx' and password = '' or 1 = 1 or ''
因此就可以查询到用户的信息,引起不安全的漏洞。一般带参数的查询都需要使用PreparedStatement对象。
3. 使用PreparedStatement对象(即预处理语句对象)和ResultSet对象进行简单CRUD(增删改查)操作
首先看一下PreparedStatement接口,它继承自Statement接口。PreparedStatement对象(即预处理语句对象)表示预编译的SQL语句。SQL语句被预编译并存储在PreparedStatement对象中。然后可以使用此对象多次高效地执行该SQL语句。预处理语句对象是Connection对象(即连接对象)通过调用prepareStatement(sql)方法来获取的,传入的参数是还未预编译的SQL语句(即原始的SQL语句),但是该SQL语句的特殊之处在于参数部分是用?来代替。2中的SQL语句的例子通过PreparedStatement类实现的代码如下:
public void read1(String id, String password) {
Connection connection = null;
PreparedStatement pstmt = null;
ResultSet resultSet = null;
try {
connection = JdbcUtil.getConnection();
// 下面这条SQL语句是预编译语句类的核心,该SQL语句不是通过传入的值拼接而成。
String sql = "select id, name from student where id = ? and password = ?";
pstmt = connection.prepareStatement(sql);
pstmt.setString(1, id);
pstmt.setString(2, password);
// 该方法是不带参数的,否则执行的不是预处理(即预编译)的SQL语句
resultSet = pstmt.executeQuery();
while (resultSet.next()) {
System.out.println("id = " + resultSet.getInt("id") + ", name = " + resultSet.getString("name"));
}
} catch(SQLException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
JdbcUtil.close(connection, resultSet, pstmt);
}
}
因为PreparedStatement对象中包含的是预处理SQL语句,所以可以有效地防止SQL注入的问题,同时还可以提高一些效率。
注意:
resultSet = pstmt.executeQuery();
由于PreparedStatement接口继承自Statement接口,所以也有executeQuery(sql)带参数的方法,如果这样写的话那么执行的就是父类接口当中的方法了,则执行的不是预处理的SQL语句。
4. 一些其他的方法
由于执行数据查询的语句是通过调用ResultSet对象的executeQuery()方法来实现的,在插入数据、更新数据、删除数据的操作是通过调用executeUpdate(SQL)方法来实现的。所以执行给定的SQL语句,该语句可能为INSERT(插入数据)、UPDATE(修改数据)或DELETE(删除数据)语句,或者不返回任何内容的SQL语句(如SQL DDL语句)。
ResultSet对象的next()方法:将光标从当前位置向前移一行。ResultSet光标最初位于第一行之前;第一次调用next()方法使第一行成为当前行;第二次调用使第二行成为当前行,依此类推。
完整的CRUD代码:
public class CRUD {
public static void main(String[] args) throws SQLException {
read();
// create();
// update();
// delete();
}
// 数据查询
static void read() throws SQLException {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
// 2.建立连接,获取连接对象
conn = JdbcUtils.getConnection();
// conn = JdbcUtilsSing.getInstance().getConnection();
// 3.创建语句,此处即SQL语句
st = conn.createStatement();
// 4.执行语句,数据查询语句
rs = st.executeQuery("select id, name, money, birthday from user");
// 5.处理结果
while (rs.next()) {
System.out.println(rs.getObject("id") + "\t"
+ rs.getObject("name") + "\t"
+ rs.getObject("birthday") + "\t"
+ rs.getObject("money"));
}
} finally {
JdbcUtils.free(rs, st, conn);
}
}
// 插入数据
static void create() throws SQLException {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
// 2.建立连接
conn = JdbcUtils.getConnection();
// conn = JdbcUtilsSing.getInstance().getConnection();
// 3.创建语句
st = conn.createStatement();
String sql = "insert into user(name,birthday, money) values ('name1', '1987-01-01', 400) ";
// 4.执行语句
int i = st.executeUpdate(sql);
System.out.println("i=" + i);
} finally {
JdbcUtils.free(rs, st, conn);
}
}
// 修改数据
static void update() throws SQLException {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
// 2.建立连接
conn = JdbcUtils.getConnection();
// conn = JdbcUtilsSing.getInstance().getConnection();
// 3.创建语句
st = conn.createStatement();
String sql = "update user set money=money+10 ";
// 4.执行语句
int i = st.executeUpdate(sql);
System.out.println("i=" + i);
} finally {
JdbcUtils.free(rs, st, conn);
}
}
// 删除数据
static void delete() throws SQLException {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
// 2.建立连接
conn = JdbcUtils.getConnection();
// conn = JdbcUtilsSing.getInstance().getConnection();
// 3.创建语句
st = conn.createStatement();
String sql = "delete from user where id>4";
// 4.执行语句
int i = st.executeUpdate(sql);
System.out.println("i=" + i);
} finally {
JdbcUtils.free(rs, st, conn);
}
}
}
来源:oschina
链接:https://my.oschina.net/u/614348/blog/682243