Posted on 2008-10-21 22:24
梦与桥 阅读(228)
评论(0) 编辑 收藏 所属分类:
jsp程序设计
1、使用事务
如果事务中所有命令都能正确执行,就提交这个事务,否则如果有一个命令出错,就回滚这个事务,并返回到提交前的状态,这样可以保护数据库的完整性。一个数据库连接的默认提交方式是自动提交,每个SQL命令一执行就会提交给数据库,所以先要改为非自动提交模式。实例代码如下:
<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@ page import="java.sql.*,javax.naming.*,javax.sql.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>使用数据库事务</title>
</head>
<body>
<%
Connection con = null;
try {
// 通过连接池来获得一个连接
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/sqlserver");
con = ds.getConnection();
PreparedStatement updateAge = null;
String updateString = "update student "
+ "set age = ? where name like ?";
updateAge = con.prepareStatement(updateString);
int[] age = { 45, 39, 25, 96 };
String[] names = { "梁朝伟%", "贝壳汗母%", "小罗%", "霍元甲%" };
int len = age.length;
// 设置事务提交模式为非自动提交
con.setAutoCommit(false);
for (int i = 0; i < len; i++) {
updateAge.setInt(1, age[i]);
updateAge.setString(2, names[i]);
updateAge.executeUpdate();
}
// 上面执行的语句,如果不出现异常则提交 SQL 语句
con.commit();
out.println("<h1>修改成功,事务执行完毕</h1>");
} catch (NamingException ex) {
System.out.println("Name Not Bound : " + ex.getMessage());
} catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
if (con != null) {
try {
System.out.print("Transaction is being ");
System.out.println("rolled back");
// 如果出现异常则事务回滚
con.rollback();
} catch (SQLException excep) {
System.out.print("SQLException: ");
System.out.println(excep.getMessage());
}
}
} finally {// 不管发生不发生异常,要关闭连接,释放资源
try {
if (con != null) {
con.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
%>
</body>
</html>
2、批处理更新
可以向数据库提交多个更新操作,在某些情况下可以大大提高性能。可以利用Statement、PreparedStatement、CallableStatement对象来提交批处理更新。实例代码如下:
<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@ page import="java.sql.*,javax.naming.*,javax.sql.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>使用数据库批处理更新</title>
</head>
<body>
<%
Connection con = null;
Statement stmt = null;
try {
// 通过连接池来获得一个连接
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/sqlserver");
con = ds.getConnection();
stmt = con.createStatement();
con.setAutoCommit(false);
stmt.addBatch("insert into student values(20,'拉登',56)");
stmt.addBatch("insert into student values(21,'张学友',49)");
stmt.addBatch("insert into student values(22,'刘德华',51)");
stmt.addBatch("insert into student values(23,'猪八戒',128)");
int[] updateCounts = stmt.executeBatch();
con.commit();
for (int i = 0; i < updateCounts.length; i++) {
out.println("第" + (i + 1) + "条SQL语句修改数据库记录数 : "
+ updateCounts[i]+"<br>");
}
con.setAutoCommit(true);
ResultSet uprs = stmt.executeQuery("select * from student");
out.println("执行批处理更新后的student表中记录:<br>");
while (uprs.next()) {
String name = uprs.getString("name");
int age = uprs.getInt("age");
out.print(name + " " + age+"<br>");
out.println();
}
// 上面执行的语句,如果不出现异常则提交 SQL 语句
con.commit();
out.println("<h1>修改成功,事务执行完毕</h1>");
uprs.close();
stmt.close();
} catch (NamingException ex) {
System.out.println("Name Not Bound : " + ex.getMessage());
} catch (SQLException ex) {
System.out.println("SQLException: " + ex.getMessage());
if (con != null) {
try {
System.out.print("Transaction is being ");
System.out.println("rolled back");
// 如果出现异常则事务回滚
con.rollback();
} catch (SQLException excep) {
System.out.print("SQLException: ");
System.out.println(excep.getMessage());
}
}
} finally {// 不管发生不发生异常,要关闭连接,释放资源
try {
if (con != null) {
con.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
%>
</body>
</html>
3、操作元数据
1)DatabaseMetaData(数据库元数据)
<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@ page import="java.sql.*,javax.naming.*,javax.sql.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>数据库元数据</title>
</head>
<body>
<%
Connection con = null;
try {
// 通过连接池来获得一个连接
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/sqlserver");
con = ds.getConnection();
// 测试数据库信息
DatabaseMetaData dm = con.getMetaData();
out.println("<h2>1. 数据库的基本信息</h1>");
out.println("Database is " + dm.getDatabaseProductName()+"<br>");
out.println("Database version is "
+ dm.getDatabaseProductVersion()+"<br>");
out.println("JDBC Driver is " + dm.getDriverName()+"<br>");
out.println("JDBC driver version is "
+ dm.getDriverVersion()+"<br>");
// 获取数据库中目录(数据库)的信息
out.println("<h2>2. 数据库中目录(数据库)的信息</h2>");
ResultSet catalogs = dm.getCatalogs();
while (catalogs.next()) {
out.println(catalogs.getString(1));
}
// 获取数据库中模式的信息
out.println("<h2>3. 数据库中模式的信息</h2>");
ResultSet schemas = dm.getSchemas();
while (schemas.next()) {
out.println(schemas.getString(1)+"<br>");
}
// 获取数据库中各个表的情况
out.println("<h2>4. 数据库中各个表的信息</h2>");
ResultSet tables = dm.getTables("pubs", null, null, null);
while (tables.next()) {
for (int i = 0; i < 5; i++) {
out.print(tables.getString(i + 1));
out.print(" | ");
}
out.println();
}
// 获取数据库表中各个列的信息
out.println("<h2>5. 数据库表中各个列的信息</h2>");
ResultSet columns = dm.getColumns(null, null,"student", null);
while (columns.next()) {
for (int i = 0; i < 18; i++) {
out.print(columns.getString(i + 1));
out.print(" | ");
}
out.println();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 用完后要关闭连接,释放资源
if (con != null)
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
%>
</body>
</html>
2)ResultSetMetaData(结果集元数据)
<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@ page import="java.sql.*,javax.naming.*,javax.sql.*" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>结果集元数据</title>
</head>
<body>
<%
Connection con = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 通过连接池来获得一个连接
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/sqlserver");
con = ds.getConnection();
stmt = con.createStatement();
String querySQL1 = "select * from student";
rs = stmt.executeQuery(querySQL1);
// 提取结果集的元数据:
ResultSetMetaData rsmd = rs.getMetaData();
int colCount = rsmd.getColumnCount();
String[] columnNames = new String[colCount];
String[] columnLabels = new String[colCount];
int[] columnTypes = new int[colCount];
for (int i = 0; i < colCount; i++) {
columnNames[i] = rsmd.getColumnName(i + 1);
columnLabels[i] = rsmd.getColumnLabel(i + 1);
columnTypes[i] = rsmd.getColumnType(i + 1);
}
out.println("<h2>结果集的元数据如下:</h2>");
out.println("<h2>----------------------</h2>");
out.println("列名:");
for (int i = 0; i < colCount; i++) {
out.print(columnLabels[i] + "\t");
}
out.println("<br>");
out.println("列标签:");
for (int i = 0; i < colCount; i++) {
out.print(columnNames[i] + "\t");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
// 用完后要关闭连接,释放资源
if (con != null)
con.close();
} catch (Exception e) {
e.printStackTrace();
}
}
%>
</body>
</html>
4、JavaBean操作数据库
1)JavaBean
package jdbcdemo;
/** *//**
* 封装数据库操作的JavaBean
* @author Administrator
*
*/
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import java.util.*;
public class QueryBean {
private Connection conn=null;
private Vector data=new Vector();
private Connection getConn(){
try{
// 通过连接池来获得一个连接
Context initContext = new InitialContext();
Context envContext = (Context)initContext.lookup("java:/comp/env");
DataSource ds = (DataSource)envContext.lookup("jdbc/sqlserver");
conn= ds.getConnection();
}catch(Exception e){
e.printStackTrace();
}
return conn;
}
public Vector getData(){
try{
getConn();
Statement st = conn.createStatement();
String query = "select id,name from student";
// 获得一个结果集
ResultSet rs = st.executeQuery(query);
// 获得结果集的元数据(表及相关的信息)
ResultSetMetaData rsmt = rs.getMetaData();
// 得到结果集有几列
int num = rsmt.getColumnCount();
while (rs.next()) {
Vector row=new Vector();
// 输出每一行的值
for (int i = 1; i <= num; i++) {
String temp = rs.getString(i);
row.add(temp);
}
data.add(row);
}
}catch(Exception e){
e.printStackTrace();
}finally{
try {
// 用完后要关闭连接,释放资源
if (conn != null)
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return data;
}
}
2)显示
<%@ page language="java" contentType="text/html; charset=GBK"%>
<%@ page import="java.util.*" %>
<jsp:directive.page import="jdbcdemo.QueryBean"/>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>查询数据库数据</title>
</head>
<body>
<jsp:useBean id="sel" scope="page" class="jdbcdemo.QueryBean"></jsp:useBean>
<%
try {
out.println("<H1>调用JavaBean查询数据</H1>");
out.println("<table width='600' border='1'>");
Vector data=sel.getData();
for(int i=0; i<data.size();i++){
out.println("<tr>");
Vector row=(Vector)data.elementAt(i);
for(int j=0;j<row.size();j++){
out.println("<td>"+row.elementAt(j)+"</td>");
}
out.println("</tr>");
}
out.println("</table>");
} catch (Exception e) {
e.printStackTrace();
}
%>
</body>
</html>
5、JavaBean操作数据库
所谓SQL注入式攻击,就是攻击者把SQL命令插入到Web表单的输入或页面请示的查询字符串,欺骗服务器执行恶意的SQL命令。以验证用户身份登录为例,网页中的Web表单要求用户输入用户名和密码,如果后台采用如下方式构造SQL语句来验证用户和密码是否正确:select * from admin where username=' "&user&" ' and password=' "&pwd&" '
那么,如果输入的用户名是:1 'or' 1 '='1,后台的查询语句将会变成:
select * from admin where username=' 1 'or' 1 '= ' 1 ' and password=' "&pwd&" '
这样查询语句就通过了,从而就可以进入管理界面。所以防范的时候需要对用户的输入进行检查,特别是一些特殊的字符串,比如单引号、双引号、分号、逗号、冒号、连接号等,对它们进行转换或者过滤。
要防范SQL注入式攻击有两种方式:一种是编写客户端代码以阻止用户提交包含敏感信息的数据;另一种是编写服务端代码以在服务端进行业务操作之前,对用户提交的参数进行检查。
1)客户端防范SQL注入式攻击的JavaScript代码:
<script language="javascript">
<!--
var url=location.search;
var re=/^\? (.*)(select%20|insert%20|delete%20|count\(|drop%20table|update%20truncate%20|asc \(|mid\(|char \(|xp_cmdshell|exec%20master|net%20localgroup%20administrators|\"|:|net%20user|\'|%20)(.*)$/gi;
var e=re.test(url);
if(e)
{
laert("含有非法字符");
location.href="error.jsp";
}
//-->
2)服务器端防范SQL注入式攻击的Java代码:
booleancheckParam(String param){
//列出要查找的敏感字符串
String[] checkstr={"'","%","delete","insert"};
for(int i=0;i<checkstr.length;i++){
if(param.indexOf(checkstr[i]>=0){
return false;
}
}
return true;
}