`
wgllz
  • 浏览: 109818 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

适合BS模式项目的录入页面

    博客分类:
  • PHP
阅读更多
说明:
当焦点不在表格内的input时,回车键复制最后一行,delete删除键最后一行
选择checkbox,可以进行复制,删除
双击表格会出现菜单,自动收集该列已存在数据,选中自动填充 这里是亮点
数据发送采用ajax(自定义的一个ajax类,blog已发布过)一行一行的发送
兼容IE6和Firefox1.5 符合W3C
本表格一切功能都是为了减少输入录入工作,适合大项目开放使用

程序代码

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="MSThemeCompatible" content="No">
<title>无标题文档</title>
<script type="text/JavaScript">
<!--
//////////////////////////////////////////页面初始化///////////////////////////////////////
beginListen();
//////////////////////////////////////////页面初始化///////////////////////////////////////
//////////////////////////////////////////ajax类///////////////////////////////////////
function Ajax(url,recvT,stringS,resultF) {
this.url = url;
this.stringS = stringS;
this.xmlHttp = this.createXMLHttpRequest();
if (this.xmlHttp == null) {
alert("erro");
return;
}
var objxml = this.xmlHttp;
objxml.onreadystatechange = function (){Ajax.handleStateChange(objxml,recvT,resultF)};
}

Ajax.prototype.createXMLHttpRequest = function() {
try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch(e) {}
try { return new ActiveXObject("Microsoft.XMLHTTP"); } catch(e) {}
try { return new XMLHttpRequest(); } catch(e) {}
return null;
}

Ajax.prototype.createQueryString = function () {
var queryString = this.stringS;
return queryString;
}

Ajax.prototype.get = function () {
url = this.url;
var queryString = url+"?timeStamp=" + new Date().getTime() + "&" + this.createQueryString();
this.xmlHttp.open("GET",queryString,true);
this.xmlHttp.send(null);
}

Ajax.prototype.post = function() {
url = this.url;
var url = url + "?timeStamp=" + new Date().getTime();
var queryString = this.createQueryString();
this.xmlHttp.open("POST",url,true);
this.xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
this.xmlHttp.send(queryString);
}

Ajax.handleStateChange = function (xmlHttp,recvT,resultF) {
if (xmlHttp.readyState == 4) {
if (xmlHttp.status == 200) {
resultF(recvT?xmlHttp.responseXML:xmlHttp.responseText);
} else {
alert("您所请求的页面有异常。");
}
}
}
//////////////////////////////////////////ajax类///////////////////////////////////////

//////////////////////////////////////////处理鼠标事件///////////////////////////////////////
//表格变色
var toBeColor = "#F8F9FC";
var backColor = "#FFFFFF";
function onChangTrColor(obj) {
obj.parentNode.style.backgroundColor = toBeColor;
obj.style.backgroundColor = toBeColor;
var inputs = obj.parentNode.parentNode.getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++ ){
inputs[i].style.backgroundColor = toBeColor;
inputs[i].parentNode.style.backgroundColor = toBeColor;
}
}

function outChangTrColor(obj) {
obj.parentNode.style.backgroundColor = backColor;
obj.style.backgroundColor = backColor;
var inputs = obj.parentNode.parentNode.getElementsByTagName("input");
for (var i = 0; i < inputs.length; i++ ){
inputs[i].style.backgroundColor = backColor;
inputs[i].parentNode.style.backgroundColor = backColor;
}
}

//////////////////////////////////////////处理鼠标事件///////////////////////////////////////

//////////////////////////////////////////处理页面操作///////////////////////////////////////
//复制所选
function copySelect(){
var checkboxs = document.getElementsByName("checkbox");
for (var i=0; i<checkboxs.length; i++) {
if(checkboxs[i].checked == true){
checkboxs[i].checked = false;
copyTr(checkboxs[i]);
checkboxs[i].checked = true;
}
}
}

function copyTr(obj) {
var tbody = document.getElementById("tbData").getElementsByTagName("tbody")[0];
var Str = obj.parentNode.parentNode;
var tr = Str.cloneNode(true);
tbody.appendChild(tr);
}

//删除所选
function delSelect(){
var checkboxs = document.getElementsByName("checkbox");
var table = document.getElementById("tbData");
var tr = table.getElementsByTagName("tr");
for (var i=0; i<checkboxs.length; i++) {
if(tr.length==2){
checkboxs[i].checked = false;
return;
}
if(checkboxs[i].checked==true){
removeTr(checkboxs[i]);
i=-1;
}
}
}

function removeTr(obj) {
var sTr = obj.parentNode.parentNode;
sTr.parentNode.removeChild(sTr);
}

//全选按钮
function selectAll() {
var checkboxs = document.getElementsByName("checkbox");
var mark = true;
for (var i=0; i<checkboxs.length; i++) {
if (checkboxs[i].checked==false){mark = false}
}
if (mark){
for (var i=0; i<checkboxs.length; i++) {
checkboxs[i].checked = false;
}
}else{
for (var i=0; i<checkboxs.length; i++) {
checkboxs[i].checked = true;
}
}
}

//////////////////////////////////////////处理页面操作///////////////////////////////////////

//////////////////////////////////////////处理键盘操作///////////////////////////////////////
//键盘事件
function beginListen(){
if(document.addEventListener){
document.addEventListener("keydown",keyDown,true);
}else{
document.attachEvent("onkeydown",keyDown);
}
}
function stopListen(){
document.detachEvent("onkeydown",keyDown);
}

//处理键盘事件
function keyDown(event){
if(event.keyCode==13){addTr()}
if(event.keyCode==46){delTr()}
}

//增加表格
function addTr() {
var tbody = document.getElementById("tbData").getElementsByTagName("tbody")[0];
var sTr = tbody.getElementsByTagName("tr")[0];
var tr = sTr.cloneNode(true);
tbody.appendChild(tr);
}

//增加表格
function addTr() {
var tbody = document.getElementById("tbData").getElementsByTagName("tbody")[0];
var trs = tbody.getElementsByTagName("tr");
var sTr = trs[trs.length-1];
var tr = sTr.cloneNode(true);
tbody.appendChild(tr);
}

//删除表格
function delTr() {
var table = document.getElementById("tbData");
var tr = table.getElementsByTagName("tr");
if(tr.length==2){return;}
var lastTr = tr[tr.length-1];
lastTr.parentNode.removeChild(lastTr);
}


//////////////////////////////////////////处理键盘操作///////////////////////////////////////

//////////////////////////////////////////处理按钮事件///////////////////////////////////////
//自动填充
var currentObj;
function showDiv(event,obj) {
var eX = event.clientX;
var eY = event.clientY;
var sY = document.body.parentNode.scrollTop;
var dY = eY + sY;
var divShowInput = document.getElementById("divShowInput");
divShowInput.style.top = dY + "px";
divShowInput.style.left = eX+"px";
divShowInput.style.display = "block";
currentObj = obj;
////智能菜单////
fixMenu();
//判断焦点位置
var tds = obj.parentNode.parentNode.getElementsByTagName("td");
var tdOrder;
for (var i = 0; i < tds.length; i++ ){
if(tds[i] === obj.parentNode){
tdOrder = i;
}
}
//填充标题标题
var tdTitleTr = document.getElementById("tbData").getElementsByTagName("tr")[0];
var tdTitle = tdTitleTr.getElementsByTagName("td")[tdOrder];
document.getElementById("barTitle").innerHTML = tdTitle.innerHTML;
//收集表格信息//判断重复
var trs = obj.parentNode.parentNode.parentNode.getElementsByTagName("tr");
var autoFillP = document.getElementById("autoFillP");
var bankM = true;
for (var i = 0; i < trs.length; i++ ){
var inputValue = trs[i].getElementsByTagName("td")[tdOrder].getElementsByTagName("input")[0].value;
if (inputValue != "") {
bankM = false;
var menus = autoFillP.getElementsByTagName("a");
if(menus.length > 0) {
var beliveM = true;
for (var j = 0; j < menus.length; j++ ){
if(menus[j].firstChild.nodeValue == inputValue) {
beliveM = false;
}
}
if(beliveM){
var Svalue = document.createElement("a");
Svalue.setAttribute("href","javascript:void 0");
Svalue.onclick = function () {fillInput(this)};
var Stext = document.createTextNode(inputValue);
Svalue.appendChild(Stext);
autoFillP.appendChild(Svalue);
}
}else{
var Svalue = document.createElement("a");
Svalue.setAttribute("href","javascript:void 0");
Svalue.onclick = function () {fillInput(this)};
var Stext = document.createTextNode(inputValue);
Svalue.appendChild(Stext);
autoFillP.appendChild(Svalue);
}
}
}
if(bankM) {
var Svalue = document.createElement("a");
Svalue.setAttribute("href","javascript:void 0");
var Stext = document.createTextNode("数据空");
Svalue.appendChild(Stext);
autoFillP.appendChild(Svalue);
}
}

function fillInput(obj) {
currentObj.value = obj.innerHTML;
var divShowInput = document.getElementById("divShowInput");
divShowInput.style.display = "none";
}

function clearInput() {
currentObj.value = "";
var divShowInput = document.getElementById("divShowInput");
divShowInput.style.display = "none";
}

function hideDiv(obj) {
obj.parentNode.style.display = "none";
}

//删除智能菜单已有数据
function fixMenu() {
var autoFillP = document.getElementById("autoFillP");
var values = autoFillP.getElementsByTagName("a");
for (var i = values.length-1; i >= 0; i-- ){
autoFillP.removeChild(values[i]);
}
}
//////////////////////////////////////////处理按钮事件///////////////////////////////////////

//////////////////////////////////////////数据发送///////////////////////////////////////

//////////////////////////////////////////数据发送///////////////////////////////////////
function sendData() {
var sendName = new Array("ok","A1","A2","A3","A4","A5","A6","A7","A8","A9","A10","A11");
var trs = document.getElementById("tbData").getElementsByTagName("tbody")[0].getElementsByTagName("tr");
for (var i = 0; i < trs.length; i++) {
var sendValue = new Array();
var values = trs[i].getElementsByTagName("input");
var postString = sendName[1] + "=" + values[1].value;;
for (var j = 2; j < values.length; j++) {
postString = postString + "&" + sendName[j] + "=" + values[j].value;
}
var SendAjax = new Ajax("isave.asp",0,postString,sendok);
SendAjax.post();
function sendok(revData){
alert(revData);
}
}
}

//////////////////////////////////////////数据发送///////////////////////////////////////


//-->
</script>
<style type="text/css">
<!--
body {
font-family: Arial, Helvetica, sans-serif;
font-size: 12px;
background-color: #E9EDF7;
}
#tbBackground {
background-color:#FFFFFF;
text-align:center;
}
#tbData {
background-color:#DDE3EC;
}
#tbData td {
background-color:#FFFFFF;
}
#tbData input {
width:50px;
border:none;
}
#tbData .checkbox {
width:15px;
}

#tbData thead {
}

#tbTopOpt a{
display:block;
width:80px;
padding:5px;
background-color:#F8F9FC;
border:solid 1px #999999;
color:#000000;
text-decoration: none;
}
#tbTopOpt a:hover{
background-color:#DDE3EC;
}
#tbBomOpt a{
display:block;
width:80px;
padding:5px;
background-color:#F8F9FC;
border:solid 1px #999999;
color:#000000;
text-decoration: none;
}
#tbBomOpt a:hover{
background-color:#DDE3EC;
}
#tbData a{
color:#000000;
text-decoration: none;
}

#divShowInput {
position:absolute;
top:30px;
left:350px;
z-index:10;
background-color:#F8F9FC;
display:none;
border:solid 1px #DDE3EC;
width:100px;
overflow:hidden;
}
#divShowInput a {
display:block;
background-color:#F8F9FC;
color:#000000;
text-decoration: none;
text-align:center;
width:auto;
}
#divShowInput a:hover {
background-color:#DDE3EC;
border-left:solid 2px #FF0000;
border-right:solid 2px #FF0000;
color:#FF0000;
}

#divShowInput p {
cursor:hand;
margin:0;
padding:0;
background-color:#F8F9FC;
text-align:center;
border-bottom:double #DDE3EC;
}
-->
</style>
</head>

<body>
<div id="divShowInput">
<p id="barTitle" onClick="hideDiv(this)"></p>
<p id="defComP" onClick="hideDiv(this)">
<a xx=void 0" onClick="clearInput()">清空</a>
</p>
<p id="autoFillP">
<a xx=void 0" onClick="fillInput(this)">Llinzzi</a>
<a xx=void 0" onClick="fillInput(this)">Huanhuan</a>
<a xx=void 0" onClick="fillInput(this)">Tom.com</a>
<a xx=void 0" onClick="fillInput(this)">超级长的长长长长长长</a>
</p>
</div>
<table id="tbBackground" width="760" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td><table id="tbTopOpt" width="700" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td height="40" width="125"><a xx=void 0" onClick="copySelect()">复制所选</a></td>
<td width="537"><a xx=void 0" onClick="delSelect()">删除所选</a></td>
<td width="38"> </td>
</tr>
</table></td>
</tr>
<tr>
<td><table id="tbData" width="750" border="0" align="center" cellpadding="0" cellspacing="1">
<thead>
<tr>
<td height="25" ><a xx=void 0" onClick="selectAll();">全选</a></td>
<td>A1</td>
<td>A2</td>
<td>A3</td>
<td>A4</td>
<td>A5</td>
<td>A6</td>
<td>A7</td>
<td>A8</td>
<td>A9</td>
<td>A10</td>
<td>A11</td>
</tr>
</thead>
<tbody>
<tr>
<td><input class="checkbox" type="checkbox" name="checkbox" value="checkbox"></td>
<td><input name="A1" type="text" onFocus="stopListen()" onBlur="beginListen()" onDblClick="showDiv(event,this)" onMouseOver="onChangTrColor(this)" onMouseOut="outChangTrColor(this)"></td>
<td><input name="A2" type="text" onFocus="stopListen()" onBlur="beginListen()" onDblClick="showDiv(event,this)" onMouseOver="onChangTrColor(this)" onMouseOut="outChangTrColor(this)"></td>
<td><input name="A3" type="text" onFocus="stopListen()" onBlur="beginListen()" onDblClick="showDiv(event,this)" onMouseOver="onChangTrColor(this)" onMouseOut="outChangTrColor(this)"></td>
<td><input name="A4" type="text" onFocus="stopListen()" onBlur="beginListen()" onDblClick="showDiv(event,this)" onMouseOver="onChangTrColor(this)" onMouseOut="outChangTrColor(this)"></td>
<td><input name="A5" type="text" onFocus="stopListen()" onBlur="beginListen()" onDblClick="showDiv(event,this)" onMouseOver="onChangTrColor(this)" onMouseOut="outChangTrColor(this)"></td>
<td><input name="A6" type="text" onFocus="stopListen()" onBlur="beginListen()" onDblClick="showDiv(event,this)" onMouseOver="onChangTrColor(this)" onMouseOut="outChangTrColor(this)"></td>
<td><input name="A7" type="text" onFocus="stopListen()" onBlur="beginListen()" onDblClick="showDiv(event,this)" onMouseOver="onChangTrColor(this)" onMouseOut="outChangTrColor(this)"></td>
<td><input name="A8" type="text" onFocus="stopListen()" onBlur="beginListen()" onDblClick="showDiv(event,this)" onMouseOver="onChangTrColor(this)" onMouseOut="outChangTrColor(this)"></td>
<td><input name="A9" type="text" onFocus="stopListen()" onBlur="beginListen()" onDblClick="showDiv(event,this)" onMouseOver="onChangTrColor(this)" onMouseOut="outChangTrColor(this)"></td>
<td><input name="A10" type="text" onFocus="stopListen()" onBlur="beginListen()" onDblClick="showDiv(event,this)" onMouseOver="onChangTrColor(this)" onMouseOut="outChangTrColor(this)"></td>
<td><input name="A11" type="text" onFocus="stopListen()" onBlur="beginListen()" onDblClick="showDiv(event,this)" onMouseOver="onChangTrColor(this)" onMouseOut="outChangTrColor(this)"></td>
</tr>
</tbody>
</table></td>
</tr>
<tr>
<td><table width="700" border="0" align="center" cellpadding="0" cellspacing="0" id="tbBomOpt">
<tr>
<td height="40" width="125"><a xx=void 0" onClick="copySelect()">复制所选</a></td>
<td width="537"><a xx=void 0" onClick="delSelect()">删除所选</a></td>
<td width="537"><a xx=void 0" onClick="sendData()">提交</a></td>
<td width="38"> </td>
</tr>
</table></td>
</tr>
</table>
</body>
</html>

8:12 | 添加评论 | 阅读评论 (1) | 固定链接 | 引用通告 (0) | 记录它
5月11日
hibernate+ webwork+ spring添删改查示例
  (本故事除了部分点明道姓并具有故事详细发生的具体时间点地等部分情节以外,其它内容纯属虚构,若有雷同,纯属巧合。)

  看本文的朋友请先看上一篇文章:玩玩Spring之struts+hibernate+spring添删改查示例,否则会看不懂滴(的)。

  该示例程序的运行效果先睹为快:
  http://www.easyjf.com/html/bbs/20060510/1512699849613700.htm?ejid=1141219960424115

  新同学:听说Struts有很多致命的技术缺陷啊,是吗?
  大牛:恩,专家都说了。
  新同学:听说J2EE程序员很讲究艺术及高雅,能举个例子吗?
  大牛:对啊,MVC中webwork就是高雅啊,用他写起程序来真是赏心悦目,华丽得真是没法容易。

  主演:webwork
  配角:struts、jsp、hibernate、spring等
  
  借着吹spring的风,今天笔者给大家介绍一种很多人都非常欣赏的轻量极、高雅的J2EE组合,那就是hibernate+ webwork+ spring。说介绍不准确,应该还只是一个简单的演示,毕竟webwork的赞歌已经有很多人唱过了,这里就不重复(主要还是因为唱不出来,惭愧!)。我只希望能通过简单的代码,让大家去体会webwork的高雅、过人之处。

  同样是上一篇中有关一个用户表“添删改查”的例子,这里只是把Web层改成使用webwork实现,下面我们直接介绍Web开发部分,其它部分的开发请照搬前面一篇的例子,新人可以结合上个例子中的Struts部分进行看。

1、写Action

  webwork跟Struts乃至其它的MVC框架一样,都有一个处理Web请求的Action,我们来看看本例子中这个Action的内容。下面是UserManageAction.java的全部代码:

package com.easyjf.webwork.action;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import com.easyjf.example.business.IUser;
import com.easyjf.example.business.IUserService;
import com.easyjf.util.CommUtil;
import com.easyjf.web.tools.IPageList;
import com.easyjf.web.tools.ListQuery;
import com.easyjf.web.tools.PageList;
import com.opensymphony.webwork.interceptor.ParameterAware;
import com.opensymphony.xwork.ActionSupport;
import com.opensymphony.xwork.Preparable;
public class UserManageAction extends ActionSupport implements ParameterAware,Preparable {
private List allUser;
private IUserService userService;
private IUser user;
private Map parameters;
//用户查询
public String query() throws Exception {
String[] temp=(String[])parameters.get("page");
int currentPage=CommUtil.null2Int(temp!=null?temp[0]:"0");
temp=(String[])parameters.get("pageSize");
int pageSize=CommUtil.null2Int(temp!=null?temp[0]:"0");
if(currentPage<1)currentPage=1;
if(pageSize<1)pageSize=10;
String scope="1=1";
Collection paras=new ArrayList();
temp=(String[])parameters.get("orderType");
String orderType=CommUtil.null2String(temp!=null?temp[0]:"");
temp=(String[])parameters.get("orderField");
String orderField=CommUtil.null2String(temp!=null?temp[0]:"");
temp=(String[])parameters.get("queryUserName");
String userName=CommUtil.null2String(temp!=null?temp[0]:"");
temp=(String[])parameters.get("queryTel");
String tel=CommUtil.null2String(temp!=null?temp[0]:"");
if(!userName.equals(""))
{
scope+=" and userName like ?";
paras.add("%"+userName+"%");
}
if(!tel.equals(""))
{
scope+=" and tel like ?";
paras.add("%"+tel+"%");
}
if(orderField.equals(""))//默认按用户名排序
{
orderField="userName";
orderType="desc";
}
if(!orderField.equals(""))
{
scope +=" order by "+orderField;
if(!orderType.equals(""))scope+=" "+orderType;
}
IPageList pList=new PageList(new ListQuery(userService.query(scope,paras)));
pList.doList(pageSize,currentPage,"","");
if(pList!=null){
this.parameters.put("list",pList.getResult());
this.parameters.put("pages",new Integer(pList.getPages()));
this.parameters.put("rows",new Integer(pList.getRowCount()));
this.parameters.put("page",new Integer(pList.getCurrentPage()));
this.parameters.put("gotoPageHTML",CommUtil.showPageHtml(pList.getCurrentPage(),pList.getPages()));
}
this.parameters.put("orderType",orderType);
this.parameters.put("orderField",orderField);
this.allUser = userService.query(scope,paras);
return execute();
}
//添加或修改用户
public String edit() throws Exception
{
return execute();
}
//删除用户
public String del() throws Exception
{
if(user!=null && userService.del(this.user))
{
this.parameters.put("msg","数据删除成功!");
}
else
{
this.parameters.put("msg","数据修改失败");
}
return query();
}
//保存用户信息
public String save() throws Exception
{
IUser obj=this.getUser();
boolean ret=false;
if(obj!=null){
if((obj.getCid()!=null)&&(!obj.getCid().equals("")))ret=userService.update(user);
else ret=userService.save(user);
}
if(ret)
{
this.parameters.put("msg","数据操作成功!");
}
else
{
this.parameters.put("msg","数据操作失败");
}
return query();
}
public IUserService getUserService() {
return userService;
}
public List getAllUser() {
return allUser;
}
public IUser getUser() {
return user;
}
public void setUser(IUser user) {
this.user = user;
}
public void setUserService(IUserService userService)
{
this.userService=userService;
}
public void setParameters(Map parameters) {
this.parameters=parameters;
}
public Map getParameters() {
return parameters;
}
public void prepare() throws Exception {
this.form2Obj();
}
//根据页面参数创建IUser对象
private void form2Obj() {
String[] temp=(String[])parameters.get("cid");
String cid=temp!=null?temp[0]:"";
IUser user=null;
if(cid!=null && (!cid.equals("")))user=userService.read(cid);
if(user==null)user=userService.newUser();
setUser(user);
}
}


2、写页面文件

  xwork支持多种页面模板,可以是JSP,也可以是Freemarker等,这里我们使用的是大家比较熟悉的JSP作模板。页面同样分为userEdit.jsp以及userList.jsp两个,模板中使用了一些wework的标签,(还好没有全部搞成标签,呵呵!),大家注意观察以<ww: 开头的标签写法就OK了,可以对照Struts的标签看一下。这两个页面从我们这个示例的完整源代码中可以得到,完整示例源码下载地址:

  http://www.easyjf.com/html/bbs/20060510/1512699849613700.htm?ejid=1141219960424115

3、配置xwork.xml

  可以理解成struts中的struts-config.xml文件,当然等你真正熟悉他以后,发现他的配置文件中的玩艺及技术含量都要比Struts牛的多。下面是xwork.xml文件的全部内容:

  <!DOCTYPE xwork PUBLIC "-//OpenSymphony Group//XWork 1.1.1//EN" "http://www.opensymphony.com/xwork/xwork-1.1.1.dtd">
<xwork>
<include file="webwork-default.xml"/>
<package name="userManage" extends="webwork-default" namespace="/userManage">
<action name="query" class="com.easyjf.webwork.action.UserManageAction" method="query">
<result>/userList.jsp</result>
<interceptor-ref name="params" />
<interceptor-ref name="basicStack"/>
</action>
<action name="edit" class="com.easyjf.webwork.action.UserManageAction" method="edit">
<result>/userEdit.jsp</result>
<interceptor-ref name="params" />
<interceptor-ref name="basicStack"/>
</action>
<action name="save" class="com.easyjf.webwork.action.UserManageAction" method="save">
<result name="input">/userEdit.jsp</result>
<result>/userList.jsp</result>
</action>
<action name="del" class="com.easyjf.webwork.action.UserManageAction" method="del">
<result>/userList.jsp</result>
</action>
</package>
</xwork>


4、修改web.xml文件

  以Struts类似,同样需要修改web.xml文件,才能让webwork处理指定的请求。下面是本例中的web.xml文件的全部内容:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<filter>
<filter-name>webwork</filter-name>
<filter-class>com.opensymphony.webwork.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>webwork</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>

  通过上面的配置,使得所有的请求都会交给webwork处理。

  好,现在一个完整的webwork示例程序就完了。不知webwork新朋友注意到没,webwork中没有了ActionForm Bean,配置文件也相对比较清晰明了,Action中的方法不再有类似public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response)这样一大串让人看起来就不爽的参数,其干净得一个参数也没有。大家可以闭上眼睛摸着脑门再体会一下Webwork的Action的写法,是不是要简洁、华丽、优雅得多。

  当然,那么多技术牛人在支持webwork,并不是单看中这个Action的简洁,webwork本身还有很多东西,还包括AJAX支持,报表集成,强大的验证系统以及IOC等,其中有很多是Spring也有的东西,仅从技术的角度来看,笔者也认为他确实能称上是数一数二的。

  当然,本人不是webwork的粉丝,因此其它MVC框架的粉丝这里不要PK我,Struts的朋友就更不应该了,因为webwork开发团队与struts团队已经合并了,合并后的作品Apache Struts Action 2.0也即将出来了。Tapestry 、JSF的粉丝看到这里也别纳闷,有竞争才有技术进步嘛。
  
  好,今天就先玩到这里。由于笔者对webwork只是粗浅的看了一下,因此也许还不能完全通过这个示例表述出webwork的原意。还请webwork的超级粉丝或专家来帮忙补充一下,若发现不足的地方,请不吝批评指教。

  本示例的全部源码下载地址:
  http://www.easyjf.com/html/bbs/20060510/1512699849613700.htm?ejid=1141219960424115
 

  本示例的运行效果图:

  http://www.easyjf.com/html/bbs/20060510/1512699849613700.htm?ejid=1141219960424115
  
  (备注:由于笔者不想拐弯抹角浪费大家玩的时间,有些“表白”难免过于直接,还请不喜欢Spring或者过分喜欢Spring的同行多多见谅! 本文中的“我们”,仅指与笔者有着同样成长经历的80后人,对于文章提到的观点,多数皆属于笔者个人观点,不代表任何人。
  本文作者:EasyJF开源团队 大峡 版权归EasyJF开源团队所有,欢迎转载,转载请保留作者版权声明,谢谢!)


关于玩玩Spring系列,玩的过程及结果将会不定期在以下三个网站全球同步公布:
1.EasyJF开源团队官方网站,网址:http://www.easyjf.com
2.笔者的Blog,网址:http://www.blogjava.net/daxia/
3.Java研究组织(JR) ,网址:http://www.javaresearch.org
欢迎更多跟我一样爱玩的哥哥姐姐弟弟妹妹一起来玩。
7:24 | 添加评论 | 固定链接 | 引用通告 (0) | 记录它
4月30日
java实现精确的四舍五入
java代码:


源文件Arith.java:
import java.math.BigDecimal;

/**
* 由于Javaμ募虻ダ嘈筒荒芄痪·的对浮点数进行运算,这个工具类提供精
* 确的浮点数运算,包括加减乘除和四舍五入。
*/

public class Arith{
//默认除法运算精度
private static final int DEF_DIV_SCALE = 10;
//这个类不能实例化

private Arith(){
}

/**
* 提供精确μ募ó法运算。
* @param v1 被加数
* @param v2 加数
* @return 两个参数的和
*/
public static double add(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.add(b2).doubleValue();

}

/**
* 提供精确μ募?法运算。
* @param v1 被减数
* @param v2 减数
* @return 两个参数的差
*/

public static double sub(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.subtract(b2).doubleValue();
}

/**
* 提供精确的乘法运算。
* @param v1 被乘数
* @param v2 乘数
* @return 两个参数的积
*/
public static double mul(double v1,double v2){
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.multiply(b2).doubleValue();
}

/**
* 提供(相对)精确的除法运算,当发生除不尽的情况时,精确到
* 小数点以后10位,以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @return 两个参数的商
*/
public static double div(double v1,double v2){
return div(v1,v2,DEF_DIV_SCALE);
}

/**
* 提供(相对)精确的除法运算。当发生除不尽的情况时,由scale参数指
* 定精度,以后的数字四舍五入。
* @param v1 被除数
* @param v2 除数
* @param scale 表示表示需要精确到小数点以后几位。
* @return 两个参数的商
*/
public static double div(double v1,double v2,int scale){
if(scale<0){
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b1 = new BigDecimal(Double.toString(v1));
BigDecimal b2 = new BigDecimal(Double.toString(v2));
return b1.divide(b2,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}

/**
* 提供精确的小数位四舍五入处理。
* @param v 需要四舍五入的数字
* @param scale 小数点后保留几位
* @return 四舍五入后的?峁?
*/
public static double round(double v,int scale){
if(scale<0){
throw new IllegalArgumentException(
"The scale must be a positive integer or zero");
}
BigDecimal b = new BigDecimal(Double.toString(v));
BigDecimal one = new BigDecimal("1");
return b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();
}
};

2:30 | 添加评论 | 固定链接 | 引用通告 (0) | 记录它
4月28日
设计之初的一些思考
设计oo的时候,你要分析需求,设计各个模块的通信接口,这个过程,同样需要经验,同样需要摸索,同样没有一踀而就的捷径。

但是,oo设计的时候又要避免过度,一些时候,在是否通过接口预留灵活性,提取容易变化的部分,或者是尽量简单之间,还是有冲突的。你需要做一个艰难的猜测和抉择。
而一旦抉择作出,以后如果发现事情进展不如所愿,那么改动接口的代价相当的大。

OO的关键是需求。
所谓"refactor",不过也是强调需求,让你不要自作聪明地瞎假设需求而复杂化设计。时刻着眼于当前的需求。这样,一旦需求变更,所浪费的力气可以保证最小,而且,船小才好调头嘛。
如果需求分析的不好,一切就歇菜了,虽然因为一些比如ioc之类的设计方法能让你不至于推到重来,但是需求仍然是重中之重。

那些什么上下文没有,上来就说“怎么用OO来做一个人骑车呀?”,“是人.骑(车)呀?还是车.被骑(人)?”纯粹是没头没脑地瞎掰。

而CO的关键则是组合子和组合规则的设计。这些组合方法必须非常精巧,尽量正交。组合子的设计既要简单(越简单才越容易被组合),还要完整。
比如说,对整数这个组合子,我们有+-*等组合方法,这样只要有了0,1这两个组合子,我们就可以构造出整个整数世界。
可是,精巧的组合子设计也不是那么容易的。需要有一点点数学的感觉和严密的逻辑思维基础。

而如果使用co,在设计简单的各个组合子的时候,你会以一种非常渐进式的方式来发现:哦,原来的组合子设计不够正交,有这个地方可以抽出来,好,抽出来,把波及到的几个组合子的设计修改一下。

因为组合子都非常简单,这个变化的波及范围一般来说相当小。

细节封装。这个封装不是一般OO意义上的封装,而是说:把要实现的接口细节封装起来,让客户通过预定义好的组合方式来扩展,而不是象oo那样让用户实现实现这个接口来扩展。
10:44 | 添加评论 | 固定链接 | 引用通告 (0) | 记录它
JDBC连接数据库经验集萃
Java数据库连接(JDBC)由一组用 Java 编程语言编写的类和接口组成。JDBC 为工具/数据库开发人员提供了一个标准的 API,使他们能够用纯Java API 来编写数据库应用程序。然而各个开发商的接口并不完全相同,所以开发环境的变化会带来一定的配置变化。本文主要集合了不同数据库的连接方式。
一、连接各种数据库方式速查表
下面罗列了各种数据库使用JDBC连接的方式,可以作为一个手册使用。

1、Oracle8/8i/9i数据库(thin模式)
Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl为数据库的SID
String user="test";
String password="test";
Connection conn= DriverManager.getConnection(url,user,password);

2、DB2数据库
Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();
String url="jdbc:db2://localhost:5000/sample"; //sample为你的数据库名
String user="admin";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);

3、Sql Server7.0/2000数据库
Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();
String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb";
//mydb为数据库
String user="sa";
String password="";
Connection conn= DriverManager.getConnection(url,user,password);

4、Sybase数据库
Class.forName("com.sybase.jdbc.SybDriver").newInstance();
String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDB为你的数据库名
Properties sysProps = System.getProperties();
SysProps.put("user","userid");
SysProps.put("password","user_password");
Connection conn= DriverManager.getConnection(url, SysProps);

5、Informix数据库
Class.forName("com.informix.jdbc.IfxDriver").newInstance();
String url =
"jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;
user=testuser;password=testpassword"; //myDB为数据库名
Connection conn= DriverManager.getConnection(url);

6、MySQL数据库
Class.forName("org.gjt.mm.mysql.Driver").newInstance();
String url ="jdbc:mysql://localhost/myDB?user=soft&password=soft1234&useUnicode=true&characterEncoding=8859_1"
//myDB为数据库名
Connection conn= DriverManager.getConnection(url);

7、PostgreSQL数据库
Class.forName("org.postgresql.Driver").newInstance();
String url ="jdbc:postgresql://localhost/myDB" //myDB为数据库名
String user="myuser";
String password="mypassword";
Connection conn= DriverManager.getConnection(url,user,password);


8、access数据库直连用ODBC的
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;
String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");
Connection conn = DriverManager.getConnection(url,"","");
Statement stmtNew=conn.createStatement() ;

二、JDBC连接MySql方式
下面是使用JDBC连接MySql的一个小的教程

1、查找驱动程序
MySQL目前提供的java驱动程序为Connection/J,可以从MySQL官方网站下载,并找到mysql-connector-java-3.0.15-ga-bin.jar文件,此驱动程序为纯java驱动程序,不需做其他配置。

2、动态指定classpath
如果需要执行时动态指定classpath,就在执行时采用-cp方式。否则将上面的.jar文件加入到classpath环境变量中。

3、加载驱动程序
try{
Class.forName(com.mysql.jdbc.Driver);
System.out.println(Success loading Mysql Driver!);
}catch(Exception e)
{
System.out.println(Error loading Mysql Driver!);
e.printStackTrace();
}

4、设置连接的url
jdbc:mysql://localhost/databasename[?pa=va][&pa=va]

三、以下列出了在使用JDBC来连接Oracle数据库时可以使用的一些技巧,这些技巧能够使我们更好地发挥系统的性能和实现更多的功能(系转载)。

  1、在客户端软件开发中使用Thin驱动程序

  在开发Java软件方面,Oracle的数据库提供了四种类型的驱动程序,二种用于应用软件、applets、servlets等客户端软件,另外二种用于数据库中的Java存储过程等服务器端软件。在客户机端软件的开发中,我们可以选择OCI驱动程序或Thin驱动程序。OCI驱动程序利用Java本地化接口(JNI),通过Oracle客户端软件与数据库进行通讯。Thin驱动程序是纯Java驱动程序,它直接与数据库进行通讯。为了获得最高的性能,Oracle建议在客户端软件的开发中使用OCI驱动程序,这似乎是正确的。但我建议使用Thin驱动程序,因为通过多次测试发现,在通常情况下,Thin驱动程序的性能都超过了OCI驱动程序。

  2、关闭自动提交功能,提高系统性能

  在第一次建立与数据库的连接时,在缺省情况下,连接是在自动提交模式下的。为了获得更好的性能,可以通过调用带布尔值false参数的Connection类的setAutoCommit()方法关闭自动提交功能,如下所示:

  conn.setAutoCommit(false);

  值得注意的是,一旦关闭了自动提交功能,我们就需要通过调用Connection类的commit()和rollback()方法来人工的方式对事务进行管理。

  3、在动态SQL或有时间限制的命令中使用Statement对象

  在执行SQL命令时,我们有二种选择:可以使用PreparedStatement对象,也可以使用Statement对象。无论多少次地使用同一个SQL命令,PreparedStatement都只对它解析和编译一次。当使用Statement对象时,每次执行一个SQL命令时,都会对它进行解析和编译。这可能会使你认为,使用PreparedStatement对象比使用Statement对象的速度更快。然而,我进行的测试表明,在客户端软件中,情况并非如此。因此,在有时间限制的SQL操作中,除非成批地处理SQL命令,我们应当考虑使用Statement对象。

  此外,使用Statement对象也使得编写动态SQL命令更加简单,因为我们可以将字符串连接在一起,建立一个有效的SQL命令。因此,我认为,Statement对象可以使动态SQL命令的创建和执行变得更加简单。

  4、利用helper函数对动态SQL命令进行格式化

  在创建使用Statement对象执行的动态SQL命令时,我们需要处理一些格式化方面的问题。例如,如果我们想创建一个将名字O'Reilly插入表中的SQL命令,则必须使用二个相连的“''”号替换O'Reilly中的“'”号。完成这些工作的最好的方法是创建一个完成替换操作的helper方法,然后在连接字符串心服用公式表达一个SQL命令时,使用创建的helper方法。与此类似的是,我们可以让helper方法接受一个Date型的值,然后让它输出基于Oracle的to_date()函数的字符串表达式。

  5、利用PreparedStatement对象提高数据库的总体效率

  在使用PreparedStatement对象执行SQL命令时,命令被数据库进行解析和编译,然后被放到命令缓冲区。然后,每当执行同一个PreparedStatement对象时,它就会被再解析一次,但不会被再次编译。在缓冲区中可以发现预编译的命令,并且可以重新使用。在有大量用户的企业级应用软件中,经常会重复执行相同的SQL命令,使用PreparedStatement对象带来的编译次数的减少能够提高数据库的总体性能。如果不是在客户端创建、预备、执行PreparedStatement任务需要的时间长于Statement任务,我会建议在除动态SQL命令之外的所有情况下使用PreparedStatement对象。

  6、在成批处理重复的插入或更新操作中使用PreparedStatement对象

  如果成批地处理插入和更新操作,就能够显著地减少它们所需要的时间。Oracle提供的Statement和 CallableStatement并不真正地支持批处理,只有PreparedStatement对象才真正地支持批处理。我们可以使用addBatch()和executeBatch()方法选择标准的JDBC批处理,或者通过利用PreparedStatement对象的setExecuteBatch()方法和标准的executeUpdate()方法选择速度更快的Oracle专有的方法。要使用Oracle专有的批处理机制,可以以如下所示的方式调用setExecuteBatch():
PreparedStatement pstmt3D null;
try {
((OraclePreparedStatement)
pstmt).setExecuteBatch(30);
...
pstmt.executeUpdate();
}


  调用setExecuteBatch()时指定的值是一个上限,当达到该值时,就会自动地引发SQL命令执行,标准的executeUpdate()方法就会被作为批处理送到数据库中。我们可以通过调用PreparedStatement类的sendBatch()方法随时传输批处理任务。

  7、使用Oracle locator方法插入、更新大对象(LOB)

  Oracle的PreparedStatement类不完全支持BLOB和CLOB等大对象的处理,尤其是Thin驱动程序不支持利用PreparedStatement对象的setObject()和setBinaryStream()方法设置BLOB的值,也不支持利用setCharacterStream()方法设置CLOB的值。只有locator本身中的方法才能够从数据库中获取LOB类型的值。可以使用PreparedStatement对象插入或更新LOB,但需要使用locator才能获取LOB的值。由于存在这二个问题,因此,我建议使用locator的方法来插入、更新或获取LOB的值。

  8、使用SQL92语法调用存储过程

  在调用存储过程时,我们可以使用SQL92或Oracle PL/SQL,由于使用Oracle PL/SQL并没有什么实际的好处,而且会给以后维护你的应用程序的开发人员带来麻烦,因此,我建议在调用存储过程时使用SQL92。

  9、使用Object SQL将对象模式转移到数据库中

  既然可以将Oracle的数据库作为一种面向对象的数据库来使用,就可以考虑将应用程序中的面向对象模式转到数据库中。目前的方法是创建Java bean作为伪装的数据库对象,将它们的属性映射到关系表中,然后在这些bean中添加方法。尽管这样作在Java中没有什么问题,但由于操作都是在数据库之外进行的,因此其他访问数据库的应用软件无法利用对象模式。如果利用Oracle的面向对象的技术,可以通过创建一个新的数据库对象类型在数据库中模仿其数据和操作,然后使用JPublisher等工具生成自己的Java bean类。如果使用这种方式,不但Java应用程序可以使用应用软件的对象模式,其他需要共享你的应用中的数据和操作的应用软件也可以使用应用软件中的对象模式。

  10、利用SQL完成数据库内的操作

  我要向大家介绍的最重要的经验是充分利用SQL的面向集合的方法来解决数据库处理需求,而不是使用Java等过程化的编程语言。

  如果编程人员要在一个表中查找许多行,结果中的每个行都会查找其他表中的数据,最后,编程人员创建了独立的UPDATE命令来成批地更新第一个表中的数据。与此类似的任务可以通过在set子句中使用多列子查询而在一个UPDATE命令中完成。当能够在单一的SQL命令中完成任务,何必要让数据在网上流来流去的?我建议用户认真学习如何最大限度地发挥SQL的功能。

二、JDBC连接MySql方式
下面是使用JDBC连接MySql的一个小的教程

1、查找驱动程序
MySQL目前提供的java驱动程序为Connection/J,可以从MySQL官方网站下载,并找到mysql-connector-java-3.0.15-ga-bin.jar文件,此驱动程序为纯java驱动程序,不需做其他配置。

2、动态指定classpath
如果需要执行时动态指定classpath,就在执行时采用-cp方式。否则将上面的.jar文件加入到classpath环境变量中。

3、加载驱动程序
try{
Class.forName(com.mysql.jdbc.Driver);
System.out.println(Success loading Mysql Driver!);
}catch(Exception e)
{
System.out.println(Error loading Mysql Driver!);
e.printStackTrace();
}

4、设置连接的url
jdbc:mysql://localhost/databasename[?pa=va][&pa=va]

三、以下列出了在使用JDBC来连接Oracle数据库时可以使用的一些技巧,这些技巧能够使我们更好地发挥系统的性能和实现更多的功能(系转载)。

  1、在客户端软件开发中使用Thin驱动程序

  在开发Java软件方面,Oracle的数据库提供了四种类型的驱动程序,二种用于应用软件、applets、servlets等客户端软件,另外二种用于数据库中的Java存储过程等服务器端软件。在客户机端软件的开发中,我们可以选择OCI驱动程序或Thin驱动程序。OCI驱动程序利用Java本地化接口(JNI),通过Oracle客户端软件与数据库进行通讯。Thin驱动程序是纯Java驱动程序,它直接与数据库进行通讯。为了获得最高的性能,Oracle建议在客户端软件的开发中使用OCI驱动程序,这似乎是正确的。但我建议使用Thin驱动程序,因为通过多次测试发现,在通常情况下,Thin驱动程序的性能都超过了OCI驱动程序。

  2、关闭自动提交功能,提高系统性能

  在第一次建立与数据库的连接时,在缺省情况下,连接是在自动提交模式下的。为了获得更好的性能,可以通过调用带布尔值false参数的Connection类的setAutoCommit()方法关闭自动提交功能,如下所示:

  conn.setAutoCommit(false);

  值得注意的是,一旦关闭了自动提交功能,我们就需要通过调用Connection类的commit()和rollback()方法来人工的方式对事务进行管理。

  3、在动态SQL或有时间限制的命令中使用Statement对象

  在执行SQL命令时,我们有二种选择:可以使用PreparedStatement对象,也可以使用Statement对象。无论多少次地使用同一个SQL命令,PreparedStatement都只对它解析和编译一次。当使用Statement对象时,每次执行一个SQL命令时,都会对它进行解析和编译。这可能会使你认为,使用PreparedStatement对象比使用Statement对象的速度更快。然而,我进行的测试表明,在客户端软件中,情况并非如此。因此,在有时间限制的SQL操作中,除非成批地处理SQL命令,我们应当考虑使用Statement对象。

  此外,使用Statement对象也使得编写动态SQL命令更加简单,因为我们可以将字符串连接在一起,建立一个有效的SQL命令。因此,我认为,Statement对象可以使动态SQL命令的创建和执行变得更加简单。

  4、利用helper函数对动态SQL命令进行格式化

  在创建使用Statement对象执行的动态SQL命令时,我们需要处理一些格式化方面的问题。例如,如果我们想创建一个将名字O'Reilly插入表中的SQL命令,则必须使用二个相连的“''”号替换O'Reilly中的“'”号。完成这些工作的最好的方法是创建一个完成替换操作的helper方法,然后在连接字符串心服用公式表达一个SQL命令时,使用创建的helper方法。与此类似的是,我们可以让helper方法接受一个Date型的值,然后让它输出基于Oracle的to_date()函数的字符串表达式。

  5、利用PreparedStatement对象提高数据库的总体效率

  在使用PreparedStatement对象执行SQL命令时,命令被数据库进行解析和编译,然后被放到命令缓冲区。然后,每当执行同一个PreparedStatement对象时,它就会被再解析一次,但不会被再次编译。在缓冲区中可以发现预编译的命令,并且可以重新使用。在有大量用户的企业级应用软件中,经常会重复执行相同的SQL命令,使用PreparedStatement对象带来的编译次数的减少能够提高数据库的总体性能。如果不是在客户端创建、预备、执行PreparedStatement任务需要的时间长于Statement任务,我会建议在除动态SQL命令之外的所有情况下使用PreparedStatement对象。

  6、在成批处理重复的插入或更新操作中使用PreparedStatement对象

  如果成批地处理插入和更新操作,就能够显著地减少它们所需要的时间。Oracle提供的Statement和 CallableStatement并不真正地支持批处理,只有PreparedStatement对象才真正地支持批处理。我们可以使用addBatch()和executeBatch()方法选择标准的JDBC批处理,或者通过利用PreparedStatement对象的setExecuteBatch()方法和标准的executeUpdate()方法选择速度更快的Oracle专有的方法。要使用Oracle专有的批处理机制,可以以如下所示的方式调用setExecuteBatch():
PreparedStatement pstmt3D null;
try {
((OraclePreparedStatement)
pstmt).setExecuteBatch(30);
...
pstmt.executeUpdate();
}


  调用setExecuteBatch()时指定的值是一个上限,当达到该值时,就会自动地引发SQL命令执行,标准的executeUpdate()方法就会被作为批处理送到数据库中。我们可以通过调用PreparedStatement类的sendBatch()方法随时传输批处理任务。

  7、使用Oracle locator方法插入、更新大对象(LOB)

  Oracle的PreparedStatement类不完全支持BLOB和CLOB等大对象的处理,尤其是Thin驱动程序不支持利用PreparedStatement对象的setObject()和setBinaryStream()方法设置BLOB的值,也不支持利用setCharacterStream()方法设置CLOB的值。只有locator本身中的方法才能够从数据库中获取LOB类型的值。可以使用PreparedStatement对象插入或更新LOB,但需要使用locator才能获取LOB的值。由于存在这二个问题,因此,我建议使用locator的方法来插入、更新或获取LOB的值。

  8、使用SQL92语法调用存储过程

  在调用存储过程时,我们可以使用SQL92或Oracle PL/SQL,由于使用Oracle PL/SQL并没有什么实际的好处,而且会给以后维护你的应用程序的开发人员带来麻烦,因此,我建议在调用存储过程时使用SQL92。

  9、使用Object SQL将对象模式转移到数据库中

  既然可以将Oracle的数据库作为一种面向对象的数据库来使用,就可以考虑将应用程序中的面向对象模式转到数据库中。目前的方法是创建Java bean作为伪装的数据库对象,将它们的属性映射到关系表中,然后在这些bean中添加方法。尽管这样作在Java中没有什么问题,但由于操作都是在数据库之外进行的,因此其他访问数据库的应用软件无法利用对象模式。如果利用Oracle的面向对象的技术,可以通过创建一个新的数据库对象类型在数据库中模仿其数据和操作,然后使用JPublisher等工具生成自己的Java bean类。如果使用这种方式,不但Java应用程序可以使用应用软件的对象模式,其他需要共享你的应用中的数据和操作的应用软件也可以使用应用软件中的对象模式。

  10、利用SQL完成数据库内的操作

  我要向大家介绍的最重要的经验是充分利用SQL的面向集合的方法来解决数据库处理需求,而不是使用Java等过程化的编程语言。

  如果编程人员要在一个表中查找许多行,结果中的每个行都会查找其他表中的数据,最后,编程人员创建了独立的UPDATE命令来成批地更新第一个表中的数据。与此类似的任务可以通过在set子句中使用多列子查询而在一个UPDATE命令中完成。当能够在单一的SQL命令中完成任务,何必要让数据在网上流来流去的?我建议用户认真学习如何最大限度地发挥SQL的功能。

1、查找驱动程序
MySQL目前提供的java驱动程序为Connection/J,可以从MySQL官方网站下载,并找到mysql-connector-java-3.0.15-ga-bin.jar文件,此驱动程序为纯java驱动程序,不需做其他配置。

2、动态指定classpath
如果需要执行时动态指定classpath,就在执行时采用-cp方式。否则将上面的.jar文件加入到classpath环境变量中。

3、加载驱动程序
try{
Class.forName(com.mysql.jdbc.Driver);
System.out.println(Success loading Mysql Driver!);
}catch(Exception e)
{
System.out.println(Error loading Mysql Driver!);
e.printStackTrace();
}

4、设置连接的url
jdbc:mysql://localhost/databasename[?pa=va][&pa=va]

三、以下列出了在使用JDBC来连接Oracle数据库时可以使用的一些技巧,这些技巧能够使我们更好地发挥系统的性能和实现更多的功能(系转载)。

  1、在客户端软件开发中使用Thin驱动程序

  在开发Java软件方面,Oracle的数据库提供了四种类型的驱动程序,二种用于应用软件、applets、servlets等客户端软件,另外二种用于数据库中的Java存储过程等服务器端软件。在客户机端软件的开发中,我们可以选择OCI驱动程序或Thin驱动程序。OCI驱动程序利用Java本地化接口(JNI),通过Oracle客户端软件与数据库进行通讯。Thin驱动程序是纯Java驱动程序,它直接与数据库进行通讯。为了获得最高的性能,Oracle建议在客户端软件的开发中使用OCI驱动程序,这似乎是正确的。但我建议使用Thin驱动程序,因为通过多次测试发现,在通常情况下,Thin驱动程序的性能都超过了OCI驱动程序。

  2、关闭自动提交功能,提高系统性能

  在第一次建立与数据库的连接时,在缺省情况下,连接是在自动提交模式下的。为了获得更好的性能,可以通过调用带布尔值false参数的Connection类的setAutoCommit()方法关闭自动提交功能,如下所示:

  conn.setAutoCommit(false);

  值得注意的是,一旦关闭了自动提交功能,我们就需要通过调用Connection类的commit()和rollback()方法来人工的方式对事务进行管理。

  3、在动态SQL或有时间限制的命令中使用Statement对象

  在执行SQL命令时,我们有二种选择:可以使用PreparedStatement对象,也可以使用Statement对象。无论多少次地使用同一个SQL命令,PreparedStatement都只对它解析和编译一次。当使用Statement对象时,每次执行一个SQL命令时,都会对它进行解析和编译。这可能会使你认为,使用PreparedStatement对象比使用Statement对象的速度更快。然而,我进行的测试表明,在客户端软件中,情况并非如此。因此,在有时间限制的SQL操作中,除非成批地处理SQL命令,我们应当考虑使用Statement对象。

  此外,使用Statement对象也使得编写动态SQL命令更加简单,因为我们可以将字符串连接在一起,建立一个有效的SQL命令。因此,我认为,Statement对象可以使动态SQL命令的创建和执行变得更加简单。

  4、利用helper函数对动态SQL命令进行格式化

  在创建使用Statement对象执行的动态SQL命令时,我们需要处理一些格式化方面的问题。例如,如果我们想创建一个将名字O'Reilly插入表中的SQL命令,则必须使用二个相连的“''”号替换O'Reilly中的“'”号。完成这些工作的最好的方法是创建一个完成替换操作的helper方法,然后在连接字符串心服用公式表达一个SQL命令时,使用创建的helper方法。与此类似的是,我们可以让helper方法接受一个Date型的值,然后让它输出基于Oracle的to_date()函数的字符串表达式。

  5、利用PreparedStatement对象提高数据库的总体效率

  在使用PreparedStatement对象执行SQL命令时,命令被数据库进行解析和编译,然后被放到命令缓冲区。然后,每当执行同一个PreparedStatement对象时,它就会被再解析一次,但不会被再次编译。在缓冲区中可以发现预编译的命令,并且可以重新使用。在有大量用户的企业级应用软件中,经常会重复执行相同的SQL命令,使用PreparedStatement对象带来的编译次数的减少能够提高数据库的总体性能。如果不是在客户端创建、预备、执行PreparedStatement任务需要的时间长于Statement任务,我会建议在除动态SQL命令之外的所有情况下使用PreparedStatement对象。

  6、在成批处理重复的插入或更新操作中使用PreparedStatement对象

  如果成批地处理插入和更新操作,就能够显著地减少它们所需要的时间。Oracle提供的Statement和 CallableStatement并不真正地支持批处理,只有PreparedStatement对象才真正地支持批处理。我们可以使用addBatch()和executeBatch()方法选择标准的JDBC批处理,或者通过利用PreparedStatement对象的setExecuteBatch()方法和标准的executeUpdate()方法选择速度更快的Oracle专有的方法。要使用Oracle专有的批处理机制,可以以如下所示的方式调用setExecuteBatch():
PreparedStatement pstmt3D null;
try {
((OraclePreparedStatement)
pstmt).setExecuteBatch(30);
...
pstmt.executeUpdate();
}


  调用setExecuteBatch()时指定的值是一个上限,当达到该值时,就会自动地引发SQL命令执行,标准的executeUpdate()方法就会被作为批处理送到数据库中。我们可以通过调用PreparedStatement类的sendBatch()方法随时传输批处理任务。

  7、使用Oracle locator方法插入、更新大对象(LOB)

  Oracle的PreparedStatement类不完全支持BLOB和CLOB等大对象的处理,尤其是Thin驱动程序不支持利用PreparedStatement对象的setObject()和setBinaryStream()方法设置BLOB的值,也不支持利用setCharacterStream()方法设置CLOB的值。只有locator本身中的方法才能够从数据库中获取LOB类型的值。可以使用PreparedStatement对象插入或更新LOB,但需要使用locator才能获取LOB的值。由于存在这二个问题,因此,我建议使用locator的方法来插入、更新或获取LOB的值。

  8、使用SQL92语法调用存储过程

  在调用存储过程时,我们可以使用SQL92或Oracle PL/SQL,由于使用Oracle PL/SQL并没有什么实际的好处,而且会给以后维护你的应用程序的开发人员带来麻烦,因此,我建议在调用存储过程时使用SQL92。

  9、使用Object SQL将对象模式转移到数据库中

  既然可以将Oracle的数据库作为一种面向对象的数据库来使用,就可以考虑将应用程序中的面向对象模式转到数据库中。目前的方法是创建Java bean作为伪装的数据库对象,将它们的属性映射到关系表中,然后在这些bean中添加方法。尽管这样作在Java中没有什么问题,但由于操作都是在数据库之外进行的,因此其他访问数据库的应用软件无法利用对象模式。如果利用Oracle的面向对象的技术,可以通过创建一个新的数据库对象类型在数据库中模仿其数据和操作,然后使用JPublisher等工具生成自己的Java bean类。如果使用这种方式,不但Java应用程序可以使用应用软件的对象模式,其他需要共享你的应用中的数据和操作的应用软件也可以使用应用软件中的对象模式。

  10、利用SQL完成数据库内的操作

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics