作者:sure160
email: sure160@china.com
日期:6/13/2001 12:46:36 PM
简介:本文探讨了关系数据库中的实体对象在面向对象语言中如何抽象、实现,并提出一种实现方案。
一、为什么要使用实体对象的概念
实体对象指的是可永久存储的数据对象,通常可以用关系数据库的一张数据表或一张主表和与之连接的几张子表来表示。为什么要引入实体对象的概念呢?我可以肯定您是看过关于面向对象优点的长篇大论的,不过我觉得有必要再唠叨两句,因为不是所有用C++或JAVA编程的人都是使用面向对象的方式想问题的。
在现实世界中,对象比它的属性要稳定,所以数据要抽象成对象。比如由于需求的修改,一个图书管理系统要显示更多的书目详细信息,图书的属性发生了变化,而图书这个对象并没有变,和其他对象(例如书架、借阅者)之间的关系也没有变。用一个数据对象来保存书目信息的程序修改起来要简单的多。
把实体对象如何永久储存的方法封装到对象中可以实现使用对象的外部程序的与数据库无关,便于程序的移植。
在程序设计中使用实体对象概念把面向对象分析、面向对象设计、面向对象编码着几个步骤连贯和一致。
可以减少外部程序中复杂性,使用这些实体对象的程序只需要简单的调用insert()或update()的方法,而不用去写讨厌的SQL语句。
但是,由于历史原因,即使象Java这样的新兴语言,也没有在所有地方完全利用面向对象的思想。让我们看看JDBC吧,这是一个号称用对象封装的数据库接口。可是它封装的是什么呢?连接、语句、结果集和存储过程。这其实并不是我们设计系统所关心的东西,我们关心的是数据对象本身,而不是它从数据库中提取的方法。当然,JDBC本身也不该受到太多的指责,因为他本来的目标就是封装、屏蔽关系型数据库之间的差异,而不是企图实现一个面向对象的数据库。
EJB第一次引起我的注意就是因为它提出的Entity Bean,也就是实体对象。它对实体对象提供了一套完整的实现思路,但是我认为它太复杂了,主要原因是EJB想要做的事太多了。大部分情况下我并不需要分布式处理,我也不需要把实体对象存储到文件中去。我需要的仅仅是在一个本地运行的基于数据库的程序。
二、EJB如何实现的实体对象
刚才提到了EJB已经实现了实体对象,那么让我们看看它是如何实现的。EJB中Entity Bean的对象实际上是对数据对象的一种完美的抽象,在这里我们几乎看不到数据库管理系统的作用。一个实体对象有几种状态,在内存中、在磁盘缓存中、或者在数据库中,实体对象的这些状态通常我们是不关心的,EJB的容器在必要的情况下会自动转换对象的状态,也就是说自动把它存到数据库中,或从数据库中取出。我们要访问一个数据对象,要向一个对象容器提出申请,由它返回一个对象实例供我们使用。一个Entity Bean对应于数据表中的一行。如果我们访问的是同一行数据,对象容器返回的是不同的对象,但都指向同一个Entity Bean,并把我们所有的方法请求都发送给这个Entity Bean。实际上EntityBean的容器基本实现了一个面向对象的数据库。它这种实现方法带来几个显著的问题:
运行效率非常低。JAVA的速度慢是个老问题了,EJB的速度慢不光是因为大量代码用JAVA实现,而且由于它的结构,要根据数据表中的某一个属性查出一行数据,必须首先用SQL查询查找到这一行的主键(Primary Key),然后通过主键来找到这个Bean,如果这个Bean不在内存中--很不幸,这种情况经常发生,那么实际上是执行了两次SQL查询才找到一行数据。
容器本身要管理事务,以防数据的污读、污写、死锁等等一系列问题。本来DBMS管理这类问题已经有很多年经验了,已经相当完美的解决了这些问题,可是EJB不得不通过一个Transcation Server来管理这些问题。这使得容器的代码变得极其复杂,另外编程人员也不得不重新熟悉这些接口。
由于bean 中的数据是否存储在数据库里是由容器管理的,那么其他程序访问数据库会带来数据同步的问题。因此,在EJB架构中,外部程序不能直接访问数据库,只能通过EJB访问。
三、我们实现的目标
我们只想把数据库对象更好的封装起来,为什么要购买别人昂贵的代码?为什么要为我们不会用到的分布式去牺牲大量的性能。我们想要尽量使用DBMS的功能,以实现最佳的性能和最简化的代码。
事务处理最好还是用DBMS来管理,因为它一向管得很好,而且事务处理的代码很复杂,我不打算自己来完成。
我不打算用同一个对象来指向数据库的一行。数据库的一行数据在程序中可能有多个对象,这些对象都应该是临时对象,而不是永久对象。他们的共享问题由DBMS本身加锁来解决。
由于我们只是为访问DBMS提供了一个接口,外部程序完全可以不通过这个接口来访问数据库。
实现后,使用实体对象的代码要简单。例如,数据库里有一个表account,它只有两个字段accountid和name,我们把它作为一个实体对象Account,假设我们要完成从数据库查询、修改、插入,使用它的代码片段如下:
Connection conn=ConnectionPool.getConn(); //也可以通过标准的DriverManager得到数据库连接,这是完全一样的
Conn.setAutoCommit(false); //如果不使用事务,这一行可以省去
Account a1=new Account(conn);
a1.getByAccountId(1); //查找到相应记录
System.out.println(a1.name);
a1.getByAccountIdForUpdate(1); //如果企图修改一个对象,必须通过forUpdate系列的方法得到这个对象
a1.name="new name";
a1.update(); //修改原有记录
Account a2=new Account(conn);
a2.accountId=3;
a2.name="姚大";
a2.insert(); //插入一条新记录
conn.commit();
实体对象的属性通过方法修改是比较理想的方式,如用getName(),setName()两个方法访问Name属性。这还可以解决属性之间相互关联的问题。例如,表中有一个地区代码和地区名称两个域,必须保持一致,这就可以考虑在属性设置方法中实现。在这里我们为了简单,直接通过属性修改,在一般情况下,我觉得也是可以接受到。
有一点必须注意的就是多线程程序所带来的数据完整性问题。对于我们常使用的从数据库读取数据到对象中->修改对象属性->更新到数据库这个流程,非常容易出现数据完整性破坏问题。比如一个进程中甲对象读取数据后,另一个进程中乙对象又修改了同一数据,这时甲对象再次更新数据库会带来污写。解决的办法是对象增加一个方法给数据库的这条记录加锁。例如Account.getByAccountId函数改为Account.getByAccountIdForUpdate,这个函数中相应的sql语句(ORACLE数据库)改为"select AccountId,name from account where accountId=? for update",这样数据取出后就自动加锁,这个锁将会在事务提交或回滚时释放。for update在SQLServer相应的语法为holdlock。
说到数据库加锁的问题就不能不考虑到数据库死锁的可能。想完全避免死锁是很困难的,只有尽量降低这种可能性。方法是:1、尽量少使用forUpdate这种函数,只有在更改数据库数据时才使用。查询的时候不要用,如果查询后根据某个条件有可能修改,那么在查询时不加锁,在修改前重新调用forUpdate函数加锁。2、尽量以某个特定的顺序加锁。例如有表A和表B,两个程序都要同时更新这两个表,最好都是先访问表A,再访问表B。
Oracle有个很好的功能就是自动检测死锁。如果发生死锁,会回滚一个事务,并返回一个SQL错误,我们的程序要检测这个异常,处理程序中可能的错误。
上面说到的对象中,只有getByXXX()这样的方法,这种方法只会返回唯一的对象,如果想要返回一组对象,这时需要一个辅助类来实现。这个辅助类称为对象浏览器EntityBrowser。再实体对象中返回一个对象浏览器的方法一般命名为getAllByXXX()
使用对象浏览器EntityBrowser要列出所有account表中的id和name的代码如下,其实这个对象浏览器和Java定义的Enumeration接口的最大区别就是它有一个close方法。请看下面的代码片断,它输出所有的Accout对象。
Connection conn=ConnectionPool.getConn();
Account a1=new Account(conn);
EntityBrowser browser=a1.getAll();
System.out.println("==Account List==");
While (browser.hasMoreElement()) {
Account a=(Account)browser.nextElement();
System.out.print(a.accountId);
System.out.print("--");
System.out.println(a.name);
}
browser.close();
以上就是我们要实现的实体对象,下面介绍如何编写一个实体对象。
四、实现的代码解释
首先,下面的代码定义一个所有实体对象的基础类EntityObject,这是一个抽象类,不能直接使用,但为其它实体对象定出了一个结构。
Import java.sql.*;
/**所有实体对象基础类*/
abstract public class EntityObject {
protected java.sql.Connection _conn;
private boolean _dbStored;
/**实体对象需要用一个数据库连接初始化,这样可以利用这个连接做事务提交或回滚*/
public EntityObject(Connection conn) {_conn=conn;_dbStored=false;}
/**这个方法用来插入新记录,子类必须重定义这个方法*/
public void insert() throws SQLException{ _dbStored=true;}
/**这个方法用来修改数据库原有记录,子类必须重定义这个方法*/
public void update() throws SQLException {_dbStored=true; }
/**这个方法用来删除数据库原有记录,子类必须重定义这个方法*/
public void delete() throws SQLException {_dbStored=false; }
/**这个方法用来把数据库select语句得出的结果映射到对象的属性中去,子类必须重定义这个方法*/
public void _setAttribute(ResultSet rs) throws SQLException {_dbStored=true; }
/**这个方法可以判断
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
里面有很多java资料,列举一些:J2EE配置指南,JAVA APPLET 签名和认证 ,JAVA APPLET 源程序学习,JAVA SOCKET编程,JAVA WEB START 10 ARCHITEC,JAVA 编程技术中汉字问题的,SERVLET基础例程 - HELLOSER,SOAP规范,WEBSPHERE快速入门,分布式对话服务器的管理。 先写这些吧,反正499篇文章,自己看看吧。
资源推荐
资源详情
资源评论
收起资源包目录
Java学习材料(499篇文章) (500个子文件)
实体对象的抽象以及一种基于.TXT 16KB
转:第一部分:EJB 体系结构.TXT 16KB
XP 精华----如何使 JAVA 项.TXT 16KB
简单的例子.TXT 16KB
第二部分:EJB 编程模型(转.TXT 15KB
DECLARATIONS AND ACCESS CO.TXT 15KB
用 JSP 在客户端生成 JAVASC.TXT 15KB
OVERLOADING OVERRIDING RUN.TXT 15KB
SSL與數位認證.TXT 15KB
JAVA2的安全新特性下的APPLE.TXT 14KB
SOAP规范(1).TXT 14KB
EJB一则,FRANZY@163NET多多.TXT 14KB
JAVA 编程技术中汉字问题的.TXT 14KB
JDBC技术介绍 转.TXT 14KB
JAVA 程序编码规范.TXT 14KB
(2).TXT 14KB
将 MICROSOFT 的 INTERNET I.TXT 14KB
THREADS.TXT 14KB
SERVLET23.TXT 14KB
EJB内部资参1.TXT 13KB
转载--微软98年关于MTS和EJB.TXT 13KB
SOAP规范(2).TXT 13KB
JAVASERVER PAGESTM 白皮书.TXT 13KB
53 CORBA技术及实例.TXT 13KB
WEBSPHERE快速入门(2).TXT 13KB
在JSP页面中实现检索数据的.TXT 13KB
JDBCTM 指南:入门.TXT 13KB
WEBSPHERE快速入门(22).TXT 12KB
JSP高级技术如何开发动态网站.TXT 12KB
JAVAJSP 好的入门文章共赏.TXT 12KB
JAVASERVER PAGES (JSP) 10.TXT 12KB
JDBC 入门.TXT 12KB
BEGINNER USING SERVLETS TO.TXT 12KB
三种WEB开发主流技术ASP-PHP.TXT 12KB
值得关注:JAVA 14 即将发布.TXT 12KB
WEBSPHERE快速入门(14).TXT 12KB
用连接池提高SERVLET访问数.TXT 11KB
JAVA 线 程 的 讨 论 与 应 .TXT 11KB
JSPSERVLET 中的汉字编码问.TXT 11KB
用JAVA绘制K线 (转2).TXT 11KB
JSP - FAQ (2).TXT 11KB
JAVA性能的优化(下)(转).TXT 11KB
用 JAVA 保存位图文件(转).TXT 11KB
转帖:JAVA无用论.TXT 11KB
在网页上发布统计曲线.TXT 11KB
最大限制地提高代码的可重用.TXT 11KB
(3).TXT 11KB
GOOD JAVA STYLE PART 2.TXT 11KB
WEBSPHERE快速入门(17).TXT 11KB
SOAP规范(完).TXT 10KB
OPERATORS AND ASSIGNMENTS(.TXT 10KB
用JSP和数据库做的购物车的.TXT 10KB
EJB概述(下).TXT 10KB
如何用 SERVLET 打开非 HTML.TXT 10KB
困扰JSP的一些问题.TXT 10KB
JAVA的网络功能与编程 一(.TXT 10KB
FTP站点荟萃,你自己找找看.TXT 10KB
用JAVA转换简繁体的基础知识.TXT 10KB
JAVA混淆编译器(转APUSICCO.TXT 10KB
JBUILDER 5新增功能介绍.TXT 10KB
安装好你的机器来使用JSP(.TXT 10KB
给你一个SERVLET例子,JSP差.TXT 10KB
JDBCTM 指南:入门2 - 连接.TXT 10KB
JAVA 在CLIENTSERVER 网络中.TXT 10KB
回复有没有现成的CLASS实现C.TXT 10KB
回复如何在WEB页上实现文件.TXT 10KB
回复JAVA新手的问题!.TXT 10KB
用 JAVA 保存位图文件.TXT 10KB
COOKIE 规范.TXT 10KB
使用JAVABEAN高效处理JSP(2).TXT 10KB
JDBCTM 指南:入门4 - STATE.TXT 10KB
杂谈 BY HAHA.TXT 9KB
第一部分:EJB 体系结构的历.TXT 9KB
好文--JIVE 中的设计模式 (.TXT 9KB
JAVA中文问题详解(转).TXT 9KB
续 太长了.TXT 9KB
JSP 的模板.TXT 9KB
JSPSERVLET中文问题的解决(.TXT 9KB
JAVA WEB START 10 FAQ.TXT 9KB
52 分布式应用开发技术概述.TXT 9KB
给你一篇IBM的介绍STRUCTS的.TXT 9KB
JSP - FAQ (5).TXT 9KB
如何在 JAVA 应用程序中读取.TXT 9KB
JSP 构 架--2种方式.TXT 9KB
SERVLET 和 XML:互为补充(.TXT 9KB
准备翻译J2EE的DOC,不知道.TXT 9KB
JSP - FAQ (1).TXT 9KB
LANGUAGE FUNDAMENTALS.TXT 9KB
基于MYSQL的高性能数据库应.TXT 9KB
GOOD JAVA STYLE PART 1.TXT 9KB
JAVA的网络功能与编程 二 .TXT 9KB
JSP - FAQ (3).TXT 9KB
内有一篇文章或许有用.TXT 8KB
利用JAVA实现串口全双工通讯.TXT 8KB
最大化JAVA代码的可重用性 (.TXT 8KB
ACME包中的以POST方式发送数.TXT 8KB
JAVA正则表达式详解(下).TXT 8KB
我的面向对象程序观 (转).TXT 8KB
WEBSPHERE快速入门(8).TXT 8KB
用 JAVABEAN 来实现 MYSQL .TXT 8KB
共 500 条
- 1
- 2
- 3
- 4
- 5
资源评论
Jay_lion
- 粉丝: 1
- 资源: 12
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功