06-JSP中使用数据库_第1页
06-JSP中使用数据库_第2页
06-JSP中使用数据库_第3页
06-JSP中使用数据库_第4页
06-JSP中使用数据库_第5页
已阅读5页,还剩52页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

JSP中使用数据库知识点回顾EL简介掌握EL主要作用掌握EL获取数据基本用法掌握EL运算符了解EL保留字了解如何禁用EL掌握常用的EL隐式对象(内置对象)EL的应用及实例演示本章目标JDBC概述JDBC常用API(Driver、DriverManager、Connection、Statement、ResultSet、PreparedStatement、CallableStatement)连接数据库的基本过程使用JDBC进行事务处理JDBC概述概述(什么是JDBC)java数据库连接(JavaDatabaseConnectivity,JDBC)是一种用于执行SQL语句的JavaAPI,由一组用Java编程语言编写的类和接口组成。JDBC为数据库开发人员提供了一组标准的API,使他们能够用纯JavaAPI来编写数据库应用程序。MySQLOracleMySQL驱动Oracle驱动应用程序MySQLOracleMySQL驱动Oracle驱动应用程序JDBCJDBC概述JDBC的目的? 推广java的应用。 设计出一种通用的数据库访问接口。使应用程序开发人员使用JDBC可以连接任何提供了JDBC驱动程序的数据库系统。JDBC的用途是什么? 简单地说,JDBC可做三件事: 数据库建立连接。 发送SQL语句。 处理结果。

JDBC概述组成JDBC的2个包:java.sqljavax.sql(javax是java扩展包)开发JDBC应用需要以上2个包的支持外还需要导入相应JDBC的数据库实现(即数据库驱动)第一个JDBC程序编程从user表中读取数据,并打印在页面中。一、搭建实验环境:

1、在sqlserver中创建一个数据库,并创建user表和插入表的数据。

2、新建一个Java工程,并导入数据驱动。二、编写程序,在程序中加载数据库驱动

Class.forName(StringclassName);三、建立连接(Connection) Connectionconn=DriverManager.getConnection(url,user,pass);

四、创建用于向数据库发送SQL的Statement对象,并发送sql Statementst=conn.createStatement(); ResultSetrs=st.executeQuery(sql);五、从代表结果集的ResultSet中取出数据,打印到页面六、断开与数据库的连接,并释放相关资源JDBC编程步骤装载驱动程序建立连接操作数据释放资源JDBC访问数据库的流程通过Class.forName加载驱动程序;通过DriverManager类获得表示数据库连接的Connection类对象;通过Connection对象绑定要执行的语句,生成Statement类对象;执行SQL语句,接收执行结果集ResultSet;可选的对结果集ResultSet类对象的处理;必要的关闭ResultSet、Statement和ConnectionJDBC常用API常用的类或者接口作用DriverManager类驱动管理类,支持驱动器和数据库连接的创建Connection接口代表与某一数据库的连接Statement接口在连接中执行SQL并取得执行结构PreparedStatement接口是Statement的子接口,代表预编译的SQL声明CallableStatement接口是Statement的子接口,代表SQL的存储过程ResultSet接口代表执行SQL后产生的数据库结果集DriverManagerJdbc程序中的DriverManager用于加载驱动,并创建与数据库的链接,这个API的常用方法:

DriverManager.registerDriver(newDriver())

DriverManager.getConnection(url,user,password),注意:在实际开发中并不推荐采用registerDriver方法注册驱动。原因有二:一、查看Driver的源代码可以看到,如果采用此种方式,会导致驱动程序注册两次,也就是在内存中会有两个Driver对象二、程序依赖mysql的api,脱离mysql的jar包,程序将无法编译,将来程序切换底层数据库将会非常麻烦。推荐方式:Class.forName(“com.microsoft.sqlserver.jdbc.SQLServerDriver”);采用此种方式不会导致驱动对象在内存中重复出现,并且采用此种方式,程序仅仅只需要一个字符串,不需要依赖具体的驱动,使程序的灵活性更高同样,在开发中也不建议采用具体的驱动类型指向getConnection方法返回的connection对象。DriverManagerDriverManager加载Driver类并在DriverManager类中注册后,它们即可用来与数据库建立连接。当调用DriverManager.getConnection方法发出连接请求时,DriverManager将检查每个驱动程序,查看它是否可以建立连接。 以下代码是通常情况下用驱动程序建立连接所需所有步骤的示例:DriverManagerDriverManager//加裁驱动程序并自动注册连接实例Class.forName("oracle.jdbc.driver.OracleDriver");//设置URLStringurl="jdbc:oracle:thin:@localhost:1521:inspur";//设置用户名和密码Stringusername="scott";Stringpassword="tiger";//通过DriverManager向DB发出连接请求,获得连接对象Connectionconn=DriverManager.getConnection(url,username,password);数据库URLURL用于标识数据库的位置,程序员通过URL地址告诉JDBC程序连接哪个数据库,URL的写法为:jdbc:sqlserver://localhost:1433;DatabaseName=sid协议子协议主机域名:端口数据库常用数据库URL地址的写法:Oracle写法:jdbc:oracle:thin:@localhost:1521:sidMySql—jdbc:mysql://localhost:3306/sid数据库URLConnectionJdbc程序中的Connection,它用于代表数据库的链接,Collection是数据库编程中最重要的一个对象,客户端与数据库所有交互都是通过connection对象完成的,这个对象的常用方法:createStatement():创建向数据库发送sql的statement对象prepareStatement(sql):创建向数据库发送预编译sql的PrepareSatement对象提高性能解决SQL注入问题prepareCall(sql):创建执行存储过程的callableStatement对象。setAutoCommit(boolean

autoCommit):设置事务是否自动提交。commit():在链接上提交事务。---与事务相关!!rollback():在此链接上回滚事务。StatementJdbc程序中的Statement对象用于向数据库发送SQL语句,Statement对象常用方法:executeQuery(String

sql):用于向数据发送查询语句。executeUpdate(String

sql):用于向数据库发送insert、update或delete语句execute(Stringsql):用于向数据库发送任意sql语句addBatch(String

sql):把多条sql语句放到一个批处理中。executeBatch():向数据库发送一批sql语句执行。ResultSetJdbc程序中的ResultSet用于代表Sql语句的执行结果。Resultset封装执行结果时,采用的类似于表格的方式。ResultSet对象维护了一个指向表格数据行的游标cursor,初始的时候,游标在第一行之前,调用ResultSet.next()方法,可以使游标指向具体的数据行,进而调用方法获取该行的数据。ResultSet既然用于封装执行结果的,所以该对象提供的大部分方法都是用于获取数据的get方法:获取任意类型的数据getObject(intindex)getObject(stringcolumnName)获取指定类型的数据,例如:

getString(intindex)getString(StringcolumnName)提问:数据库中列的类型是varchar,获取该列的数据调用什么方法?Int类型呢?bigInt类型呢?Boolean类型?常用数据类型转换表Jdbc(rs)对应方法返回类型getBooleangetBytes()Booleanbyte[]getByte()BytegetShort()ShortgetInt()IntgetLong()LonggetString()StringgetClobgetBlob()ClobBlobgetDate()java.sql.DategetTime()java.sql.TimegetTimestamp()java.sql.TimestampSQL类型BIT(1)bit(10)TINYINTSMALLINTIntBIGINTCHAR,VARCHAR,LONGVARCHARText(clob)BlobDATETIMETIMESTAMP遍历查询结果ResultSet滚动结果集可滚动结果集可滚动结果集的创建Statementstmt=conn.createStatement(type,concurrency);PreparedStatementpstmt=conn.preparedStatement(type,concurrency);变量type来设置是否是可滚动的结果集,可以是以下几个ResultSet常量TYPE_FORWARD_ONLY:结果集不能滚动TYPE_SCROLL_INSENSITIVE:结果集可以滚动,但是对数据库变化不敏感,数据库查询生成结果集后发生了变化,结果集不发生变化。TYPE_SCROLL_SENSITIVE:结果集可以滚动,但是对数据库变化敏感。ResultSet滚动结果集可更新结果集更新结果集的内容,数据库将自动更新Statementstmt=conn.createStatement(type,concurrency);PreparedStatementpstmt=conn.preparedStatement(type,concurrency);变量concurrency设置是否可以更新。ResultSet类的concurrency的值:CONCUR_READ_ONLY结果集不能用于更新数据库CONCUR_UPDATABLE结果集可以更新数据库。ResultSet滚动结果集ResultSet还提供了对结果集进行滚动和更新的方法Statementstmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE);next():移动到下一行previous():移动到前一行absolute(introw):移动到指定行beforeFirst():移动resultSet的最前面afterLast():移动到resultSet的最后面updateRow():更新行数据释放资源Jdbc程序运行完后,切记要释放程序在运行过程中,创建的那些与数据库进行交互的对象,这些对象通常是ResultSet,Statement和Connection对象。特别是Connection对象,它是非常稀有的资源,用完后必须马上释放,如果Connection不能及时、正确的关闭,极易导致系统宕机。Connection的使用原则是尽量晚创建,尽量早的释放。为确保资源释放代码能运行,资源释放代码也一定要放在finally语句中。1、查询出T_USER表中所有的数据通过T_USER表实现用户登录验证,实现对T_USER表的增删改2、编写工具类简化增删改查操作。(异常暂不处理)使用JDBC对数据库进行增删改查Jdbc中的statement对象用于向数据库发送SQL语句,想完成对数据库的增删改查,只需要通过这个对象向数据库发送增删改查语句即可。Statement对象的executeUpdate方法,用于向数据库发送增、删、改的sql语句,executeUpdate执行完后,将会返回一个整数(即增删改语句导致了数据库几行数据发生了变化)。Statement.executeQuery方法用于向数据库发送查询语句,executeQuery方法返回代表查询结果的ResultSet对象。使用JDBC对数据库进行添加操作使用executeUpdate(Stringsql)方法完成数据添加操作,示例操作: Statementst=conn.createStatement(); Stringsql="insertintouser(….)values(…..)"; intnum=st.executeUpdate(sql); if(num>0){ System.out.println("插入成功!!!"); }使用JDBC对数据库进行修改操作使用executeUpdate(Stringsql)方法完成数据修改操作,示例操作: Statementst=conn.createStatement(); Stringsql=“updateusersetname=‘’wherename=‘’"; intnum=st.executeUpdate(sql); if(num>0){ System.out.println(“修改成功!!!"); }使用JDBC对数据库进行删除操作使用executeUpdate(Stringsql)方法完成数据删除操作,示例操作: Statementst=conn.createStatement(); Stringsql=“deletefromuserwhereid=1;

intnum=st.executeUpdate(sql); if(num>0){

System.out.println(“删除成功!!!"); }使用JDBC对数据库进行查询操作使用executeQuery(Stringsql)方法完成数据查询操作,示例操作: Statementst=conn.createStatement(); Stringsql=“select*fromuserwhereid=1;

ResultSet

rs=st.executeQuery(sql); while(rs.next()){ //根据获取列的数据类型,分别调用rs的相应方法

//映射到java对象中

}PreparedStatementPreparedStatement接口 PreparedStatement实例包含已编译的SQL语句。就是说使SQL语句“准备好”。包含于PreparedStatement对象中的SQL语句可具有一个或多个IN参数。IN参数的值在SQL语句创建时未被指定。相反的,该语句为每个IN参数保留一个问号(“?”)作为占位符。每个问号的值必须在该语句执行之前,通过适当的setXXX方法来提供。该PreparedStatement接口继承Statement,并与之在三方面有所不同:PreparedStatementPreperedStatement可以避免SQL注入的问题。Statement会使数据库频繁编译SQL,可能造成数据库缓冲区溢出。PreparedStatement可对SQL进行预编译,从而提高数据库的执行效率。作为Statement的子类,PreparedStatement继承了Statement的所有功能。另外它还添加了一整套方法,用于设置发送给数据库以取代IN参数占位符的值。同时,三种方法execute、executeQuery和executeUpdate已被更改以使之不再需要参数。这些方法的Statement形式(接受SQL语句参数的形式)不应该用于PreparedStatement对象。PreparedStatement创建PreparedStatement对象 以下的代码段(其中con是Connection对象)创建包含带两个IN参数占位符的SQL语句的PreparedStatement对象: PreparedStatementpstmt=con.prepareStatement("UPDATEtable4SETm=?WHEREx=?");pstmt对象包含语句“UPDATEtable4SETm=?WHEREx=?”,它已发送给DBMS,并为执行作好了准备。 2传递IN参数:

PreparedStatement使用PreparedStatement对象

在执行PreparedStatement对象之前,必须设置每个?参数的值。这可通过调用setXXX方法来完成,其中XXX是与该参数相应的类型。例如,如果参数具有Java类型long,则使用的方法就是setLong。setXXX方法的第一个参数是要设置的参数的序数位置,第二个参数是设置给该参数的值。例如,以下代码将第一个参数设为123456789,第二个参数设为100000000:

一旦设置了给定语句的参数值,就可用它多次执行该语句,直到调用clearParameters方法清除它为止。在连接的缺省模式下(启用自动提交),当语句完成时将自动提交或还原该语句。 pstmt.setLong(1,123456789);pstmt.setLong(2,100000000);PreparedStatement使用PreparedStatement对象

如果基本数据库和驱动程序在语句提交之后仍保持这些语句的打开状态,则同一个PreparedStatement可执行多次。如果这一点不成立,那么试图通过使用PreparedStatement对象代替Statement对象来提高性能是没有意义的。 利用pstmt(前面创建的PreparedStatement对象),以下代码示例了如何设置两个参数占位符的值并执行pstmt10次。如上所述,为做到这一点,数据库不能关闭pstmt。在该示例中,第一个参数被设置为"Hi"并保持为常数。在for循环中,每次都将第二个参数设置为不同的值:从0开始,到9结束。pstmt.setString(1,"Hi");for(inti=0;i<10;i++){

pstmt.setInt(2,i);

introwCount=pstmt.executeUpdate();}PreparedStatement使用PreparedStatement对象 IN参数中数据类型的一致性

setXXX方法中的XXX是Java类型。它是一种隐含的JDBC类型(一般SQL类型),因为驱动程序将把Java类型映射为相应的JDBC类型,并将该JDBC类型发送给数据库。例如,以下代码段将PreparedStatement对象pstmt的第二个参数设置为44,Java类型为short: 驱动程序将44作为JDBCSMALLINT发送给数据库,它是Javashort类型的标准映射。 程序员的责任是确保将每个IN参数的Java类型映射为与数据库所需的JDBC数据类型兼容的JDBC类型。不妨考虑数据库需要JDBCSMALLINT的情况。如果使用方法setByte,则驱动程序将JDBCTINYINT发送给数据库。这是可行的,因为许多数据库可从一种相关的类型转换为另一种类型,并且通常TINYINT可用于SMALLINT适用的任何地方pstmt.setShort(2,44);CallableStatementCallableStatement对象

CallableStatement对象为所有的DBMS提供了一种以标准形式调用存储过程的方法。存储过程储存在数据库中。对存储过程的调用是CallableStatement对象所含的内容。这种调用是用一种换码语法来写的,有两种形式:一种形式带结果参数,另一种形式不带结果参数。结果参数是一种输出(OUT)参数,是存储过程的返回值。两种形式都可带有数量可变的输入(IN参数)、输出(OUT参数)或输入和输出(INOUT参数)的参数。问号将用作参数的占位符。CallableStatementCallableStatement对象 在JDBC中调用已储存过程的语法如下所示。注意,方括号表示其间的内容是可选项;方括号本身并不是语法的组成部份。带参数的: {call过程名[(?,?,...)]}不带参数的: {call过程名} 通常,创建CallableStatement对象的人应当知道所用的DBMS是支持存储过程的,并且知道这些存储过程都是些什么。然而,如果需要检查,多种DatabaseMetaData方法都可以提供这样的信息。例如,如果DBMS支持存储过程的调用,则supportsStoredProcedures方法将返回true,而getProcedures方法将返回对存储过程的描述。CallableStatement继承Statement的方法(它们用于处理一般的SQL语句),还继承了PreparedStatement的方法(它们用于处理IN参)。CallableStatement创建CallableStatement对象

CallableStatement对象是用Connection方法prepareCall创建的。下例创建CallableStatement的实例,其中含有对存储过程INSERTPRO_T1T2调用。

其中?占位符为IN、OUT还是INOUT参数,取决于存储过程INSERTPRO_T1T2Stringsql2="{callINSERTPRO_T1T2(?,?)}";CallableStatementcallpro2=conn.prepareCall(sql2);CallableStatementIN和OUT参数将IN参数传给CallableStatement对象是通过setXXX方法完成的。该方法继承自PreparedStatement。所传入参数的类型决定了所用的setXXX方法(例如,用setFloat来传入float值等)。如果存储过程返回OUT参数,则在执行CallableStatement对象以前必须先注册每个OUT参数的JDBC类型(这是必需的,因为某些DBMS要求JDBC类型)。注册JDBC类型是用registerOutParameter方法来完成的。语句执行完后,CallableStatement的getXXX方法将取回参数值。正确的getXXX方法是为各参数所注册的JDBC类型所对应的Java类型。换言之,registerOutParameter使用的是JDBC类型(因此它与数据库返回的JDBC类型匹配),而getXXX将之转换为Java类型。CallableStatementIN和OUT参数

作为示例,下述代码先注册OUT参数,执行由cstmt所调用的已储存过程,然后检索在OUT参数中返回的值。方法getByte从第一个OUT参数中取出一个Java字节,而getBigDecimal从第二个OUT参数中取出一个BigDecimal对象(小数点后面带三位数):

CallableStatement与ResultSet不同,它不提供用增量方式检索大OUT值的特殊机制。CallableStatementcstmt=con.prepareCall("{callgetTestData(?,?)}");cstmt.registerOutParameter(1,java.sql.Types.TINYINT);cstmt.registerOutParameter(2,java.sql.Types.DECIMAL,3);cstmt.executeQuery();bytex=cstmt.getByte(1);java.math.BigDecimaln=cstmt.getBigDecimal(2,3);CallableStatementIN和OUT参数

既支持输入又接受输出的参数(INOUT参数)除了调用registerOutParameter方法外,还要求调用适当的setXXX方法(该方法是从PreparedStatement继承来的)。setXXX方法将参数值设置为输入参数,而registerOutParameter方法将它的JDBC类型注册为输出参数。setXXX方法提供一个Java值,而驱动程序先把这个值转换为JDBC值,然后将它送到数据库中。这种IN值的JDBC类型和提供给registerOutParameter方法的JDBC类型应该相同。然后,要检索输出值,就要用对应的getXXX方法。例如,Java类型为byte的参数应该使用方法setByte来赋输入值。应该给registerOutParameter提供类型为TINYINT的JDBC类型,同时应使用getByte来检索输出值。 下例假设有一个已储存过程reviseTotal,其唯一参数是INOUT参数。方法setByte把此参数设为25,驱动程序将把它作为JDBCTINYINT类型送到数据库中。接着,registerOutParameter将该参数注册为JDBCTINYINT。执行完该存储过程后,将返回一个新的JDBCTINYINT值。方法getByte将把这个新值作为Javabyte类型检索。CallableStatementcstmt=con.prepareCall("{callreviseTotal(?)}");cstmt.setByte(1,25);cstmt.registerOutParameter(1,java.sql.Types.TINYINT);cstmt.executeUpdate();bytex=cstmt.getByte(1);CallableStatementIN和OUT参数

检索作为OUT参数的NULL值 返回到OUT参数中的值可能会是JDBCNULL。当出现这种情形时,将对JDBCNULL值进行转换以使getXXX方法所返回的值为null、0或false,这取决于getXXX方法类型。对于ResultSet对象,要知道0或false是否源于JDBCNULL的唯一方法,是用方法wasNull进行检测。如果getXXX方法读取的最后一个值是JDBCNULL,则该方法返回true,否则返回false。CallableStatement使用例:try{Class.forName("oracle.jdbc.OracleDriver");Connectionconn=DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:teacher","scott","tiger");//调用存储过程Stringcall="{callget_emp(?,?,?)}";CallableStatementpstmt=conn.prepareCall(call);pstmt.setString(1,"CLARK");pstmt.registerOutParameter(2,Types.VARCHAR);pstmt.registerOutParameter(3,Types.VARCHAR);pstmt.execute();System.out.println(pstmt.getString(2));System.out.println(pstmt.getString(3));//调用函数Stringfun="{?=callfun_emp(?)}";CallableStatementpstmt1=conn.prepareCall(fun);pstmt1.registerOutParameter(1,Types.VARCHAR);pstmt1.setString(2,"CLARK");pstmt1.execute();System.out.println(pstmt1.getString(1));}catch(ClassNotFoundExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}catch(SQLExceptione){//TODOAuto-generatedcatchblocke.printStackTrace();}ResultSetMetaDataResultSetMetaData结果集元数据提供了有关从数据库查询返回的结果集对象的额外信息,由ResultSetMetaData对象提供数据库元数据提供了数据库的相关信息,由DataBaseMetaData对象提供//从元数据中获得列数(常用)ResultSetMetaDatarsmd;rsmd=results.getMetaData();numCols=rsmd.getColumnCount();使用JDBC进行批处理业务场景:当需要向数据库发送一批SQL语句执行时,应避免向数据库一条条的发送执行,而应采用JDBC的批处理机制,以提升执行效率。实现批处理有两种方式,第一种方式:Statement.addBatch(sql)执行批处理SQL语句executeBatch()方法:执行批处理命令clearBatch()方法:清除批处理命令使用JDBC进行批处理Connectionconn=null;Statementst=null;ResultSetrs=null;try{conn=JdbcUtil.getConnection();Stringsql1="insertintoperson(name,password,email,birthday) values('kkk','123','abc@','1978-08-08')";Stringsql2="updateusersetpassword='123456'whereid=3";st=conn.createStatement();st.addBatch(sql1);//把SQL语句加入到批命令中st.addBatch(sql2);//把SQL语句加入到批命令中st.executeBatch();}finally{ JdbcUtil.free(conn,st,rs);}使用JDBC进行批处理采用Statement.addBatch(sql)方式实现批处理:优点:可以向数据库发送多条不同的SQL语句。缺点:SQL语句没有预编译。当向数据库发送多条语句相同,但仅参数不同的SQL语句时,需重复写上很多条SQL语句。例如:

Insertintouser(name,password)values(‘aa’,’111’); Insertintouser(name,password)values(‘bb’,’222’); Insertintouser(name,password)values(‘cc’,’333’); Insertintouser(name,password)values(‘dd’,’444’);使用JDBC进行批处理实现批处理的第二种方式:PreparedStatement.addBatch()使用JDBC进行批处理conn=JdbcUtil.getConnection();Stringsql="insertintoperson(name,password,email,birthday)values(?,?,?,?)";st=conn.prepareStatement(sql);for(inti=0;i<50000;i++

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论