国通快速建站,给公司网站做seo,网站制作公司十强,网站开发根目录建在哪7.2 创建JDBC应用
7.2.1 创建JDBC应用程序的步骤 使用JDBC操作数据库中的数据包括6个基本操作步骤#xff1a; #xff08;1#xff09;载入JDBC驱动程序#xff1a; 首先要在应用程序中加载驱动程序driver#xff0c;使用Class.forName()方法加载特定的驱动程序#xf…7.2 创建JDBC应用
7.2.1 创建JDBC应用程序的步骤 使用JDBC操作数据库中的数据包括6个基本操作步骤 1载入JDBC驱动程序 首先要在应用程序中加载驱动程序driver使用Class.forName()方法加载特定的驱动程序每种数据库管理系统的驱动程序不同由数据库厂商提供。 2定义连接URL建立数据库连接对象 通过DriverManager类的getConnection()方法获得表示数据库连接的Connection类对象。 3创建Statement对象 获取Connection对象以后可以用Connection对象的方法创建一个Statement对象的实例。 4执行查询或更新 Statement对象可以执行SELECT语句的executeQuery()方法或执行INSERT、UPDATE、DELETE语句的executeUpdate()方法。 5操作结果集 利用ResultSet对象对数据库操作返回的结果进行处理。ResultSet包含一些用来从结果集中获取数据并保存到Java变量中的方法。主要包括next()方法用于移动结果集游标逐行处理结果集getString()、getInt()、getDate()、getDouble()等方法用于将数据库中的数据类型转换为Java的数据类型。 6释放资源 使用与数据库相关的对象非常耗内存因此在数据库访问后要关闭与数据库的连接同时还应该关闭ResultSet、Statement和Connection等对象。可以使用每个对象自己的close()方法完成。
7.2.2 JDBC应用程序的实现 1载入JDBC驱动程序 在JavaAPI中的Class类提供了加载驱动程序的方法方法格式如下
参数className表示驱动类的描述符字符串例如加载Oracle驱动的语句描述符为 老版本驱动一般指5.x版本
新版本驱动一般指8.x版本
Mysql数据库的JDBC驱动程序文件可到Mysql官方网站下载。注意加载驱动程序的时候会抛出ClassNotFoundExceptionSQLException异常。 2定义连接URL建立数据库连接对象 DriverManager类提供了getConnection()方法可获得指定数据库的连接对象方法格式如下
MySQL数据库的url参数格式为
下面语句是建立MySQL数据库连接对象的语句
更多的创建Connection对象的方法同学们可以查阅JavaAPI文档。 3创建Statement对象 Connection接口中提供了获得Statement对象的方法方法格式如下
4执行查询或更新 获取Statement对象后就可以通过Statement对象的executeQuery()或exeucteUpdate()方法执行查询或者更新操作有关方法的详细解释同学们可以查阅JavaAPI文档。 5操作结果集 ResultSet接口提供对结果集进行操作的方法主要包括 1boolean next() throws SQLException移动结果集操作指针。 2getXxx(String columnName) throws SQLException根据传入列的名字获取指定列的值。 3getXxx(1) throws SQLException根据传入列的编号获取指定列的值。 SQL类型与Java数据类型不同下表列出了SQL类型与Java数据类型的对应关系。
SQLTypeJavaTypeCHARStringVARCHARStringLONGVARCHARStringNUMERICjava.math.BigDecimalDECIMALjava.math.BigDecimalBITbooleanTINYINTbyteSMALLINTshortINTEGERintBIGINTlongREALfloatFLOATdoubleDOUBLEdoubleBINARYbyte[]VARBINARYbyte[]LONGVARBINARYbyte[]DATEjava.sql.DateTIMEjava.sql.TimeTIMESTAMPjava.sql.Timestamp
更多的操作结果集的方法同学们可以查阅JavaAPI文档。 6释放资源 数据库操作完成后需要调用ResultSet、Statement、Connection接口中的关闭方法释放相关资源关闭顺序如下 首先关闭结果集ResultSet对象 然后关闭Statement对象 最后关闭Connection对象。
例: 回收JDBC资源示例代码
Java **/****** * 回收JDBC资源示例代码**** */****public** **static** **void** **close**(**ResultSet** **resultSet**, **Statement** **statement**, **Connection** **connection**)**{****try****{****if** **(** **resultSet**!**null**)**{****resultSet**.**close**(**)**;**}****}**catch**(**SQLException **e**)**{****System**.**out**.**println**(**e**.**getMessage**(**)**)**;****}****try****{****if** **(** **statement**!**null**)**{****statement**.**close**(**)**;**}****}**catch**(**SQLException **e**)**{****System**.**out**.**println**(**e**.**getMessage**(**)**)**;****}****try****{****if** **(**connection **!**null**)**{**connection**.**close**(**)**;**}****}**catch**(**SQLException **e**)**{****System**.**out**.**println**(**e**.**getMessage**(**)**)**;****}****}**7.2.3 JDBC中主要的类及常用方法 使用JDBC编写访问数据库的应用程序需要经过加载数据库驱动程序、创建连接、创建Statement对象、发送SQL语句、解析操作结果等步骤它们由JDBC API中一组类的方法实现。主要的类如下 1Class类(了解即可,后续内容会讲) Class类全称java.lang.ClassJava程序运行时会自动创建程序中的每个类的Class对象通过Class类的方法可以得到程序中每个类的信息。Class类方法主要包括 public static Class forName(String className)该方法根据给定的字符串参数返回相应的Class对象。例Class.forName(“com.mysql.jdbc.Driver”)的作用是加载Oracle驱动。 public String getName()该方法返回类名例str.getClass().getName())。 如果想了解更多Class类的其它方法可以查阅Java API文档。 2DriverManager类 DriverManager类在用户程序和数据库系统之间维护着与数据库驱动程序之间的连接。它实现驱动程序的装载、创建与数据库系统连接的Connection类对象。DriverManager类的方法主要包括
Java
public static Connection getConnection(String url, String user, String password)
//根据url、数据库登录的用户名、密码获取一个数据库的连接对象。
3Connection接口 Connection用于管理到指定数据库的连接。 Connection conDriverManager.getConnection (url, username, password); Connetction类中重要的成员方法包括 createStatement()方法创建Statement类的实例。 prepareStatement()方法创建PreparedStatement类的实例。 close()立即释放此Connection对象的数据库和JDBC资源而不是等待它们被自动释放。 4Statement接口 Statement数据库操作类提供执行数据库操作的方法如更新、查询数据库记录等。 Statement对象的创建方式如下 Statement stmtcon.createStatement(); Statement类中重要的成员方法包括 executeQuery()方法它用来执行一个查询语句参数是一个String对象就是一个SELECT语句。它的返回值是ResultSet类的对象查询结果封装在该对象中。 例stmt.executeQuery(select * from users where username‘张三’ and password‘123’ ); executeUpdate()方法它用来执行更新操作参数是一个String对象即一个更新数据表记录的SQL语句。使用它可以对表中的记录进行修改、插入和删除等操作。例
Java
复制代码
stmt.executeUpdate(“INSERT INTO users(username,password) values(‘刘青’, ‘aaa’) ”);
stmt.executeUpdate(“UPDATE users set password‘bbb’ where username**‘张三’ ”)**;
stmt.executeUpdate(“DELETE from users where username‘李四’ ”);
插入后想立即获取返回的主键通过设置Statement.RETURN_GENERATED_KEYS来实现
java//执行INSERT语句说明要返回数据库生成的主键
int count stmt.executeUpdate(sql, Statement.RETURN_GENERATED_KEYS);
System.out.println(“成功插入”count“条记录”);
//产生的主键以结果集的形式返回
rs stmt.getGeneratedKeys();
//遍历结果集输出主键实际上结果集只有一条记录
while(rs.next()){
**long** **id** **** **rs**.**getLong**(**1**)**;****System**.**out**.**println**(**产生的主键是****id**)**;**}
使用它还可以创建和删除数据表及修改数据表结构。例
close()关闭Statement对象。 Statement接口的好多方法都是重载的如果想了解更多其它方法可以查阅JavaAPI文档。 5ResultSet接口 ResultSet结果集类提供对查询结果集进行处理的方法。例 ResultSet rsstmt.executeQuery( select * from users ); ResultSet对象维持着一个指向表格的行的指针开始时指向表格的起始位置(第一行之前)。 ResultSet类常用的方法包括 next()方法光标移到下一条记录返回一个boolean值。 previous()方法光标移到前一条记录。 getXXX()方法获取指定类型的字段的值。调用方式 getXXX(“字段名”) 或 getXXX(int i)。i值从1开始表示结果集中第一列的字段。 close()关闭ResultSet对象。 例
ResultSet接口提供的getXxx方法如下表所示
MethodJavaTechnologyTypeReturnedgetASCIIStreamjava.io.InputStreamgetBigDecimaljava.math.BigDecimalgetBinaryStreamjava.io.InputStreamgetBooleanbooleangetBytebytegetBytesbyte[ ]getDatejava.sql.DategetDoubledoublegetFloatfloatgetIntintgetLonglonggetObjectObjectgetShortshortgetStringjava.lang.StringgetTimejava.sql.TimegetTimestampjava.sql.TimestampgetUnicodeStreamjava.io.InputStream of Unicode characters
下面以用户表t_user为例说明使用JDBC对数据库进行操作的方法用户表结构如表所示
名称数据类型主键是否为空说明IDnumber是用户编号NAMEVarchar2(50)用户名AGEvarchar2(5)用户年龄BIRTHdate用户生日PWDvarchar2(20)否用户密码
【例】使用JDBC查询数据库表t_user的所有数据。
程序运行结果如下 7:zhangsan:age:2015-09-01 8:lisi:24:2015-09-01 9:wangwu:25:2015-09-01 10:wang:23:2015-09-01 以上给大家粗略的介绍了一下JDBC中涉及到的常用相关类和接口每个类和接口包含的方法介绍的不是十分全面希望大家在后续的学习过程中能充分的利用JavaAPI这个工具不断提升自己的学习能力。
7.2.4 JDBC日期时间处理 上面例题中取出来的日期与数据库中存储的有所不同数据库中birth列包含日期和时间而上例中只显示了日期没有时间。这是因为获取日期时使用的是getDate()。对于数据库中不同的时间类型要分别采用与之相对应的Java包装类来存取: 1日期类型用java.sql.Date 2时间类型用java.sql.Time 3日期/时间类型用java.sql.Timestamp getTimestamp()可以把年月日时分秒都取出来getDate()只能取出年月日getTime()只能取出时分秒。 要把JDBC的日期/时间类型转换为字符串则可以使用下列方法
如何把java.sql.Timestamp转换为java.util.Date java.sql.Timestamp是java.util.Date的子类不需要做任何转换直接赋值即可看下面程序段
反过来如何把java.util.Date转换为java.sql.Timestamp呢java.util.Date是java.sql.Timestamp的父类要这样转换
7.2.5 JDBC封装工具类 通常无论是对数据进行查询操作还是进行增删改操作都需要打开连接关闭资源等操作因此可以把对把打开连接和关闭连接封装到一个工具类里。本章后面所有例子对数据访问所用连接都是一样的。下面的DBUtil类封装了打开连接和关闭连接方法。 【例】封装打开连接和关闭资源的DBUtil类。
程序分析关闭连接会抛出异常若遇到异常程序会意外终止因此要处理异常。而为了保证关闭资源语句在出现异常时也会执行到因此要把它放到finally语句中。另外因为查询操作才需要关闭ResultSet资源增删改是不需要关闭ResultSet资源的因此DBUtil类中对关闭操作进行了重载。 刚才我们定义了数据库通用处理类DBUtil接下来我们通过一个实例来看一下这个类应该怎么应用。 【例7-3】使用DBUtil类操作数据库
调用query()方法输出结果 7 z h a n g s a n zhangsan zhangsan 23 2015 年 09 月 01 日 15 : 15 : 068 2015年09月01日 15:15:06 8 2015年09月01日 15:15:068 lisi 24 24 24 2015年09月01日 15:15:23 9 w a n g w u wangwu wangwu 25 2015 年 09 月 01 日 15 : 15 : 5210 2015年09月01日 15:15:52 10 2015年09月01日 15:15:5210 hello1 500 500 500 2015年09月01日 15:16:03
7.2.6 SQL注入问题 在使用Statement对象查询数据库时由于定义的SQL语句是拼接的有可能出现SQL注入问题。所谓SQL注入就是通过把SQL命令插入到查询字符串最终达到欺骗服务器执行恶意的SQL命令。接下来我们通过一段代码来演示一下SQL注入案例。 【例】登录功能SQL注入示例。
程序分析上例中若传入的用户名为sadfsdf or 11则不管用户名和密码是否正确都能成功登录因为11永远为真和其它条件进行or操作也永远为真所以不管用户名和密码是否正确都能成功登录这就是SQL 注入问题。
7.3 PreparedStatement对象 PreparedStatement对象表示预编译的SQL语句的对象为解决Statement静态拼接所产生的SQL注入问题引入了PreparedStatement接口。PreparedStatement接口是Statement接口的子接口允许使用不同的参数多次执行同样的SQL语句。Connection接口提供创建PreparedStatement对象的方法可指定SQL语句
PreparedStatement对象继承了Statement但PreparedStatement语句中包含了警告预编译的SQL语句因此可以获得更高的执行效率。虽然使用Statement可以对数据库进行操作但它只适用于简单的SQL语句。如果需要执行带参数的SQL语句时我们必须利用PreparedStatement类对象。PreparedStatement对象用于执行带或不带输入参数的预编译的SQL语句语句中可以包含多个用问号代表的字段在程序中可以利用setXxx()方法设置该字段的内容从而增强了程序设计的动态性。 例如在案例中要查询编号为1的人员信息可用以下代码段
接着当我们需查询编号为2的人员信息时我们仅需以下代码 ps.setInt(1,2); PreparedStatement同Statement对象一样提供了很多基本的数据库操作方法下面列出了执行SQL命令的3种方法。
【例】使用PreparedStatement解决例上面例子登录功能的SQL注入问题。
程序分析采用以上方式登录不能成功解决了sql注入问题。 PreparedStatement的参数化的查询可以阻止大部分的SQL注入。在使用参数化查询的情况下数据库系统不会将参数的内容视为SQL指令的一部分来处理而是在数据库完成SQL指令的编译后才套用参数运行因此就算参数中含有破坏性的指令也不会被数据库所运行。 PreparedStatement接口setXxx()方法如表所示。
MethodSQLTypesetASCIIStreamLONGVARCHAR produced by an ASCII streamsetBigDecimalNUMERICsetBinaryStreamLONGVARBINARYsetBooleanBITsetByteTINYINTsetBytesVARBINARY or LONGVARBINARY (depending on the size relative to the limits on VARBINARY)setDateDATEsetDoubleDOUBLEsetFloatFLOATsetIntINTEGERsetLongBIGINTsetNullNULLsetObjectThe given object that is converted to the target SQL type before being sentsetShortSMALLINTsetStringVARCHAR or LONGVARCHAR (depending on the size relative to the driver’s limits on VARCHAR)setTimeTIMEsetTimestampTIMESTAMP
【例】利用PreparedStatement实现对用户表的增删改查操作。
在使用PreparedStatement对象执行SQL命令时命令被数据库进行解析和编译然后被放到命令缓冲区。然后每当执行同一个 PreparedStatement对象时它就会被再解析一次但不会被再次编译。在缓冲区中可以发现预编译的命令并且可以重新使用。在有大量用户的企业级应用软件中经常会重复执行相同的SQL命令使用PreparedStatement对象带来的编译次数的减少能够提高数据库的总体性能。如果不是在客户端创建、预备、执行PreparedStatement任务需要的时间长于Statement任务建议在除动态SQL命令之外的所有情况下使用PreparedStatement对象。相对于StatementPreparedStatement的优点如下 ●可动态设置参数。 ●增加了预编译功能。 ●提高执行速度。
完成4级项目1
7.4 用JDBC连接不同的数据库 了解即可本节给出的代码因不同的数据库版本可能不一致或者失效请随时参考官网。 上面我们讲解了使用JDBC连接Oracle数据库的方法因为JDBC是一套数据库连接的标准所以连接其它关系型数据库也都大同小异两点区别在于 1、数据库驱动路径不同 2、连接数据库的url不同 如下是各种数据库的JDBC连接方式 1MySql数据库
(2) DB2数据库
3Sybase数据库
4SQLServer数据库
7.5 事务处理 本节内容仅供有余力的且掌握了Oracle数据库的同学参考使用。
7.5.1事务的概念 事务是保持数据一致性的一种数据库机制通常大多数应用系统中除了查询操作(SELECT)不需要对事务进行控制之外其它数据操作(INSERT、UPDATE、DELETE)都会涉及到事务的操作在JDBC中事务主要是由数据库连接对象Connection的相关方法来控制涉及到主要方法包括 1.setAutoCommit(boolean autoCommit):将此连接的自动提交模式设置为给定状态。 2.commit():使所有上一次提交/回滚后进行的更改成为持久更改并释放此 Connection 对象当前持有的所有数据库锁。 3.rollback():取消在当前事务中进行的所有更改并释放此 Connection 对象当前持有的所有数据库锁。如果要取消事务中的操作则可以使用ROLLBACK命令。执行该命令后事务中的所有操作都被取消数据库恢复到事务开始之前的状态同时事务所占用的系统资源和数据库资源被释放。 如果只想取消事务中的部分操作而不是取消全部操作则可以在事务内部设置保存点将一个大的事务划分为若干个组成部分这样就可以将事务回滚到指定的保存点。 1connection.rollback();//回滚事务。 2SavePoint sp connection.setSavepoint(); //设置保存点 3connection.rollerbak(sp); //回滚到保存点 4connection.commit(); 可以使用SAVEPOINT语句设置保存点 1.setSavepoint():在当前事务中创建一个未命名的保存点 (savepoint)并返回表示它的新 Savepoint 对象。 2.setSavepoint(String name) :在当前事务中创建一个具有给定名称的保存点并返回表示它的新Savepoint 对象。 例如一个事务中包含3个插入操作、一个更新操作和2个保存点语句为
事务回滚的过程示意图如图7-4所示。
上述前三个方法的使用频率特别高通常应用系统中一个业务操作的实现步骤为 1在创建好数据库连接对象Connect之后调用setAutoCommit(false)方法把自动提交模式设置为假这样就避免了数据库执行自动提交而把是否提交的主动权交到程序员手中。 2按照用户的操作顺序执行相应的SQL语句。 3在执行每一个SQL语句过程中如果出现非预期的结果则调用rollback()方法执行回滚操作。 4所有SQL语句执行完成后通常调用commit()方法执行提交操作当然这时也可以执行回滚操作。
7.5.2 JDBC实现事务处理 接下来我们通过一个模拟转账实例来看一下JDBC中事务的操作。
程序分析上例中实现把张三账户的100块钱转给李四若不出现异常则数据库中张三的钱数为2900李四的钱数为2100。如图所示。
假如上例中把抛出异常的语句去掉再次运行会抛出运行时异常而数据库中数据如图所示。
在张三转出之后李四转入之前之间抛出个异常则会出现张三的钱数减少而李四的钱数却没有增加转出的100块钱丢失了。出现了数据不一致问题若要解决上述问题需要用到JDBC的事务处理。
【例】使用事务解决上一例题中的数据不一致问题。
7.6 在MVC思想中的DAO模式 本节内容仅供有余力的同学参考使用。 实际项目中经常使用MVC分层思想实现对数据库的操作MVC模式中的Model模型是应用程序中用于处理应用程序业务逻辑的部分。View视图是应用程序中处理数据显示的部分通常视图是依据模型数据创建的。Controller控制器是应用程序中协调Model组件和View组件的部分通常控制器负责从视图读取数据控制用户输入并向模型发送数据。 使用MVC思想进行DAO设计与框架搭建代码如下
对于数据库的每一张表都要定义一个数据访问类先定义访问用户表的接口UserDao。之所以定义一个数据访问的接口是因为面向接口编程能够起到封装和解耦合的作用而面向具体类编程。当类中的方法改变时调用它的类也要相应做出变更所以面向对象的一条核心编程思想是更多的采用面向接口编程。下面是访问数据库接口的实现类。
DAO的具体实现类。
本节主要讲述了JDBC中的常用类、接口以及方法的使用为了更好的给读者展示效果实例代码基本都写到数据访问对象DAO中例如本章中大量出现的UserDAO类。 在实际项目的编写过程中通常都是按照Model-View-Control模型层-视图层-控制层架构模式来组织代码通常来说数据访问对象DAO是属于模型层的一种对象专门用来编写对数据库中数据的增删改查操作而对数据库连接对象以及事务的管理通常不会放到数据访问对象DAO中来处理否则如果每个DAO的方法都来创建一个Connection连接对象就会过多的占用数据连接资源同时也就无法进行事务控制了。