1. 建立一个获取Connection对象和关闭资源的工具类java
在对数据库进行CRUD(①查询数据、②数据插入、③数据修改、④数据删除)操做的时候,每个操做都须要获取Connection对象,因此咱们就能够把获取Connection对象的过程抽离到一个工具类当中,下面是具体代码。sql
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接口的文档说明:oracle
用于执行静态SQL语句并返回它所生成的结果的对象。工具
在默认状况下,同一时间每一个Statement对象在只能打开一个ResultSet对象。所以,若是读取一个ResultSet对象与读取另外一个交叉,则这两个对象必须是由不一样的Statement对象生成的。若是存在某个语句的打开的当前ResultSet对象,则Statement接口中的全部执行方法都会隐式关闭它。url
Statement的主要做用就是执行SQL语句而且返回它所生产的结果对象。Statement对象是经过Connection对象进行获取的,经过Connection.createStatement()方法获取Statement对象。经过执行Statement对象的executeQuery()方法进行查询SQL,该语句返回单个ResultSet 对象。spa
下面是简单的代码示例:code
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); } } }