第6章
JSP访问数据库
本课教学内容
? JDBC简介
? 建立ODBC数据源
? JDBC操作 ? 使用PreparedStatement和CallableStatement ? 事务 ? 使用厂商驱动进行数据库连接
JDBC 简介
? 商业应用的后台数据一般存放在数据库中, 很明显,可以通过 Java 代码来访问数据库。 在 Java 技术系列中,访问数据库的技术叫做 JDBC,它提供了一系列的 API,让 Java 语 言编写的代码连接数据库,对数据库的数据 进行添加、删除、修改和查询
JDBC 简介
? JDBC中以下类或接口
? java.sql.Connection:负责连接数据库
? java.sql.Statement:负责执行数据库 SQL 语句
? java.sql.ResultSet:负责存放查询结果
JDBC 简介
? 针对不同类型的数据库,JDBC 机制中提供了"驱动程序"的 的概念。对于不同的数据库,程序只需要使用不同的驱动
厂商驱动连接数据库
JDBC 简介
? 安装数据库厂商驱动,需要去各自的数据库厂商网站 下载驱动包,用户也许觉得很麻烦。此时,微软公司 提供了一个解决的方案。在微软公司的 Windows 中, 预先设计了一个ODBC(Open Database Connectivity, 开放数据库互连)功能,由于 ODBC 是微软公司的产 品,因此它几乎可以连接到所有在 Windows 平台下 运行的数据库,由它连接到特定的数据库,不需要具 体的驱动。而 JDBC 就只需要连接到 ODBC 就可以 了
JDBC 简介
ODBC 驱动连接数据库
建立 ODBC 数据源
? 在使用 ODBC 之前,需要配置 ODBC 的数据 源,让 ODBC 知道连接的具体数据库
? ODBC 支持连接到各种数据库。如 Oracle、 MySQL、MSSQLServer 等,具体的设置详 见课本图解过程
建立 ODBC 数据源
? 操作如下:
? 首先在控制面板中选择"管理工具",双击"数据源(ODBC)图标"
建立 ODBC 数据源
? 操作如下:
? 在"ODBC 数据源管理器"的"系统 DSN"选项卡中单击"添加"按 钮
建立 ODBC 数据源
? 操作如下:
? 从弹出的"创建新数据源"窗口的数据源名称列表中选择 "Microsoft Acces Driver(*.mdb)" 并单击"完成"按钮
建立 ODBC 数据源
? 操作如下:
? 在弹出的"ODBC Microsoft Access 安装"窗口的"数据源名"文 本框输入自定义的数据源名称,然后点击"选择"按钮,选择 Access 数据库所在的目录,得到的结果如图
JDBC 操作
? Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); ? Connection conn=DriverManager.getConnection("jdbc:odbc:d1","",""); ? PreparedStatement ps=conn.prepareStatement("select * from xinwen"); ? ResultSet rs=ps.executeQuery(); ? while(rs.next()) ? {out.println(rs.getString(2)+"<br>"+rs.getString("zhengwen")+" <p>");} ? rs.close(); ? ps.close(); ? conn.close();
JDBC 操作
用于执行静态 SQL 语句并返回它所生成结果的对象。(声明,陈述) PreparedStatement Statement 的区别: 应该始终以PreparedStatement代替Statement.也就是说,在任何时候都 不要使用Statement
一.代码的可读性和可维护性.
perstmt = con.prepareStatement("insert into tb_name (col1,col2,col2,col4) values (?,?,?,?)");
二.PreparedStatement尽最大可能提高性能.
由于 PreparedStatement 对象已预编译过,所以其执行速度要快于 Statement 对象。每一种数据库 都会尽最大努力对预编译语句提供最大的性能优化.因为预编译语句有可能被重复调用.所以语句在 被DB的编译器编译后的执行代码被缓存下来,那么下次调用时只要是相同的预编译语句就不需要编 译。
三. 极大地提高了安全性.
恶义SQL.String sql = “select * from tb_name where name= ?”+varname+“? and passwd=?”+varpasswd+“?”;如果我们把[? or ?1? = ?1]作为varpasswd传入进来.用户名随意,看看会成为 什么? PreparedStatement可以避免这种情况。
JDBC 操作
? JDBC 的操作分为 4 个步骤:
? 通过 JDBC 连接到 ODBC,并获取连接对象
Class.forName("sun.jdbc.odbc.JdbcOdbcDri ver"); Connection conn = DriverManager.getConnection("jdbc:odbc:D SSchool");
JDBC 操作
? 使用 Statement 接口运行 SQL 语句
Statement stat = conn.createStatement(); stat.executeQuery(SQL 语句);//查询 或者 stat.executeUpdate(SQL 语句);//添加、删除或 修改
JDBC 操作
? 处理 SQL 语句运行结果,这和具体的操 作有关,后面详述 ? 关闭数据库连接:
stat.close();
conn.close();
odbc sql server
jdbc sql server
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); Connection conn = DriverManager.getConnection("jdbc:sqlserver://localhost:1433;DatabaseNam e=tt", "ch2","123"); Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); Connection conn=DriverManager.getConnection("jdbc:odbc:d1","","");
添加数据
rs=ps.executeQuery(); int i = stat.executeUpdate(sql); 它返回一个整型,意思为这条 sql 语句执行受影响的行数,即成功添加的条数 Statement s=conn.createStatement(); String sql1="insert into "; int i=s.executeUpdate(sql1); String sql = "INSERT INTO T_STUDENT(STUNO,STUNAME,STUSEX) VALUES(?,?,?)"; PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1,stuno); ps.setString(2,stuname); ps.setString(3,stusex);
int i = ps.executeUpdate();
删除、修改数据
? 具体代码案例见课本
? 两种操作均调用stat.executeUpdate(sql),并 返回一个整型量
查询数据
? 具体代码案例见课本
? 查询格式: ResultSet rs = stat.executeQuery(sql); 查询到的结果放入 ResultSet 中,实际上是一 个小表格
查询数据
? 游标
是在 ResultSet 中一个可以移动的指针,它指 向一行数据。初始时指向第一行的前一行,实际 上不指向任何数据。rs.next()可以将游标移到下 一行,它的返回值是一个布尔类型,即如果下一 行有数据则返回为 true,否则为 flase。很明显, 可以使用 rs.next()配上 while 循环来对结果进行 遍历
查询数据
? 游标
当游标指向某一行,可以通过 ResultSet 的 getXXX("列名")方法得到这一行的某个数据,
XXX 是该列的数据类型,可以是 String,也可以 是 int 等,但是所有类型的数据都可以用 getString()方法获得。除了通过列名获得数据外, 还可以通过列的编号来获得
查询数据
? 关于游标的注意
? 游标的初始值并不是指向第 1 行数据,而是指向 第 1 行的前面那条数据。所以必须要运行一次 next()函数之后,才能从开始取数据,如果强行取 则会找不到该列而报错
查询数据
? 关于游标的注意
? 从某一行中通过 getXXX()方法取数据每一列只能 取一次,超过一次,程序将会报错,如果需要重 复使用某列数据,可以先定义一个变量,将取出 的数据赋予它,再重复使用
使用 PreparedStatement
? 引出
? 以添加数据为例,在很多情况下,具体需要添加 的值,是由客户自己输入的,因此,应该是一个 个变量。该情况下,SQL 语句的写法就比较麻烦 , 而且依赖了变量,比较容易出错
? PreparedStatement 解决了这个问题
使用 PreparedStatement
? PreparedStatement 是 Statement 的子接口, 功能与 Statement 类似
? 它在 sql 语句中使用了?代替了需要插入的参数
? 用 PreperedStatement 的 setString(n,参数)方 法可以将第 n 个?用传进的参数代替。这样做增加 了程序的可维护性,也增加了程序的安全性
使用 PreparedStatement
? PreparedStatement 是 Statement 的子接口,功能与 Statement 类似 ? 它在 sql 语句中使用了?代替了需要插入的参数 ? 用 PreperedStatement 的 setString(n,参数)方法可以将第 n 个?用传进的参数 代替。这样做增加了程序的可维护性,也增加了程序的安全性
使用 PreparedStatement
? String sql="select * from yonghu where mima =?"; ? PreparedStatement ps=conn.prepareStatement(sql); ? ps.setString(1,context); ? ResultSet rs=ps.executeQuery();
? String sql = "INSERT INTO T_STUDENT(STUNO,STUNAME,STUSEX) VALUES(?,?,?)"; ? PreparedStatement ps = conn.prepareStatement(sql); ? ps.setString(1,stuno); ps.setString(2,stuname); ps.setString(3,stusex);
? int i = ps.executeUpdate();
? Statement ps=conn.createStatement(); ? String sql="insert into… ";
? int i=ps.executeUpdate(sql);
事务
? 在银行转账时,要对数据库进行两个操作, 即将一个账户的钱减少,将另一个账户的钱 增多。但是由于操作的先后顺序,如果在两 个操作之间发生故障,则会导致数据不一致。 因此,需要设计一个事务,在两条语句都被 执行成功后,数据修改才被真正提交(Commit) 放入数据库,否则数据操作回滚(Rollback)
事务
? 在默认情况下,executeUpdate 函数会在数 据库中提交改变的结果,此时,可以用 Connection 来定义该函数是否自动提交改变 结果,并进行事务的提交或者回滚
? Connection 中可以设置 executeUpdate 不要自动提交
事务
? ? ? ? ? try{ Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); conn = DriverManager.getConnection("jdbc:odbc:DSSchool"); Statement stat = conn.createStatement(); conn.setAutoCommit(false);//设置为不要自动提交
?
? ? ? ? ? ? ? ? ? ? ? } } finally{ }
String sql1 = "UPDATE1";
String sql2 = "UPDATE2"; stat.executeUpdate(sql1); stat.executeUpdate(sql2); conn.commit(); //提交以上操作
catch(Exception ex){ conn.rollback(); //回退
conn.close();
sqlserver
? 注意:
? 需要 数据库 用户名 密码
使用厂商驱动进行数据库连接
? 缺点:
? 这类驱动程序的弹性较差,由于是数据库厂商自 己提供的专属驱动程序,往往只适用于自己的数 据库系统,甚至只适合某个版本的数据库系统。 如果后台数据库换了一个或者版本升级了,则就 有可能需要更换数据库驱动程序
? 优点:
? 跨平台
使用厂商驱动进行数据库连接
? 使用厂商驱动,有 2 个步骤:
? 到相应的数据库厂商网站上下载厂商驱动,或者 从数据库安装目录下找到相应的厂商驱动包,拷 贝到项目的 classpath 下 ? 在 JDBC 代码中,设定特定的驱动程序名称和 url
使用厂商驱动进行数据库连接
? 常见数据库的驱动程序名称和 url 如下
? MS SQL Server:驱动程序为: “com.microsoft.jdbc.sqlserver.SQLServerDriver”, url 为: “jdbc:microsoft:sqlserver://[IP]:1433;DatabaseName=[DBName]” 在SQL Server 2000 中加载驱动和URL路径的语句是 String driverName = "com.microsoft.jdbc.sqlserver.SQLServerDriver"; String dbURL = "jdbc:microsoft:sqlserver://localhost:1433; DatabaseName=sample"; 而sql server 2005 中加载驱动和url的语句则为 String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; String dbURL = "jdbc:sqlserver://localhost:1433; DatabaseName=sample";
? ? ? ? ? ?
使用厂商驱动进行数据库连接
? Oracle :驱 动 程 序 为 :" oracle.jdbc.driver.OracleDriver ", url 为 :
"jdbc:oracle:thin:@[ip]:1521:[sid]"
使用厂商驱动进行数据库连接
? MySQL : 驱 动 程 序 为 : " com.mysql.jdbc.Driver " ,
url
为 :
"jdbc:mysql://localhost:3306/[DBName]"
使用厂商驱动进行数据库连接
? 程序能够正常工作的前提是:必须将相 应的包拷贝到项目的 classpath 下去。 在 MyEclipse 中,可以在项目中导入该 包,也能达到效果
本章结束
? 本章总结
? ODBC 数据源的配置 ? 数据库的增删改查
? PreparedStatement 和事务处理
? 使用厂商驱动
? 上机习题