<2006年6月>
          28293031123
          45678910
          11121314151617
          18192021222324
          2526272829301
          2345678

          統(tǒng)計(jì)

          • 隨筆 - 27
          • 文章 - 0
          • 評(píng)論 - 29
          • 引用 - 0

          留言簿(3)

          隨筆分類(lèi)

          關(guān)注Blog

          最新評(píng)論

          閱讀排行榜

          jsp中的數(shù)據(jù)庫(kù)編程
          最近好久沒(méi)上過(guò)BLOG了,前段時(shí)間實(shí)在是很忙啊。以前兩年半的時(shí)間都沒(méi)這么忙過(guò)呢~~~
          今天上網(wǎng)看到一篇文章就轉(zhuǎn)過(guò)來(lái),大家一起分享下。前些時(shí)間我在研究JSP中的數(shù)據(jù)庫(kù)連接,費(fèi)了好大的勁,做了好多天,終于連接上了,辛苦啊,先喝杯酒慶祝一下,CHEERS.................現(xiàn)在就轉(zhuǎn)帖了
          [轉(zhuǎn)]
          二,JDBC?主要接口:
          java.sql.DriverManager類(lèi)用于處理驅(qū)動(dòng)程序的調(diào)入并且對(duì)新的數(shù)據(jù)庫(kù)連接提供支持。
          java.sql.Connection,指應(yīng)用程序與特定數(shù)據(jù)庫(kù)的連接。
          java.sql.Statement,用于一般sql語(yǔ)句的執(zhí)行(可以是查詢(xún)、更新甚至可以創(chuàng)建數(shù)據(jù)庫(kù)的執(zhí)行過(guò)程)
          java.sql.ResultSet,查詢(xún)所返回的結(jié)果保存在此對(duì)象中,用它可以瀏覽和存取數(shù)據(jù)庫(kù)內(nèi)的記錄。

          1,通過(guò)jdbc-odbc橋使用odbc數(shù)據(jù)庫(kù)(并不需要jdbc?Drivers)

          先在odbc?DSN(Data?Source?Name)設(shè)置處設(shè)置pubs?sysDSN,sa為username,密碼為空
          Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");//加載驅(qū)動(dòng)程序
          con=DriverManager.getConnection("jdbc:odbc:pubs","sa","");//jdbc:odbc:pubs
          con.close();
          //應(yīng)當(dāng)catch?ClassNotFoundException和SQLException

          Connection的getWarning方法返回一個(gè)SQLWarning對(duì)象,在連接之前應(yīng)當(dāng)先檢查。
          使用jdbc-odbc的最大好處是:免費(fèi)的。但是性能受odbc的限制,而且一般odbc驅(qū)動(dòng)比較昂貴。
          2,使用專(zhuān)門(mén)的jdbc驅(qū)動(dòng)程序。//此處是mm?jdbc?Driver
          先將jar文件放在ClassPath里面。
          Class.forName("org.gjt.mm.mysql.Driver");
          con=DriverManager.getConnection("jdbc:mysql://localhost:3306/dbname","root","");
          con.close();

          可見(jiàn)使用何種方式連接何種數(shù)據(jù)庫(kù)與數(shù)據(jù)庫(kù)的操作和連接數(shù)據(jù)庫(kù)是無(wú)關(guān)的。
          三,查詢(xún)數(shù)據(jù)庫(kù)
          Statement?stmt=con.createStatement();
          stmt.setMaxRows()可以控制輸出記錄最大數(shù)量;
          ResultSet?rs=stmt.executeQuery("select?.....");

          ResultSet指向當(dāng)前記錄:
          int?userId=rs.getInt("userid");
          String?userName=rs.getString("username");
          ...或者用序號(hào)(從1開(kāi)始的)
          int?userId=rs.getInt(1);
          Stirng?userName=rs.getString(2);

          ClassNotFoundException是由于Class.forName()無(wú)法載入jdbc驅(qū)動(dòng)程序觸發(fā)的
          SQLException是jdbc在執(zhí)行過(guò)程中發(fā)生問(wèn)題時(shí)產(chǎn)生。有一個(gè)額外的方法getNextException()
          catch(SQLException?e){
          out.println(e.getMessage());
          while(e=e.getNextException()){
          out.println(e.getMessage());
          }
          }

          一般來(lái)說(shuō)并不建議在jsp中編寫(xiě)數(shù)據(jù)庫(kù)的訪問(wèn)程序,可以將數(shù)據(jù)庫(kù)的訪問(wèn)封裝在一個(gè)javabean中。
          四,ResultSet深入
          1,ResultSetMetaData
          ResultSet?rs=stmt.executeQuery("select....");
          ResultSetMetaData?rsmd=rs.getMetaData();?//獲取ResultSetMateData對(duì)象
          int?numberOfColumns=rsmd.getColumnCount();//返回列數(shù)
          boolean?b=rsmd.isSearchable(int?i);//返回第i列是否可以用于where子句
          String?c=rsmd.getColumnLabel(int?i);//獲取第i列的列標(biāo)
          Objcet?obj=rs.getObject();
          if(obj!=null)out.println(obj.toString());
          else?println("");
          2,SQL類(lèi)型與ResultSet的getObject返回類(lèi)型及對(duì)應(yīng)的XXX?getXXX()方法
          SQL類(lèi)型?JSP類(lèi)型?對(duì)應(yīng)的getXXX()方法
          ————————————————————————————————————————————
          CHAR?String?String?getString()
          VARCHAR?String?String?getString()
          LONGVARCHAR?String?InputStream?getAsciiStream()/getUnicodeStream()
          NUMERIC?java.math.BigDecimal?java.math.BigDecimal?getBigDecimal()
          DECIMAL?同上
          BIT?Boolean?boolean?getBoolean()
          TINYINT?Integer?byte?getByte()
          SMALLINT?Integer?short?getShort()
          INTEGER?Integer?int?getInt()
          BIGINT?Long?long?getLong()
          REAL?Float?float?getFloat()
          FLOAT?Double?double?getDouble()
          DOUBLE?Double?double?getDouble()
          BINARY?byte[]?byte[]?getBytes()
          VARBINARY?byte[]?byte[]?getBytes()
          LONGVARBINARY?byte[]?InputStream?getBinaryStream()
          DATE?java.sql.Date?java.sql.Date?getDate()
          TIME?java.sql.Time?java.sql.Time?getTime()
          TIMESTAMP?java.sql.Timestamp?java.sql.Timestamp?getTimestamp()

          3,null
          int?i=rs.getInt("age");
          if(!rs.wasNull())....//RecordSet::wasNull()用來(lái)檢查null
          4,存取大字符串和二進(jìn)制文本
          對(duì)于數(shù)據(jù)庫(kù)中l(wèi)ongvarchar和langvarbinary進(jìn)行流操作
          ResultSet?rs=stmt.executeQueryString("select?...");
          BufferedReader?br=new?BufferedReader(new?InputStream(rs.getAsciiStream("vol1")));//長(zhǎng)文本串
          BufferedReader?br=new?BufferedReader(new?InputStream(rs.getUnicodeStream("vol1")));
          BufferedReader?br=new?BufferedReader(new?InputStream(rs.getBinaryStream("vol2")));//長(zhǎng)二進(jìn)制文本
          //取數(shù)據(jù)必須在rs.getAsciiStream(),?rs.getUnicodeStream(),?rs.getBinaryStream()等之后馬上進(jìn)行


          五,瀏覽ResultSet
          1,JDBC2.0提供了更多瀏覽ResultSet的方法
          首先,確定你的jdbc驅(qū)動(dòng)程序支持jdbc2.0
          其次,由Connection生成Statement時(shí)要指定參數(shù)
          Statement?stmt=con.getStatement("游標(biāo)類(lèi)型",?"記錄更新權(quán)限");
          游標(biāo)類(lèi)型:
          ResultSet.TYPE_FORWORD_ONLY:只可以向前移動(dòng)
          ResultSet.TYPE_SCROLL_INSENSITIVE:可卷動(dòng)。但是不受其他用戶對(duì)數(shù)據(jù)庫(kù)更改的影響。
          ResultSet.TYPE_SCROLL_SENSITIVE:可卷動(dòng)。當(dāng)其他用戶更改數(shù)據(jù)庫(kù)時(shí)這個(gè)記錄也會(huì)改變。
          記錄更新權(quán)限:
          ResultSet.CONCUR_READ_ONLY,只讀
          ResultSet.CONCUR_UPDATABLE,可更新

          getStatement()缺省參數(shù):getStatement(ResultSet.TYPE_FORWORD_ONLY,?ResultSet.CONCUR_READ_ONLY)
          2,如果ResultSet是可卷動(dòng)的,以下函數(shù)可以使用:
          rs.absolute()//絕對(duì)位置,負(fù)數(shù)表示從后面數(shù)
          rs.first()第一條
          rs.last()最后一條
          rs.previoust()前一條
          rs.next()后一條
          rs.beforeFirst()第一條之前
          rs.afterLast()最后之后
          rs.isFirst(),rs.isLast(),rs.isBeforeFirst(),rs.isAfterLast
          注意,剛打開(kāi)的時(shí)候是處于第一條記錄之前的

          六,更新數(shù)據(jù)庫(kù)
          1,stmt.executeUpdate("strSql"),strSql是一條sql更新語(yǔ)句。update,insert,delete返回影響到的條數(shù)
          2,stmt.execute()方法在不知道sql語(yǔ)句是查詢(xún)還是更新的時(shí)候用。如果產(chǎn)生一條以上的對(duì)象時(shí),返回true,此時(shí)可用?stmt.getResultSet()和stmt.getUpdateCount()來(lái)獲取execute結(jié)果,如果不返回ResultSet對(duì)象則返回false.
          3,除了Statement的executeUpdate之外還可以用ResultSet:
          rs.updateInt(1,10);
          rs.updateString(2,"sfafd");
          rs.updateRow();

          七,使用預(yù)編譯PreparedStatement
          PreparedStatement對(duì)象和Statement對(duì)象類(lèi)似,都可以用來(lái)執(zhí)行SQL語(yǔ)句。不同在于,數(shù)據(jù)庫(kù)會(huì)對(duì)PreparedStatement的SQL語(yǔ)句進(jìn)行預(yù)編譯,而且仍舊能輸入?yún)?shù)并重復(fù)執(zhí)行編譯好的查詢(xún)速度比未編譯的要快。
          PreparedStatement?stmt=con.preparedStatement("Insert?Into?users(userid,?username)?values(?,?)");
          stmt.clearParameters();
          stmt.setInt(1,2);
          stmt.setString(2,"Big");
          stmt.executeUpdate();

          八,執(zhí)行存儲(chǔ)過(guò)程
          1,JDBC調(diào)用存儲(chǔ)過(guò)程,并使用存儲(chǔ)過(guò)程的返回值。這樣可以將處理工作分為服務(wù)端和客戶端兩部分,并大大加快系統(tǒng)的設(shè)計(jì)和開(kāi)發(fā)的時(shí)間。比如可以重復(fù)使用服務(wù)器上的組件。使用存儲(chǔ)過(guò)程之后大量諸計(jì)算工作可以交給數(shù)據(jù)庫(kù)服務(wù)器來(lái)處理,這將降低Web服務(wù)器的負(fù)載,從而提高整個(gè)系統(tǒng)的性能。
          2,有兩個(gè)表UserMain{UserID,UserName,UserType},UserRef{BrefID,?UserID,?UserBrief}
          下面的存儲(chǔ)過(guò)程可以接受jdbc傳來(lái)的參數(shù),新增內(nèi)容到UserMain和UserRef,并輸出一個(gè)OutUserID.
          CREATE?PROCEDURE?ap_adduser
          (
          @OutUserID?int?output,?//此為輸出參數(shù),output標(biāo)記
          @UserName?varchar(25),?//參數(shù)表示方法:"@XXX"為變量名,"變量名?類(lèi)型?[output]"
          @UserType?tinyint,
          @UserBrief?varchar(255),
          )
          AS
          Declare?@UserID?int?//定義局部變量
          insert?into?UserMain(UserName,?UserType)
          values(@UserName,@UserType)
          select?@UserID=@@IDENTITY?//賦值用select,此處自動(dòng)獲得ID
          insert?into?UserRef(UserID,?UserBrief)
          select?@OutUserID=@UserID
          GO/*結(jié)束,基本結(jié)構(gòu):
          CREATE?PROCEDURE?procedureName(
          parameters
          )
          AS
          actions
          GO
          */


          JSP頁(yè)面中這樣使用:
          CallableStatement?stmt=con.prepareCall("{call?ap_adduser(?,?,?,?)}");
          stmt.registerOutParameter(1,Types.INTEGER,1);//注冊(cè)輸出變量
          stmt.setString(2,"edmund");
          stmt.setInt(3,1);
          stmt.setString(4,"description");
          stmt.execute();
          int?userid=stmt.getInt(1);
          stmt.close()

          八,使用事務(wù)
          1,事務(wù)中的操作是一個(gè)整體,要么都執(zhí)行成功要么都不成功:事務(wù)開(kāi)始后,如果所有的改變都正確,則使用commit方法將這些動(dòng)作全部存入數(shù)據(jù)庫(kù),否則就使用rollback取消所有的改變動(dòng)作,而這時(shí)數(shù)據(jù)庫(kù)中的數(shù)據(jù)和執(zhí)行事務(wù)前的是相同的。
          2,使用事務(wù)時(shí)應(yīng)當(dāng)先用?con.setAutoCommit(false),最后使用commit或者rollback
          3,rollback一般在catch段執(zhí)行
          九,數(shù)據(jù)庫(kù)連接池
          1,如果有一個(gè)數(shù)據(jù)庫(kù)連接請(qǐng)求并且連接中沒(méi)有連接,則生成一個(gè)新的連接。這個(gè)連接使用完之后并不關(guān)閉它,而是將它放入連接池。在這個(gè)過(guò)程中,還要判斷連接池中的連接是否超期。如果超期則將它關(guān)閉。
          2,有很多已有的Connection?Pool包可以使用。
          3,一般將Connection?Pool作為一個(gè)application作用域的變量使用
          <jsp:useBean?id="pool"?scope="application"?class="javastart.tools.ConnectionPool"?/>
          <%@page?import="java.sql.*"%>
          <%@page?import="javastart.tools.*"%>
          <!--javastart.tools是你的Connection?Pool所在的地方-->
          DBConnection?con=null;
          try{
          con=pool.getConnection("sun.jdbc.odbc.JdbcOdbcDriver","jdbc:odbc:access","","");
          Statement?stmt=con.createStatement();
          stmt.setMaxRows(10);
          String?query=request.getParameter("quey");
          ResultSet?rs=stml.executeQuery(query);
          ResultSetMetaData?rsmd=rs.getMetaData();
          }
          .....
          finally{
          pool.releaseConnection(con);
          }

          也可以使用一個(gè)Servlet初始化連接池

          posted on 2006-06-15 10:59 牛浪de流 閱讀(369) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): 爪哇學(xué)習(xí)

          主站蜘蛛池模板: 徐闻县| 泊头市| 莱西市| 格尔木市| 定西市| 星子县| 武乡县| 开江县| 陆良县| 鄂伦春自治旗| 怀集县| 吉木乃县| 阜城县| 建昌县| 乌兰浩特市| 宜宾市| 灵川县| 濉溪县| 县级市| 衡南县| 安徽省| 神木县| 汕尾市| 湖州市| 荔波县| 安仁县| 裕民县| 金堂县| 阿尔山市| 长武县| 舒兰市| 泾阳县| 买车| 蕲春县| 宜宾市| 布尔津县| 印江| 西和县| 兴海县| 玛纳斯县| 德化县|