JDBC: 最差实战-最佳实战-模板方法

来源:互联网 发布:双色球 破解 大数据 编辑:程序博客网 时间:2024/05/20 20:17

程序 :  写一个 JDBC 程序, 要求能对数据库信息进行读取: :

 

一: 最差实战:  yuqing 数据库的 pet 表中读取两条信息.:

 

. 思路:

要读去数据库的信息,我们必须让我们的程序先与数据库建立连接, 所以

(1). 创建一个Connection 对象,该对象负责去与数据库建立连接,在这里我们用的是Mysql,呢我们就查看 MySql-JDBC Reference:  Mysqlurl格式如下:

 

jdbc:mysql://[host][,failoverhost...][:port]/[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]

   看的眼是不是有点花啊,呵呵,我们不需要呢么麻烦: 我们可以这样来:

 

Connection  conn  = DriverManager.getConnection("jdbc:mysql://127.0.0.1/yuqing","root","");

 这里解释一下本人为什么把上面写成 127.0.0.1 而不写 localhost, 本人认为这样是一个不错的习惯,  因为在做 WEB 开发的时候如果你的浏览器设置了代理,一定要小心: 要用 127.0.0.1 ,而不要用 localhost ! 因为你使用localhost 的话,访问localhost 将不再是访问本机了.

 

(2) 取得一个连接后,我们是不是该让这个连接和我们的程序之间架一个桥了   ?

:我们知道了上面有了一个 Connection 对象了,我们查看 API Collection :

它有一个这样的方法:

createStatement() : 范围类型 :  Statement
          Creates a
Statement object for sending SQL statements to the database.

所以我们就知道这就是我们要架的桥,我们的程序靠它来给我们向数据库发送 SQL 语句了.所以:

 Statement stmt = conn.createStatement();

 

(3).桥也架好了,接下来就要我们通过这个桥发送 SQL 语句了,查看 API 文档Statement :

executeQuery(String sql)  返回类型:esultSet
          Executes the given SQL statement, which returns a single
ResultSet object

我们知道这就是我们要的家伙了:---( 我们这里指的是查询 )

所以:

ResultSet rs= stmt.executeQuery("SELECT * FROM pet");      

 

我们这里只是查询,所以是executeQuery(String sql),要是更新可以用executeUpdate(String sql).但是它的返回类型是 int  !

 

(4). 我们在上面又得到了一个结果集.当然想看看自己的查询结果吧.有什么好的方法呢?这里我们又查看 API 的 ResultSet 接口:

next()
          Moves the cursor down one row from its current position.

呵呵,看到了吧,可以 while( rs.next() ) 让它一直都移动我们的游标,来显示我们的结果.这里我们只选择两条记录所以:

while(rt.next())

              {           

                     System.out.printf("%s:%s/n",rt.getString(1),rt.getString(2));

              }

(5). OK,搞定了 !

               搞定了吗 ? 当然不是,我们在前面建立了Connection 连接,架了桥.这里当然要 close 掉啊 !所以

            rt.close();

              stmt.close();

              conn.close();

这里,顺序一定不要反啊,想想如果没了连接,去哪架桥去,没了桥,通过什么查询结果去  ?

 

. 思路有了,呢就开始 coding 吧 !

 

package cn.pqcc2000;

import java.sql.*;

 

public class JdbcDemo

{

       public static void main(String args[])throws Exception

       {

 

// Class.forName(---) 是在运行的时候加载 Driver 类,这样我们就不需要在运行的时候 //java –Djdbc.derivers = com.mysql.jdbc.Driver

               Class.forName("com.mysql.jdbc.Driver");

 

Connection  conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1/yuqing","root","");

              Statement stmt = conn.createStatement();

              ResultSet rt= stmt.executeQuery("SELECT * FROM pet");       

              while(rt.next())

              {           

                     System.out.printf("%s:%s/n",rt.getString(1),rt.getString(2));

              }

             

              rt.close();

              stmt.close();

              conn.close();

             

       }

}

哈哈,这样的程序出来是不是自己觉得比较满意啊  ? 但是想想有没有什么问题呢 ?

 

 

思考:

1.     如果将来我的程序查询的数据库变了,主机变了,用户名变了,该怎么办 ?

2.     我们的异常这样处理合适吗?如果我们呢的程序在 Statement stmt = conn.createStatement(); 的时候出现异常了,也就是说我们的桥没有架设好,呢么 Result rt == null ,如果我再 rt.close( ),  呢么就会有空指针异常,我们的程序提前退出,我们的 conn.close() 就没有调用 ..所以,我们这里要捕捉异常.并在 close()的时候判断 != null .而且无论如何我们都要 close 掉这些资源.所以应放到 finally中.

有了上面的问题,我们考虑用一个properties 文件来存放我们的资源文件:

JDBC.properties 文件:

jdbc.driver =com.mysql.jdbc.Driver

jdbc.driverType =jdbc:mysql

jdbc.host =127.0.0.1

jdbc.database =yuqing

jdbc.user =root

jdbc.password =

jdbc.sql =SELECT * FROM pet

 

有了这样的一个文件我们该如何把它读取到我们的程序中呢 ? 还是查看 API

 

load(InputStream inStream) 无返回类型
          Reads a property list (key and element pairs) from the input stream

getProperty(String key) 返回类型: String
          Searches for the property with the specified key in this property list.

 

呵呵,这个就是我们要的.

 

呢么我们就开始修改我们上面的程序:

我们要做的两件事情:

(1).读取properties文件:要先 load(InputStream inStream),然后再逐一getProperty(--).

(2) 处理我们的异常

 

修改我们的程序:

package  cn.pqcc2000;

import java.io.FileInputStream;

import java.io.InputStream;

import java.util.Properties;

import java.sql.*;

public class JdbcDemo

{           

       public static void main(String args[]) throws Exception

       {           

         String   KEY_DRIVER = "jdbc.run";

         String   KEY_DRIVER_TYPE = "jdbc.driverType";

         String   KEY_HOST  = "jdbc.host" ;

         String   KEY_DATABASE  = "jdbc.database" ;

         String   KEY_USER  = "jdbc.user" ;

         String   KEY_PASSWORD  ="jdbc.password" ;

     String   KEY_SQL  = "jdbc.sql" ;     

      

     Properties prop = new Properties();

             InputStream ips = new FileInputStream("a.properties");                 

              if(ips == null)

              {

                     throw new IllegalArgumentException("file not find");

              }    

                    

              prop.load(ips);

              ips.close();                  

      

             String  driverType=prop.getProperty(KEY_DRIVER_TYPE);

       String  host=prop.getProperty(KEY_HOST);

             String  database=prop.getProperty(KEY_DATABASE);

       String  user=prop.getProperty(KEY_USER);

             String  password=prop.getProperty(KEY_PASSWORD);

             String  sql=prop.getProperty(KEY_SQL);

             String  run =prop.getProperty(KEY_RUN);

            

              Connection conn = null;

              Statement  stmt = null;

              ResultSet  rs = null;

             

             

               try

               {

                     Class.forName(run);

                     conn = DriverManager.getConnection(driverType+":"+"//"+host+"/" +database,user,password);

                     stmt = conn.createStatement();

                     rs= stmt.executeQuery(sql);

                    

                     while(rs.next())

                     {

                            System.out.printf("%s:%s/n",rs.getString(1),rs.getString(2));

                     }

              }

              catch(Exception e)

              {

                     e.printStackTrace();

              }

             

              finally

              {

                     if(rs != null)          

                            try{rs.close();}catch(Exception ex1){ex1.printStackTrace();}

                     if(stmt != null)

                            try{stmt.close();}catch(Exception ex){ex2.printStackTrace();}

                     if(conn != null)     

                            try{conn.close();}catch(Exception ex3){ex3.printStackTrace();}                   

                    

              }

             

       }

}

 

再思考这样代码好吗 ?如果以后我们要写 JDBC 的程序都要这样在每个程序里面加上这么多的 Connection ,  finally( try , catch )  吗?想想就让人很不爽,这些重复代码我们不希望每次都重复的出现在我们的代码里面,呢么怎么办呢 ? 做网页的时候我们都知道有模板会有很大的方便,呢么我们是不是也可以尝试用模板方法呢?我们先写一个模板,然后我们需要用到同样的程序的时候,我们就继承"模板",然后我们在模板里面只需要添加一些我们 "个性"的代码就 OK 了.

 

修改我们的代码:( 阿门,请宽恕 !时间关系,我在这里没有使用Properties文件)

先写一个模板:它在这里给我们做一些通用的方法,具体的"个性"代码我们到它的子类里面有不同实现.

package cn.pqcc2000;

import java.sql.*;

 

abstract  class JdbcDemo_Parent

{             

              static Statement stmt;

              ResultSet  rs  = null;         

    public     abstract  void doExecute(Statement stmt)throws Exception;    

      

       public void execute(Statement stmt)

       {                  

              Connection conn = null;

             

              try

              {

                     Class.forName("com.mysql.jdbc.Driver");  

                     conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1/yuqing", "root", "");

                     stmt = conn.createStatement();                                                                              doExecute(stmt);               

              }    

              catch(Exception e)

              {

                     e.printStackTrace();

              }           

              finally

              {

                     if(rs != null)          

                            try{rs.close();}catch(Exception ex){}

                     if(stmt != null)

                            try{stmt.close();}catch(Exception ex){}

                     if(conn != null)     

                            try{conn.close();}catch(Exception ex){}                         

              }

             

       }    

 

现在编写我们的主类,这个类要继承"模板"类,并且要重写父类里面doExecute(Statement stmt).开始我们自己"个性"的代码 :

 

package cn.pqcc2000;

import java.sql.*;

 

public class JdbcDemo_Child extends JdbcDemo_Parent

{

                           

       public static void main(String args[])

       {                         

              JdbcDemo_Parent parent = new JdbcDemo_Child();         

              parent.execute(stmt);

       }

                    

       public void doExecute(Statement stmt)throws Exception

       {                  

                            try

                            {                  

                                     rs = stmt.executeQuery("SELECT * FROM pet");  

                                                                    

                                          while(rs.next())

                                     {

                                         System.out.print(rs.toString());

                                           //System.out.printf("%s:%s/n",rs.getString(1),rs.getString(2));

                                     }        

                                     rs.close();

                                     rs = null;    // 最好加上这一句话,防止以后再对 rs 进行引用.

                            }

                            catch(Exception e)       

                            {

                                   e.printStackTrace();

                            }

                           

       }

}

 

看看我们的程序是怎么运做的 :

1.   首先new 一个对象,然后调用父类的 exexute( )方法,该方法去创建Connection

2.   execute()然后调用子类的doExecute(Statement stmt).来执行"个性化"代码

3.   继续回到execute(),处理呢些通用的,异常代码吧!

 

OK 符合要求 !

 

呵呵,我们的"模板"的作用是不是显而易见的.以后我们在写 JDBC 程序,就可以这样子,继承"模板".然后只写一些类似:

rs = stmt.executeQuery("SELECT * FROM pet"); 这样的语句就可以了呢  ?

呵呵 !时间关系,没有使用 properties.

 

不过,模板方法使用的是继承,不如将来改成策略模式,这样的话,在一定程度上减少了我们程序的耦合性!像大师说的 :"要多用组合,而不是继承" !

呵呵!

继续努力 ing !

 
原创粉丝点击