通过对前面代码的分析,会发现以下几个问题:

Url、User、Password直接在代码中定义,如果数据库服务器稍作变动,怎么办?

一个项目基本针对一个底层数据库,难道每次操作数据库,都要注册一次驱动程序嘛?是否可以只注册一次?

获取数据库连接时,每次都需要Url、User、Password,一旦改动其中一个数据,意味着要修改所有此处的代码。

释放资源,每次数据库操作后,都需要释放资源,难道每次操作后都要写三次try close catch代码嘛?


如果要解决上面的几个问题,那么就要对刚才的代码实现封装,并且把数据库的配置放到配置文件(Properties)中,具体做法如下:

新建jdbc.properties,

 Java开发系列--JDBC_封装


内容如下:

[plain] view plain copy

  1. #数据库连接配置  

  2. driverClassName=com.mysql.jdbc.Driver  

  3. url=jdbc:mysql://127.0.0.1:3306/lcma?characterEncoding=utf-8  

  4. user=root  

  5. password=iflytek  


新建一个JdbcUtil类,实现代码如下:

[java] view plain copy

  1. import java.io.InputStream;  

  2. import java.sql.Connection;  

  3. import java.sql.DriverManager;  

  4. import java.sql.ResultSet;  

  5. import java.sql.SQLException;  

  6. import java.sql.Statement;  

  7. import java.util.Properties;  

  8.   

  9. public class JdbcUtil {  

  10.   

  11.     private static String url;  

  12.     private static String user;  

  13.     private static String password;  

  14.       

  15.     static{  

  16.         //使用properties加载属性文件  

  17.         Properties prop = new Properties();  

  18.         try {  

  19.             InputStream is = JdbcUtil.class.getClassLoader().getResourceAsStream("com/iflytek/jdbc.properties");  

  20.             prop.load(is);  

  21.             //注册驱动(获取属性文件中的数据)  

  22.             String driverClassName = prop.getProperty("driverClassName");  

  23.             Class.forName(driverClassName);  

  24.             //获取属性文件中的url,username,password  

  25.             url = prop.getProperty("url");  

  26.             user = prop.getProperty("user");  

  27.             password = prop.getProperty("password");  

  28.         } catch (Exception e) {  

  29.             e.printStackTrace();  

  30.         }  

  31.     }  

  32.       

  33.     //获取数据库连接  

  34.     public static Connection getConnection(){  

  35.         Connection conn = null;  

  36.         try {  

  37.             conn = DriverManager.getConnection(url, user, password);  

  38.         } catch (SQLException e) {  

  39.             e.printStackTrace();  

  40.         }  

  41.         return conn;  

  42.     }  

  43.       

  44.     //释放资源  

  45.     public static void close(Connection conn, Statement stat, ResultSet rs){  

  46.          if(conn != null){  

  47.              try {conn.close();} catch (SQLException e) {e.printStackTrace();}  

  48.          }  

  49.          if(stat != null){  

  50.              try {stat.close();} catch (SQLException e) {e.printStackTrace();}  

  51.          }  

  52.          if(rs != null){  

  53.              try {rs.close();} catch (SQLException e) {e.printStackTrace();}  

  54.          }  

  55.     }  

  56. }  


在加载配置文件的时候使用了静态代码块,表明类一加载,配置文件就会立马加载,属性被保存在静态变量中(url,user,password)。

获取数据库连接和释放资源都采用了静态方法,通过类直接调用改方法,实现了公用代码的封装,降低的代码的耦合性。

这时候我们再来看JDBC获取数据库数据代码:

[java] view plain copy

  1. Connection conn = null;  

  2. Statement stat = null;  

  3. ResultSet rs = null;  

  4. try{  

  5.     //通过JdbcUtil获取数据库链接  

  6.     conn = JdbcUtil.getConnection();  

  7.     stat = conn.createStatement();  

  8.     rs = stat.executeQuery("select * from student");  

  9.     while(rs.next()){  

  10.          System.out.println(rs.getString("name"));  

  11.     }  

  12. }catch(Exception e){  

  13.     e.printStackTrace();  

  14. }finally {  

  15.     //通过JdbcUtil关闭资源  

  16.     JdbcUtil.close(conn, stat, rs);  

  17. }  

通过现在的代码可以看出,代码简介了很多,没有出现容易出错的配置,获取连接,加载配置文件,关闭资源我们也不需要关心,大大降低了代码的耦合性,提高了代码重用性。

封装过后的代码还是有些问题,就是采用了Statement对数据库操作,如果现在SQL语句需要传入变量,只有采用拼接的方式,这样做有很多缺点,例如拼接容易出错或容易产生SQL注入等。

通过PreparedStatement对数据库操作可以解决Statement带来的缺点,PreparedStatement和Statement区别如下:

Statement的缺点:

同样的SQL语句,每次都要发送,不能进行有效的缓存。

拼接SQL字符串非常容易出现错误。

不能防止恶意数据,易产生SQL注入。

升级后的新接口PreparedStatement(推荐):

预编译SQL语句,并进行有效的缓存,性能更好。

允许使用问号占位符参数,并且该参数必须获得值后才可以执行。

无需拼接SQL语句。

问号占位符参数:INSERTINTO User(id,name,age,birthday)VALUES(?,?,?,?); 

来看一下通过PreparedStatement对数据库操作的代码:

[java] view plain copy

  1. Connection conn = null;  

  2. PreparedStatement stat = null;  

  3. ResultSet rs = null;  

  4. try{  

  5.         //通过JdbcUtil获取数据库链接  

  6.     conn = JdbcUtil.getConnection();  

  7.     stat = conn.prepareStatement("select * from student where name like ? and age = ? ");  

  8.     stat.setString(1"%小%");  

  9.     stat.setInt(222);  

  10.     rs = stat.executeQuery();  

  11.     while(rs.next()){  

  12.            System.out.println(rs.getString("name"));  

  13.     }  

  14.     }catch(Exception e){  

  15.            e.printStackTrace();  

  16.     }finally {  

  17.         //通过JdbcUtil关闭资源  

  18.         JdbcUtil.close(conn, stat, rs);  

  19.     }  

  20. }  


注意以下两点:


1.问号占位符不能加引号。

2.占位符参数设置值从下标从1开始。


转载url:http://blog.csdn.net/mlc1218559742/article/details/52216895