毕业论文
http://www.kj333.com/guest/hmhtml/hmlist31_1.htm
以下是我搜集的一些论文网站
你自己找一找吧!!
◆论文快车 http://www.lun-wen.com/ 提供论文资料收集、写作指南、论文征稿,中国MBA、MPA、各类学术、毕业论文等资料。 484Gyi1
◆学生大论文中心 http://www.studa.com/newpaper/ 提供论文定做、发表等服务,内容涉及会计审计、财政税收、计算机、经济学、管理学、法学、理学、工学、医学、文学等20个学术类别。 376HnV7
◆蜂朝论文网 http://www.51lunwen.com/subweb/thesis/main/index.asp提供毕业论文、本科论文、硕士论文等论文发表和定制等服务。 531hb9
◆教育教学论文网 http://www.minaol.com/gb/art/ttd/index.asp以教育论文为主,含信息技术、计算机、德育、素质教育、摄影、美术、化学、英语、语文、体育等方面论文。 815on7
◆中国园丁网论文大观 http://www.teacher.net.cn/ 提供教育类论文。 203Fb2
◆法律论文资料库 http://www.law-lib.com/lw/提供法学理论、宪法、行政法、刑法、民法、经济法、司法制度、国际法等分类论文。 78Jg8
◆论文网 http://www.lunwen.net/提供论文写作服务。 400Kxh8
◆吾爱论文网http://www.52paper.com/ 提供文理工管等十二大学科门类的期刊论文、毕业论文和职称论文。 567wVAS6
◆幸福校园 http://www.happycampus.com.cn/ 论文、报告书、简历、考试情报等各种学术资料交流的中心。 36873o6
◆知新资讯http://www.paperscn.com/ 专业提供各种论文、课题资料,主要包括:教育论文、计算机论文、毕业论文、法律论文、学术论文、免费论文、硕士论文、研究生论文、博士论文、经济论文、科技论文等。 203Ydu6
◆全程论文网 http://www.lunwen51.net/一个专业代理职称论文、毕业论文、学术论文写作指导、论文推荐公开刊物发表(核心、优秀期刊)的网站。 642pjiY2
◆论文商务中心http://doc.cei.gov.cn/ 是一个开放式的、保护版权的、网上论文精品自选超市。 127JoVq5
论文发表咨询网 http://www.csepg.com/ 202wdx01
语言学论文http://chinese.pku.edu.cn/yuyinyj/shenjiong.htm 2252du8
◆论文资料网 http://www.51paper.net/ 提供论文资料服务的专业网站,含MBA论文资料、中小企业论文、物流供应链论文、财经论文、电子商务论文、论文参考资料。 1550x9
◆论文帝国 http://www.51paper.net/ 含论文查询、发布论文及***外交、社会行政、劳动人事、新闻传播、法律、财经等论文。 828Ol9
◆毕业论文网http://www.bylw.net/ 实施全免费毕业论文资料服务,不涉及向网友收费内容。 380JTi1
◆论文资料站 http://lwzl.com/免费为广大学子提供论文资料查询、交流的优良平台。 662Y23z5
◆世界论文网 http://www.worldthesis.com/ 收集并接受委托,发布国际优秀作品(论文)。 92N64
◆中国论文网 http://www.lw99.com/ 提供大量专业论文、大学毕业论文,有各种层次的内容,特别适合各大专院校毕业生、社会各界论文爱好者和各机关人员作参考学习之用,免去您各方查找资料的麻烦。 719va7
◆天下网 http://txlw.com/ 论文老牌名站,由在读博士、硕士生创办。网站侧重于为论文写作者(尤其是对撰写毕业论文的朋友)提供写作指导。 2285Vg1
◆国际优秀论文http://txlw.com/ 分为科技论文、医学论文、教育论文三大版块。 43QOES3
台湾博硕士论文资讯网 http://datas.ncl.edu.tw/theabs/1/ 231pEO1
论文网 http://lwdb.vip.sina.com/ 254VPJ2
大学生论文库 http://www.syiae.com/lunwen/ 752if5
华夏论文网 http://hxlw.vip.sina.com/ 656191
论文荟萃http://www.oh100.com/teach/teacher/lunwen/ 261kpjs5
论文秘书网http://www.wenshu.net/ 869YD87
论文指导网 http://lunwen.zzcollege.net/ 739gG3
中国大学生论文网http://www.wenshu.net/ 697KC4
大学生论文资讯网 http://www.thesis4u.com/ 424ZzIL6
轻松论文网 http://www.paperease.com/ 72QHgm8
全国优秀博士学位论文评选 http://www.cdgdc.edu.cn/yxbslw/yxbslw.htm 4667wI1
体育教学论文http://pe.stedu.net/mywz/tyjx.htm 9891UX94
体育论文 http://www.zxty.net/product4.htm 303RMCE1
新科论文网http://www.xklw.com/# 4944f07
信息化教育论文 http://www.yxedu.net/it/lunwen.htm 283RBp1
农业论文 http://www.agrionline.net.cn/keji/lunwenzy/ 688mOMA8
中国总经理网论文集http://www.cnceo.com/school/lwj.asp 748YbJ6
工程论文服务网http://infobuild.vip.sina.com/ 948kBt63
金融论文在线 http://www.finance-cn.com/ 6635Zl7
才思论文网 http://thesis.xiloo.com/ 423l5PH8
论文资源网 http://lunw.vip.sina.com/ 44uI9G3
经济论文 http://www.gjmy.com/jjlw.asp 723HES23
论文选萃http://www.chinampaonline.com/lunwen/ 543C76
活动教育研究论文http://www.21cae.net/activeteach/activearticle.htm 901heD1
毕业生论文库 http://lib.blcu.edu.cn/dt1000/bys/bys.htm 3644l4
能源论文 http://www.china5e.com/dissertation/default.htm 297PG1
会计文苑-优秀论文 http://www.chinaacc.com/wenyuan/lunwen/ 901MS7
中国广电技术论文 http://www.chinabctv.com/bctvlw/index.asp 820OJ07
教育教学论文交流网 http://www.minaol.com/gb/art/ttd/index.asp 178sxqw4
食品论文http://china-foods.net.cn/discourse.asp 170YcYB8
管理在线论文 http://www.hao3721.com/main.asp 22kaP8
中国科技论文在线 http://www.paper.edu.cn/home.jsp 960zUkA6
MBA论文全集 http://mba.001.com.cn/mbamba.htm 244u61
物理论文集 http://www.physicswd.com/ 620zwW1
中国交通技术论坛资料库 http://www.tranbbs.com/article/ 620zwW1
中国路桥工程论文资料中心 http://www.lqzx.com/lunwen.htm 748tOd4
中国论文发表网http://www.fabiao.cn/ 884SQDc7
翰林论文网http://www.hlpaper.com900QBIk6
posted @
2006-03-22 11:19 MEYE 阅读(452) |
评论 (0) |
编辑 收藏
一个很不错的数据库连接池实现,备份之
import java.sql.*;
import java.io.*;
import java.util.*;
public class DBConnectionManager {
private static int clients = 0;
private static DBConnectionManager instance;
private Vector drivers = new Vector();
private PrintWriter log;
private Hashtable pools = new Hashtable();
public DBConnectionManager() {
init();
}
private void log(String msg) {
log.println(new java.util.Date() + ": " + msg);
}
/**
* 将文本信息与异常写入日志文件
*/
private void log(Throwable e, String msg) {
log.println(new java.util.Date() + ": " + msg);
e.printStackTrace(log);
}
public static synchronized DBConnectionManager getInstance() {
if (instance == null) {
instance = new DBConnectionManager();
}
clients++;
return instance;
}
private void init() {
InputStream is = getClass().getResourceAsStream("/db.properties");
Properties dbProps = new Properties();
try {
dbProps.load(is);
}
catch (Exception e) {
System.err.println("Can not read the properties file. " +
"Make sure db.properties is in the CLASSPATH");
return;
}
loadDrivers(dbProps);
createPools(dbProps);
}
public void freeConnection(String name, Connection con) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
pool.freeConnection(con);
}
}
public Connection getConnection(String name) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
return pool.getConnection();
}
return null;
}
public Connection getConnection(String name, long time) {
DBConnectionPool pool = (DBConnectionPool) pools.get(name);
if (pool != null) {
return pool.getConnection(time);
}
return null;
}
public synchronized void release() {
// 等待直到最后一个客户程序调用
if (--clients != 0)
{
return;
}
Enumeration allPools = pools.elements();
while (allPools.hasMoreElements())
{
DBConnectionPool pool = (DBConnectionPool)allPools.nextElement();
pool.release();
}
Enumeration allDrivers = drivers.elements();
while (allDrivers.hasMoreElements())
{
Driver driver = (Driver) allDrivers.nextElement();
try {
DriverManager.deregisterDriver(driver);
log("撤销JDBC驱动程序 " + driver.getClass().getName()+"的注册");
}
catch (SQLException e) {
log(e, "无法撤销下列JDBC驱动程序的注册: " + driver.getClass().getName());
}
}
}
/*
drivers=sun.jdbc.odbc.JdbcOdbcDriver jdbc.idbDriver
logfile=D:\\user\\src\\java\\DBConnectionManager\\log.txt
idb.url=jdbc:idb:c:\\local\\javawebserver1.1\\db\\db.prp
idb.maxconn=2
access.url=jdbc:odbc:demo
access.user=demo
access.password=demopw
*/
private void loadDrivers(Properties props) {
String driverClasses = props.getProperty("drivers");
StringTokenizer st = new StringTokenizer(driverClasses);
while (st.hasMoreElements()) {
String driverClassName = st.nextToken().trim();
try {
Driver driver = (Driver)
Class.forName(driverClassName).newInstance();
DriverManager.registerDriver(driver);
drivers.addElement(driver);
// Log.log("Registered JDBC driver " + driverClassName);
}
catch (Exception e) {
// Log.log("Can not register JDBC driver: " + driverClassName + ", Exception: " + e.toString()));
}
}
}
private void createPools(Properties props) {
Enumeration propNames = props.propertyNames();
while (propNames.hasMoreElements())
{
String name = (String) propNames.nextElement();
if (name.endsWith(".url"))
{
String poolName = name.substring(0, name.lastIndexOf("."));
String url = props.getProperty(poolName + ".url");
if (url == null) {
// Log.log("No URL specified for " + poolName);
continue;
}
String user = props.getProperty(poolName + ".user");
String password = props.getProperty(poolName + ".password");
String maxconn = props.getProperty(poolName + ".maxconn", "0");
int max;
try {
max = Integer.valueOf(maxconn).intValue();
}
catch (NumberFormatException e) {
// Log.log("Invalid maxconn value " + maxconn + " for " + poolName);
max = 0;
}
DBConnectionPool pool =
new DBConnectionPool(poolName, url, user, password, max);
pools.put(poolName, pool);
// Log.log("Initialized pool " + poolName);
}
}
}
class DBConnectionPool {
private int checkedOut;
private Vector freeConnections = new Vector();
private int maxConn;
private String name;
private String password;
private String URL;
private String user;
/**
* 创建新的连接池
*
* @param name 连接池名字
* @param URL 数据库的JDBC URL
* @param user 数据库帐号,或 null
* @param password 密码,或 null
* @param maxConn 此连接池允许建立的最大连接数
*/
public DBConnectionPool(String name, String URL, String user
, String password, int maxConn)
{
this.name = name;
this.URL = URL;
this.user = user;
this.password = password;
this.maxConn = maxConn;
}
/**
* 将不再使用的连接返回给连接池
*
* @param con 客户程序释放的连接
*/
public synchronized void freeConnection(Connection con) {
// 将指定连接加入到向量末尾
freeConnections.addElement(con);
checkedOut--;
notifyAll();
}
/**
* 从连接池获得一个可用连接.如没有空闲的连接且当前连接数小于最大连接
* 数限制,则创建新连接.如原来登记为可用的连接不再有效,则从向量删除之,
* 然后递归调用自己以尝试新的可用连接.
*/
public synchronized Connection getConnection()
{
Connection con = null;
if (freeConnections.size() > 0)
{
// 获取向量中第一个可用连接
con = (Connection) freeConnections.firstElement();
freeConnections.removeElementAt(0);
try {
if (con.isClosed())
{
log("从连接池" + name+"删除一个无效连接");
// 递归调用自己,尝试再次获取可用连接
con = getConnection();
}
}
catch (SQLException e)
{
log("从连接池" + name+"删除一个无效连接");
// 递归调用自己,尝试再次获取可用连接
con = getConnection();
}
}
else if (maxConn == 0 || checkedOut < maxConn)
{
con = newConnection();
}
if (con != null) {
checkedOut++;
}
return con;
}
/**
* 从连接池获取可用连接.可以指定客户程序能够等待的最长时间
* 参见前一个getConnection()方法.
*
* @param timeout 以毫秒计的等待时间限制
*/
public synchronized Connection getConnection(long timeout)
{
long startTime = new java.util.Date().getTime();
Connection con;
while ((con = getConnection()) == null)
{
try {
wait(timeout);
}
catch (InterruptedException e) {}
if ((new java.util.Date().getTime() - startTime) >= timeout)
{
// wait()返回的原因是超时
return null;
}
}
return con;
}
/**
* 关闭所有连接
*/
public synchronized void release()
{
Enumeration allConnections = freeConnections.elements();
while (allConnections.hasMoreElements())
{
Connection con = (Connection) allConnections.nextElement();
try {
con.close();
log("关闭连接池" + name+"中的一个连接");
}
catch (SQLException e) {
log(e, "无法关闭连接池" + name+"中的连接");
}
}
freeConnections.removeAllElements();
}
/**
* 创建新的连接
*/
private Connection newConnection()
{
Connection con = null;
try {
if (user == null) {
con = DriverManager.getConnection(URL);
}
else {
con = DriverManager.getConnection(URL, user, password);
}
log("连接池" + name+"创建一个新的连接");
}
catch (SQLException e) {
log(e, "无法创建下列URL的连接: " + URL);
return null;
}
return con;
}
}
}
posted @
2006-03-16 10:42 MEYE 阅读(362) |
评论 (0) |
编辑 收藏
|
学会选择何种设计模式和构架才可以开发出最好的企业程序
摘要
文章中,列举了Chris Richardson在POJOs in Action(2006年1月份出版)的例子,该例子举了5个程序设计者在设计企业应用程序中都会问自己的问题.
如果我们盲目的使用POJOs技术(plain-old Java objects)和轻量级构架,那么我们在通过EJB建立分布式企业级JAVA程序时就可能会出现错误。每种技术都有它的强项和弱项,而根据实际情况选择最合适的技术是最重要的。 这篇文章主要讨论企业应用程序的设计模式和轻量级构架。为了让你在程序中高效的使用这些设计模式和轻量级构架,这里提供了一个决策构架. 这个构架包含了5个在设计程序或者是单独用例的业务逻辑(business logic for an individual use-case)的过程中必须回答的问题(decision-making framework)。这里特意加上了设计方案和对这种决策的理解,这样可以很大的提高你的软件质量。
在这篇文章中,你会看到对5种决策的简述,并且我会简单扼要的介绍每种设计决策的选项(options)和他们的优缺点。
版权声明:任何获得Matrix授权的网站,转载时请务必保留以下作者信息和链接 作者:Chris Richardson;tain198127(作者的blog:http://blog.matrix.org.cn/page/tain198127) 原文:http://www.javaworld.com/javaworld/jw-01-2006/jw-0130-pojo.html 译文:http://www.matrix.org.cn/resource/article/44/44254_J2EE+design+decisions.html 关键字:J2EE;design;decisions
业务逻辑和数据库访问决策
这里有2种完全不同的方法来设计JAVA企业程序,其中一种选择是采用标准EJB2实现途径(approach)。我更愿意称这种方法为重量级实现途径,当你使用重量级实现途径时你需要用会话beans(session bean)和消息驱动 beans(message-driven bean)去实现业务逻辑。你也可以使用DAOs(data access object)或者实体bean去访问业务逻辑
另外一种选择是使用POJOs 和轻量级构架,这种方式我称为POJO实现途径。当使用POJOs实现途径时,你的业务逻辑完全由POJO来实现。你可以使用持久型构架又叫做对象/关系映射构架(a.k.a=also know as )例如Hibernate 或者 JDO来访问数据库,再用Spring AOP(面向层面编程)来提供企业服务,比如事务管理和安全。 EJB3由于融合了POJOs和其他一些轻量级概念,所以对两者(指轻量级和重考锻揪叮┑那?植皇呛芮宄?>俑隼?樱?OJO中的实体bean既可以再EJB容器内运行,也可以再EJB容器外运行,然而POJOs中的会话bean和消息驱动bean仍然有重量级的行为,因为他们只能在EJB容器内部运行。所以,显而易见的,EJB3既是重量级的又有POJO的特性。EJB3中的实体bean是轻量级实现途径中的一部分。
在开发过程中,首要的是从各种各样的设计中选择到底采用重量级实现途径还是采用POJO实现途径。决策可以影响程序的几个方面,包括业务逻辑结构和数据访问机制。为了帮助从两种实现途径中择其一,来看这张典型的企业应用程序结构图,结构图在图示1中,而且在设计过程中就必须判断到底使用那种策略。
Figure 1. A typical application architecture and the key business logic and database access design decisions.
程序由网络基本表示层、业务层、持久层组成。网络基本表示层负责HTTP请求和为一般的浏览器客户端、XML和其他的胖体客户端生成HTML,比如为Ajax基本客户端生成HTML。业务层被表示层调用,用来实现程序业务逻辑。持久层被业务逻辑层用来访问外部数据源,比如数据库和其他程序。
表示层的设计不在本篇文章讨论之内,来看图表的其他部分,我们需要决定业务层结构的接口,这个接口是提供给表示层以及其他客户端的。而且还需要决定怎样访问能供多个程序访问的数据库。我们还必须决定如何处理短期事务处理事务和长期事务处理事务的并发问题。这些加起来一共有5种决策。每种决策都是要设计者来制定,为了能看懂演示图(big picture)要求每个开发者也都了解这些策略。
这些决策直接决定程序业务和表示层设计的特点。当然,还要决定一些其他很重要的决策。比如业务处理(transactions)、安全问题、缓存问题以及如何整合程序,但是关于这些问题通常在其他文献中讨论 在图表1中显示的五种决策,每种决策都有多种选择。每种选择根据它要解决的实际问题都有相应的优缺点。后续章节中,你会发现每种决策针对一个或多个领域时,在功能性、易开发性、可维护性和可用性方面有不同的平衡点。尽管我是POJO实现途径的超级大FANS,但是仍然需要了解其优缺点,以便于为你的程序做最好的选择 下面我们来了解一下每种决策的大纲和其选项。
决策1:组织业务逻辑
现在,很多的注意力都集中在某项技术的优点和缺点,尽管这很重要,但是在本质上你需要了解如何建构你的业务逻辑。如果不考虑如何组织就去写代码是非常简单的。例如,为一个会话BEAN添加代码要比在域模式(domain model.: An object model of the domain that incorporates both behavior and data.)中判断应该添加那种新特性要简单的多。理论上你仍然需要刻意的为你的软件设计最合适的业务逻辑。毕竟我相信你有过修改别人垃圾结构代码的惨痛经验
关键的决策是:到底应该用面向对象的实现途径还是面向过程的实现途径来实现你的程序。这个不是关于技术的决策,但是你技术上的决策可以潜在的约束你的业务逻辑的组织结构。采用EJB2技术,有利于面向过程设计,然而POJOs和轻量级构架可以让你为特殊的程序选择最好的实现途径
采用过程式设计 虽然我是一个面向对象实现途径(指前文的使用POJO和LIGHTFRAMEWORK)的倡导者,但是有些情况下面向对象实现途径有些大材小用,比如你只想实现一个非常简单的业务逻辑。而且,有时候,面向对象实现途径不太可行-?比如,你没有持久层构架来将你的对象映射到数据库中,在这种情况下,更好的方法是编写面向过程的代码,而且采用Martin Fowler称作事务脚本(Transaction Script)的设计模式,要比采用面向对象实现途径设计要好,因为你只需要写一个方法来调用事务处理脚本去处理表示层的请求。
采种这种实现途径的一个很重要的特点是,用于实现某种行为的类和数据存储区是分开的。在EJB2的应用程序中,这种方式的业务逻辑和图表2中的设计是非常相似的。这种设计的核心全都集中在EJB或者POJO的行为上,因为他们实现了事务脚本,并且还操作那些 “哑”对象数据(因为他们只拥有很少的行为,大部分都是数据)。因为大部分的行为都集中在少量的大型类上,所以代码会变的很难理解与维护。
Figure 2. The structure of a procedural design: large transaction script classes and many small data objects
这种设计具有高面向过程的特性,而且基本不依靠面向对象语言的特性。如果你曾经使用过C或者其他非面向对象语言的话,你应该用过这种设计模式。如果这种模式很适合你的设计的话,用这种模式设计也是一种不错的选择。
这种直观的过程式开发途径,非常的诱人,因为你只需要写代码就好了,不用考虑如何组织你的类文件。但问题是,如果你的业务逻辑非常的复杂,那么你的代码会变的噩梦般的难以维护。所以,除非你要写的程序非常的简单,否则你应该用面向对象设计你的程序,而不要受面向过程的代码的诱惑。
采用面向对象设计 在面向对象设计中,业务逻辑是由对象模型构成的,对象模型是由许多小类组成的关系网。这些类直接体现的是问题域的解决方法,如图3所示,在这种模式中,有些类只有数据,有些类只有行为,但是大多数的则两者都有,这是优秀的类设计的一种特点。
Figure 3. The structure of a domain model: small classes that have state and behavior
面向对象设计有许多的好处,包括可以提高可维护性和可延展性。你可以用EJB2的实体bean来实现一个简单的对象模型。但是如果像要获得更多的好处的话,必须要使用POJOs技术和轻量级持久层构架??比如Hibernate和JDO技术。POJO可以让你开发丰富的模型,这些模型可以拥有继承和回调等特点。而轻量级持久层构架可以让你很简单的从对象模型映射到数据库。
对象模型的另外一个名字是域模型,Fowler称这种由面向对象途径来开发的业务逻辑叫做域模型设计模式。(就是类的设计是直接用来解决问题的,则这种设计模式叫做域模型设计模式)
表模型设计模式 我曾经一直用域模型和事务处理脚本模型设计应用程序。但是有一次我听说JAVA企业应用程序可以用第三种途径来实现,这种途径就是Fowler所说的表模型设计模式。这种模式比事务处理脚本模式更加的结构化,因为它为数据库中的每个表都写了一个类,而这个类中实现了所有对这个表的操作代码,这个类就是表模型类。(我的解释就是为每个表专门写个类,对表的所有操作,全都由这个类中的方法实现,相当于用一个类模拟的数据库中的表)。和事务处理脚本模式相比,它将数据和行为分别封装到了不同的类中,因为表模型类的实例相当于真实数据库中的数据,这当然要比单独的一条记录要好的多。最后,可维护性成了问题,然而表模型设计模式还是有一些好处的。
决策2:封装业务逻辑
前面几章,我没有提及如何组织业务逻辑。你必须决定业务逻辑有什么样的接口。业务逻辑的接口由一些数据和方法组成,这些数据和方法由表示层来调用。在设计接口时重点需要考虑的是:应该封装哪些业务逻辑的操作,而哪些操作不应该显示给表示层。封装接口可以提高程序的可维护性,因为通过隐藏业务逻辑的操作细节,可以实现修改业务逻辑而不影响表示层。缺点是,你必须为封装业务逻辑而特意的写很多的代码。
你还需要考虑其他重要的问题,比如如何处理事务处理,安全,和远程调用问题。通常这些也是业务逻辑接口要负责的问题。为了保证数据的连贯性,业务层的接口必须保证每个事务处理中的调用都能执行。同样,也要验证调用者是否有权限调用业务方法。业务层接口还要负责处理一些远程客户端的问题。
来考虑一下选项。
EJB session façade 经典的J2EE解决方案是:用EJB来封装业务逻辑-基本的session facade。EJB容器提供事务处理管理,安全,分布式事务处理和远程访问。Facade方式可以通过封装业务逻辑来提高程序可维护性。粗糙型(Coarse-grained) API通过减少表示层对业务层的访问次数,而提高性能(因为它将对各个业务流程的处理再封装了一次,所以对底层的业务流程来说,它的API是比较粗糙的,这里也许翻译的不好。请大家见谅)。因为减少调用的次数,可以减少对数据库事务处理的次数,还可以提高对象在缓冲区的机会。如果表示层通过远程访问业务层,则这种API还可以减少网络负担。图表4给出了一个EJB-based session facade的例子。
Figure 4. Encapsulating the business logic with an EJB session façade
在这种设计模式中,表示层也许是通过远程来调用facade(相当于session的一个高级接口),EJB容器从facade中得到这个调用,并验证调用者的权限,然后开始一个业务处理。这个时候facade调用底层的业务对象,而这些业务对象负责实现具体的业务逻辑。等Facade返回后,EJB容器提交业务处理或者让该业务处理循环等待。
不幸的是,使用EJB session facade有一些严重的缺点。比如,EJB的会话bean只能在EJB容器中运行,这样就托慢了开发和测试周期。另外,如果用EJB2,则用来向表示层传输数据的数据传输对象的开发和维护就会变的很枯燥而且旷日持久。
POJO facade 对于许多程序来说,更好的实现途径是用POJO facade和AOP协作。比如负责管理事务处理、表示层的连接和安全问题的Spring 构架。POJO facade对业务层的封装风格和EJB facade很相似,通常也可以用一样的公共方法。而POJO和EJB关键区别是用POJO代替了EJB,用AOP提供的服务(例如业务处理管理和安全机制)替代了EJB容器。表5中,显示了用POJO facade的例子。
Figure 5. Encapsulating the business logic with a POJO façade
表示层调用POJO facade, POJO facade 调用业务对象。和EJB容器截获EJB facade方式一样,AOP通过“拦截机”来截获POJO facade,并验证调用者的权限,然后开始提交业务处理或让该业务循环等待。
通过在应用程序服务器外部开发和调试业务逻辑,对POJO facade的开发可以变的很简单,同时还可以获得许多EJB中会话Bean的好处,比如声明事务处理和安全。关键是,你可以少写点代码。你可以避免写数据传输对象类,因为POJO facade可以将对象域直接反馈给表示层;你可以使用依赖注射的方式来将应用程序组装起来,而不用在为JNDI写查找代码了。
然而,有些时候不能那用POJO facade,比如它不能参与到远程客户端建立的分布式事务处理。
暴露模型域模式 使用facade的一个缺点是你必须写额外的代码,而且负责将对象域返回给表示层的代码很容易出错。如果表示层设法调用某个对象,而业务层却没有提供该对象,也会增加runtime error出现的机会。如果你用JDO , Hibernate或者EJB3,则可以避免这种问题,方法是:将模型域(session区域)暴露给表示层,再将相应的对象域(存储对象的区域)返回给表示层,根据表示层在对象域之间的操作关系,持久层来导入相应的对象。(也就是把session区域给表示层,然后分析它需要的对象,再让持久层去加载这些对象)这就是所谓的lazy loading 技术。图表6中显示了表示层自由的访问对象域的设计图。
Figure 6. Using an exposed domain model
在图表6的设计中,表示层不通过facade而直接调用域对象,Spring AOP仍然提供服务,例如事务处理管理和安全。
用这种实现途径的一个重要的好处是,业务层不需要知道哪些对象需要调用,也不用知道那些需要返回给表示层。尽管这挺起来很简单,但是你会发现一些缺点。这会增加表示层的复杂度,因为你必须处理对数据库的连接。而且在基于Web的应用程序中,事务处理管理也要非常小心,因为在表示层将数据反馈给浏览器之前,事务处理的数据必须保持正确。
决策3:访问数据库
无论你怎样对业务逻辑怎样的组织和封装,最终你还是要从数据库中取数据出来。在经典的J2EE应用程序中,你有2个选择:JDBC??这个需要很多的底层代码;或者实体Bean??这个用起来非常困难,而且缺少重要特征。相比来说,使用轻量级构架令人高兴的事情之一就是:你有一些新的而且更有力的方法去访问数据库,而且这种方法可以显著的减少访问数据库的代码。让咱们来进一步研究
直接用JDBC会有什么问题 最近突然出现了对象/关系 映射构架(比如JDO和Hibernate) 和SQL映射构架(比如iBATIS)这些不是凭空出现的。相反,他们是在JAVA 联盟在JDBC屡造挫折之后才出现的。为了了解新构架出现的原因,这里咱们回顾一下直接使用JDBC会出现的问题。在许多程序中直接使用JDBC不是一个好的选择,主要有以下三个原因: ? 开发和维护SQL非常的困难而且耗费时间??一些开发者发现要写庞大而且复杂的SQL语句非常的困难。反映数据库变化的SQL语句会变得非常耗时。你必须小心的考虑牺牲可维护性是否值得。 ? 用SQL会使移植性变的很差??因为需要数据库的特殊SQL语句。如果一个程序和多个数据库有关系,那么你就要写多个版本的SQL语句,这使得可维护性变变成噩梦。 ? 直接写JDBC代码要会非常耗时,而且容易出错。你必须写很多的样板代码去获得连接,创建和初始化适当的声明,还要用精确的声明去清理连接。而且你还要写代码去将JAVA 对象映射到SQL声明。由于要无奈的去写, JDBC代码很容易出错。
如果你的程序必须直接运行SQL语句的话,那前面两个问题是无法避免的。有时候为了获得好的性能,必须要全力的写SQL语句,包括供应商提供的那些特殊东西。由于许多业务上的原因,持久层可能会产生混乱的SQL语句,为了防止这种情况,DBA可能要求你的程序来完全控制SQL语句的执行。通常,团队买进的关系型数据库过于庞大,以至于应用程序工作时会出现一些和数据库有关的琐碎事务。根据”iBATIS in Action”的作者说这里会有一种情况出现:“数据库或者SQL语句本身存在的时间比程序代码存在的时间还要长,或者同一段SQL语句或数据库有多个程序的版本。有些情况下,程序已经用另外一种语言重写了,但是SQL语句和数据库却没有太大的改变。” 如果直接使用SQL弄的你筋疲力尽,那么很幸运,这里有一种直接执行SQL语句的构架,它可比用JDBC要容易多了。当然了,这就是iBATIS.
使用 iBATIS 我开发过的所有企业JAVA应用程序,都是直接执行SQL语句的。早期的程序是执行特定的SQL语句的,后来是用持久层构架再用少量的SQL语句构成的。一开始我直接用JDBC来执行SQL语句,但是后来,我经常写一些小的构架去完成JDBC中那些比较无聊的部分。我也用过一段Spring的JDBC类,这些类除去了JDBC中的许多样板代码。但是无论是我自己写的构架还是使用Spring的类,在Java类映射到SQL语句的时候都会存在问题,这就是我为什么那么高兴的加入iTATIS 那边的原因了。
iBATIS 不仅将应用程序完全的与“数据库连接”、具体的SQL语句隔绝开来,更实现了通过XML描述文档来将JavaBean 映射到SQL语句。它用Java bean 内省机制来将“道具bean(bean properties)”映射为相应的数据库语句占位符,而且它可以将ResultSet后的结果构造为bean。它还可以通过数据库生成主键,自动加载相关的对象、实现缓存和lazy loading。这样,iBATIS 就除去了许多执行SQL语句带来的苦差。通过编辑XML描述文档和调用少量的iBATIS的API,代替了写大量的JDBC底层代码。
使用持久层框架 当然,iBATIS不能实现高层开发和维护SQL语句,而且缺乏可移植性。为了避免这类问题,你需要用到持久层框架。持久层框架可以将对象域映射到数据库中。它提供了创建,查找,删除对象的API函数。当程序要控制对象时它可以自动的加载相应的对象,还可以在事务处理结束时自动更新数据库。持久层框架通过对象/关系映射机制可以自动的生成SQL语句,对象/关系映射机制用XML文档定义了怎样将类映射为表,怎样将数据映射为列(column)和关系是怎样被映射为外键与连接表的。
在持久层构架上EJB也有它的短处:实体bean。EJB2的实体bean有很多的不足,而且开发和测试它会变得非常的枯燥。最后,很少用EJB2的实体bean了。在EJB3中会说明那些问题。
两种最有流行的轻量级持久层构架是JDO和Hibernate,前者是Sun的标准框架,后者是开源工程。两种框架都可以为POJO类提供持久层事务处理。你可以用POJO类来开发和测试你的业务逻辑,而不用担心持久层的问题,这个时候它会将类映射到数据库中的schema。另外,他们两个都可以在服务器程序外部或者内部,这样可以进一步降低开发难度。用Hibernate和JDO来进行开发比用老的EJB2的实体bean要舒服的多。
除了要决定怎样访问数据库外,还要决定如何处理数据库的并行处理问题。下面来看一下,为什么并行处理问题那么重要,同时看一下可实现的选项
决策4:处理数据库事务处理的并行问题
差不多所有的企业应用程序都需要多用户和多个后台进程并行的更新数据库。2个数据库 处理事务同时访问同时访问同一个数据是很正常的,但是这种情况很可能引起数据库中的数据不一致或者引起应用程序的不正常。由于大部分的应用程序都需要处理多个处理事务并行访问同一个数据,则它可以影响到业务和持久层的设计。
无论你是使用EJB还是轻量级构架,你的程序必须可以并行访问共享数据。EJB2要求使用供应商提供的特殊扩充接口来实现并行,然而与此不同的是,JDO和Hibernate可以直接支持大部分并行机制。更重要的是,使用JDO和Hibernate不仅只配置简单,而且只需要少量的代码就可以实现了。
在这样主要介绍几种“并行更新数据库处理事务”的选项的概要,这些事务处理和用户的输入无关。下一章,我主要介绍一下如何在应用程序级长时间的并行更新数据库处理事务,这种处理事务会与用户输入有关,而且是由一系列的数据库事务处理组成的。
独立数据库事务 有时候对共享数据的并行访问可以简单的依靠数据库本身来实现,数据库可以设置为执行孤立的数据??这只是对数据库而言。如果你对这种概念不熟悉也不要担心,你只要记住:如果应用程序使用完全的孤立事务方式,那么同时执行2个事务的结果和一个接一个的执行是一样的。(也就是说,如果你用孤立事务的方式来访问数据库的话,你同时执行2个事务,就会变成一个接一个的串行执行了。)
这种方法也许听起来非常的简单,但问题是这种处理方式有时候会降低性能,因为如何实现对事务的孤立是由数据库来决定的。为了这个原因,许多应用程序都避免使用它,而采用optimistic或者pessimistic 所锁,这会在下面讲到。
开放式锁定 并行更新数据的一种途径是用开放式锁定。开放式锁定工作原理是通过应用程序来检查数据是否被更新(被其他事务修改造成的)而实现的。一种更普通的实现开放式锁定的方法是在每个表中添加一个“版本列”(version column),对每个表而言,程序每次改变其中一行的时候都会更新这个“版本列”。每个UPDATE语句中的WHERE语句会根据上次查询的结果判断这个版本号是不是被更改了。在事务访问数据库中的数据时,程序中可以用PreparedStatement.executeUpadte()这个函数的返回值来检查行的个数,从而判断是否要继续执行UPDATE语句。如果数据中的行已经被其他的事务更新或者删除了,那么程序会让该事务从新访问数据库。
用开放式锁定机制来锁定那些直接执行SQL语句的应用程序是非常简单的。但是,用持久层构架(比如JDO和Hibernate)实现更容易,因为他们已经提供了开放式锁定机制??在配置选项中。一旦在配置选项中,选中了这种方式,持久层构架会自动的生成SQL的UPDATE语句来完成版本检查的任务。开放式锁定的名字来源于一种假设的情况,在这种情况下:并发更新的机会非常少,而且程序只能检测、覆盖这些数据而不能防止这种事情的发生。另外一种可选的途径是用保守式锁定,使用他的假设条件是:并发更新肯定会发生,而且必须被禁止。
保守式锁定 对于开放式锁定来说,另外一种途径是使用保守式锁定。当一个事务读取某些行的数据时,他会对这些数据加锁,这样就防止其他的事务访问这些数据了。具体的实现是需要数据库支持的,然而不幸的是,不是所有的数据库都支持保守式锁定。如果你的数据库支持话,那么你的应用程序直接执行SQL语句来实现保守式锁定将非常容易。但是,可能你已经猜到了,在程序中用JDO或者Hibernate来实现保守式锁定更容易,JDO以配置选项的方式提供了保守式锁定,而Hibernage提供了简单的API实现锁定对象。
除了可以处理单个数据库事务并行问题,常常你还需要处理多数据库事务的并行问题。
决策5:在长事务下处理并发访问
独立事务、开放式锁定、和保守式锁定只能用在单个数据库事务上的,然而,许多的程序需要 长时间的 在多个数据库事务之间 读取或者更新 共享数据。比如,有一种情况描述的是 怎样实现 用户编辑命令,这和很多的进程有关,这些进程可能会运行 很长的时间,而且它由 多个数据库事务组成。因为数据可能会被 一个数据库事务 读取,而又被 另外一个数据库事务 修改了,那么程序必须对 共享数据的并发访问 进行不同的处理。这样就必须使用 开放式锁定设计模式或 者保守是锁定设计模式,关于这两种模式会在Fowler的 Patterns of Enterprise Application Architecutre中详细介绍。
开放式脱机锁定模式 一种选择是开放式锁定机制的扩展,它会从第一次读取数据开始,在编辑进程执行后检查数据是否已经被修改了。例如,你可以在数据库的共享数据的表中使用版本号来实现。在编辑进程开始的时候,程序将版本号存储到会话状态中,然后每次用户要存储数据时,应用程序都要进行检查,保证数据库中的版本号和会话状态中的版本号一致。 因为开放式脱机锁定模式只有在用户进行保存修改过的数据时才可以检测,所以它只有在不成为客户的累赘的时候,才可以很好的运行。但如果情况是:客户必须要撤销几个操作的话,那么就会因为这种锁定模式而非常苦恼,那么更好的一种选择是用保守式脱机锁定。
保守式脱机锁定模式 在编辑进程开始时,保守式脱机锁定方式通过锁定 共享数据,来解决 多个数据库事务 同时更新共享数据的问题,这样,这个编辑进程就可以防止 其他的用户来修改数据了。这种方式和保守式锁定机制一开始描述的很类似,但它是靠程序来实现的,而不是数据库。因为同一时间内,只有有权利编辑共享数据的用户,才有权利去保存这些修改 | |
posted @
2006-03-15 11:15 MEYE 阅读(439) |
评论 (0) |
编辑 收藏
利用jdom实现读取数据库生成XML及读取XML文件插入数据库 |
| |
1. 首先是准备开源包,到http://jdom.org.下载,当前最新版本是jdom-1.0.zip。
2. 然后将其解压,并将build文件夹下的jdom.jar,将其拷贝到你的jdk安装目录的lib下面,也拷贝到jdk安装目录下的jre文件夹的lib的ext下,同时会将这个目录添加到环境变量classpath下。如: d:/jdk1.4/jre/lib/ext/jdom.jar和d:/jdk1.4/lib/jdom.jar.另外要注意的问题就是你存放java文件的路径也要加到classpath 中去,至于java的环境变量的设置我这里不做介绍。
3. 在这个实例中我用的数据库是mysql,因为是我比较喜欢开源和免费的东西,所以选择它。至于具体的版本如下: mysqlcc-0.9.4-win32.zip //图形控制界面 mysql-5.0.0a-alpha-win.zip mysql-connector-java-3.0.17-ga.zip //连接驱动程序的jar包 其实别的版本也可以。具体的安装我这里就不说了,如果不了解就可以到goole里找一下相关资料就可以了:) 首先来看我数据库表的设计:为了简单起见我只创见了一个含有两个表的数据库jdomdb,其中一个表是存放用户信息的userinfo表,另外一个就是用于存放演示中读取xml文件后往数据库里面插入的数据的表tmpinfo。 下面开始创建数据库表信息如下图:
左侧部分就是表userinfo字段信息的。同时表tmpinfo的字段信息也是一样。这里我也提供了数据库的表结构文件jdomdb.sql,你只要建立好名为jdomdb数据库,然后将其导入就可以了。 为了演示我们必须准备基本的数据,这里我们通过一个jsp文件testdb.jsp来插入一些数据。或则你可以直接手工在表中插入几条数据。
4. 下载包中的文件说明:
读数据库并将数据导出到XML文件中的文件:ExtraXml.java 其中导出来的文件名叫userinfo.xml; 读XML文件并将数据插入数据库的文件: ReadXml.java ; 封装数据库连接等操作的JavaBean文件:DBConn.java ; 有个封装好的例子就是ExtraXml3.java,只要调用javabean做相应的调用就可以了。 jdomdb.sql是我导出来的最基本的数据库的表结构,可以直接导入。 还有所必须用到的jdom.jar包。
下载连接:附件:javaXML.rar(150K)
参考网上的相关资料:http://www.knowsky.com/3226.html
| |
posted @
2006-03-15 11:14 MEYE 阅读(580) |
评论 (0) |
编辑 收藏