JSP中SQL數(shù)據(jù)庫編程技術(shù)
發(fā)表時間:2024-06-12 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]一,SQL復(fù)習(xí) 1,SQL語句分為兩類:DDL(Data Definition Language)和DML(Dat Manipulation Languge,數(shù)據(jù)操作語言)。前者主要是定義數(shù)據(jù)邏輯結(jié)構(gòu),包括定義表、視圖和索引;DML主要是對數(shù)據(jù)庫進行查詢和更新操作。 2,Create Table(...
一,SQL復(fù)習(xí)
1,SQL語句分為兩類:DDL(Data Definition Language)和DML(Dat Manipulation Languge,數(shù)據(jù)操作語言)。前者主要是定義數(shù)據(jù)邏輯結(jié)構(gòu),包括定義表、視圖和索引;DML主要是對數(shù)據(jù)庫進行查詢和更新操作。
2,Create Table(DDL):
Create Table tabName(
colName1 colType1 [else],
colName2 colType2 [else],
...,
colNamen colTypen [else]
);
例如:Cteate Table pJoiner(
pno char(6) not null,
eno char(6) nut null
);
char int varchar等等都是用來定義列數(shù)據(jù)類型的保留字,其中varchar表示可變字符類型。
3,Select <col1>,<col2>,...,<coln>
From <tab1>,<tab2>,...,<tabm>
[Where<條件>]
條件中的子查詢:
Where Not Exists(
Select * From tab2 Where col1=col2
)//當(dāng)查詢結(jié)果為空時,條件為真。
4,INSERT INTO <tab1> VALUES(<col1>, ...<coln>)
5,DELETE FROM <tab1> [WHERE<條件>]
6,UPDATE <tab1>
SET <tab1>=<vlu1>
...
<tabn>=<vlun>
[WHERE<條件>]
例如:
Update exployee
Set age=27
Where name=''趙一''
二,JDBC 主要接口:
java.sql.DriverManager類用于處理驅(qū)動程序的調(diào)入并且對新的數(shù)據(jù)庫連接提供支持。
java.sql.Connection,指應(yīng)用程序與特定數(shù)據(jù)庫的連接。
java.sql.Statement,用于一般sql語句的執(zhí)行(可以是查詢、更新甚至可以創(chuàng)建數(shù)據(jù)庫的執(zhí)行過程)
java.sql.ResultSet,查詢所返回的結(jié)果保存在此對象中,用它可以瀏覽和存取數(shù)據(jù)庫內(nèi)的記錄。
1,通過jdbc-odbc橋使用odbc數(shù)據(jù)庫(并不需要jdbc Drivers)
先在odbc DSN(Data Source Name)設(shè)置處設(shè)置pubs sysDSN,sa為username,密碼為空
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");//加載驅(qū)動程序
con=DriverManager.getConnection("jdbc:odbc:pubs","sa","");//jdbc:odbc:pubs
con.close();
//應(yīng)當(dāng)catch ClassNotFoundException和SQLException
Connection的getWarning方法返回一個SQLWarning對象,在連接之前應(yīng)當(dāng)先檢查。
使用jdbc-odbc的最大好處是:免費的。但是性能受odbc的限制,而且一般odbc驅(qū)動比較昂貴。
2,使用專門的jdbc驅(qū)動程序。//此處是mm jdbc Driver
先將jar文件放在ClassPath里面。
Class.forName("org.gjt.mm.mysql.Driver");
con=DriverManager.getConnection("jdbc:mysql://localhost:3306/dbname","root","");
con.close();
可見使用何種方式連接何種數(shù)據(jù)庫與數(shù)據(jù)庫的操作和連接數(shù)據(jù)庫是無關(guān)的。
三,查詢數(shù)據(jù)庫
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");
...或者用序號(從1開始的)
int userId=rs.getInt(1);
Stirng userName=rs.getString(2);
ClassNotFoundException是由于Class.forName()無法載入jdbc驅(qū)動程序觸發(fā)的
SQLException是jdbc在執(zhí)行過程中發(fā)生問題時產(chǎn)生。有一個額外的方法getNextException()
catch(SQLException e){
out.println(e.getMessage());
while(e=e.getNextException()){
out.println(e.getMessage());
}
}
一般來說并不建議在jsp中編寫數(shù)據(jù)庫的訪問程序,可以將數(shù)據(jù)庫的訪問封裝在一個javabean中。
四,ResultSet深入
1,ResultSetMetaData
ResultSet rs=stmt.executeQuery("select....");
ResultSetMetaData rsmd=rs.getMetaData(); //獲取ResultSetMateData對象
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類型與ResultSet的getObject返回類型及對應(yīng)的XXX getXXX()方法
SQL類型 JSP類型 對應(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()用來檢查null
4,存取大字符串和二進制文本
對于數(shù)據(jù)庫中l(wèi)ongvarchar和langvarbinary進行流操作
ResultSet rs=stmt.executeQueryString("select ...");
BufferedReader br=new BufferedReader(new InputStream(rs.getAsciiStream("vol1")));//長文本串
BufferedReader br=new BufferedReader(new InputStream(rs.getUnicodeStream("vol1")));
BufferedReader br=new BufferedReader(new InputStream(rs.getBinaryStream("vol2")));//長二進制文本
//取數(shù)據(jù)必須在rs.getAsciiStream(), rs.getUnicodeStream(), rs.getBinaryStream()等之后馬上進行
五,瀏覽ResultSet
1,JDBC2.0提供了更多瀏覽ResultSet的方法
首先,確定你的jdbc驅(qū)動程序支持jdbc2.0
其次,由Connection生成Statement時要指定參數(shù)
Statement stmt=con.getStatement("游標(biāo)類型", "記錄更新權(quán)限");
游標(biāo)類型:
ResultSet.TYPE_FORWORD_ONLY:只可以向前移動
ResultSet.TYPE_SCROLL_INSENSITIVE:可卷動。但是不受其他用戶對數(shù)據(jù)庫更改的影響。
ResultSet.TYPE_SCROLL_SENSITIVE:可卷動。當(dāng)其他用戶更改數(shù)據(jù)庫時這個記錄也會改變。
記錄更新權(quán)限:
ResultSet.CONCUR_READ_ONLY,只讀
ResultSet.CONCUR_UPDATABLE,可更新
getStatement()缺省參數(shù):getStatement(ResultSet.TYPE_FORWORD_ONLY, ResultSet.CONCUR_READ_ONLY)
2,如果ResultSet是可卷動的,以下函數(shù)可以使用:
rs.absolute()//絕對位置,負數(shù)表示從后面數(shù)
rs.first()第一條
rs.last()最后一條
rs.previoust()前一條
rs.next()后一條
rs.beforeFirst()第一條之前
rs.afterLast()最后之后
rs.isFirst(),rs.isLast(),rs.isBeforeFirst(),rs.isAfterLast
注意,剛打開的時候是處于第一條記錄之前的
六,更新數(shù)據(jù)庫
1,stmt.executeUpdate("strSql"),strSql是一條sql更新語句。update,insert,delete返回影響到的條數(shù)
2,stmt.execute()方法在不知道sql語句是查詢還是更新的時候用。如果產(chǎn)生一條以上的對象時,返回true,此時可用stmt.getResultSet()和stmt.getUpdateCount()來獲取execute結(jié)果,如果不返回ResultSet對象則返回false.
3,除了Statement的executeUpdate之外還可以用ResultSet:
rs.updateInt(1,10);
rs.updateString(2,"sfafd");
rs.updateRow();
七,使用預(yù)編譯PreparedStatement
PreparedStatement對象和Statement對象類似,都可以用來執(zhí)行SQL語句。不同在于,數(shù)據(jù)庫會對PreparedStatement的SQL語句進行預(yù)編譯,而且仍舊能輸入?yún)?shù)并重復(fù)執(zhí)行編譯好的查詢速度比未編譯的要快。
PreparedStatement stmt=con.preparedStatement("Insert Into users(userid, username) values(?,?)");
stmt.clearParameters();
stmt.setInt(1,2);
stmt.setString(2,"Big");
stmt.executeUpdate();
八,執(zhí)行存儲過程
1,JDBC調(diào)用存儲過程,并使用存儲過程的返回值。這樣可以將處理工作分為服務(wù)端和客戶端兩部分,并大大加快系統(tǒng)的設(shè)計和開發(fā)的時間。比如可以重復(fù)使用服務(wù)器上的組件。使用存儲過程之后大量諸計算工作可以交給數(shù)據(jù)庫服務(wù)器來處理,這將降低Web服務(wù)器的負載,從而提高整個系統(tǒng)的性能。
2,有兩個表UserMain{UserID,UserName,UserType},UserRef{BrefID, UserID, UserBrief}
下面的存儲過程可以接受jdbc傳來的參數(shù),新增內(nèi)容到UserMain和UserRef,并輸出一個OutUserID.
CREATE PROCEDURE ap_adduser
(
@OutUserID int output, //此為輸出參數(shù),output標(biāo)記
@UserName varchar(25), //參數(shù)表示方法:"@XXX"為變量名,"變量名 類型 [output]"
@UserType tinyint,
@UserBrief varchar(255),
)
AS
Declare @UserID int //定義局部變量
insert into UserMain(UserName, UserType)
values(@UserName,@UserType)
select @UserID=@@IDENTITY //賦值用select,此處自動獲得ID
insert into UserRef(UserID, UserBrief)
select @OutUserID=@UserID
GO/*結(jié)束,基本結(jié)構(gòu):
CREATE PROCEDURE procedureName(
parameters
)
AS
actions
GO
*/
JSP頁面中這樣使用:
CallableStatement stmt=con.prepareCall("{call ap_adduser(?,?,?,?)}");
stmt.registerOutParameter(1,Types.INTEGER,1);//注冊輸出變量
stmt.setString(2,"edmund");
stmt.setInt(3,1);
stmt.setString(4,"description");
stmt.execute();
int userid=stmt.getInt(1);
stmt.close()
八,使用事務(wù)
1,事務(wù)中的操作是一個整體,要么都執(zhí)行成功要么都不成功:事務(wù)開始后,如果所有的改變都正確,則使用commit方法將這些動作全部存入數(shù)據(jù)庫,否則就使用rollback取消所有的改變動作,而這時數(shù)據(jù)庫中的數(shù)據(jù)和執(zhí)行事務(wù)前的是相同的。
2,使用事務(wù)時應(yīng)當(dāng)先用 con.setAutoCommit(false),最后使用commit或者rollback
3,rollback一般在catch段執(zhí)行
九,數(shù)據(jù)庫連接池
1,如果有一個數(shù)據(jù)庫連接請求并且連接中沒有連接,則生成一個新的連接。這個連接使用完之后并不關(guān)閉它,而是將它放入連接池。在這個過程中,還要判斷連接池中的連接是否超期。如果超期則將它關(guān)閉。
2,有很多已有的Connection Pool包可以使用。
3,一般將Connection Pool作為一個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);
}
也可以使用一個Servlet初始化連接池