《Java数据对象技术JDO三.ppt》由会员分享,可在线阅读,更多相关《Java数据对象技术JDO三.ppt(23页珍藏版)》请在三一办公上搜索。
1、Java数据对象技术JDO三,项目目录结构对于Media Mania应用开发环境来说,你需要采用下面的目录结构,这个项目必须有一个根目录,存在于系统的文件体系的某个地方。下面这些目录都是以这个根目录为基准的:src这个目录包括应用的所有源码。在src目录下,有一个按照com/mediamania/prototype结构的子目录体系(与Java中的com.mediamania.prototype包相对应)。这也是Movie.java、Actor.java和Role.java源文件所在的目录。classes当Java源码被编译时,生成的.class文件置于这个目录中enhanced这个目录存放增强
2、后的.class类代码文件(由增强器所产生)database这个目录存放JDO参考产品用于存储数据的文件。,尽管这样的目录结构并不是JDO规范所要求的,但你得理解它,这样才能跟随我们对Media Mania应用的描述。当你执行你的JDO应用时,Java运行环境必须调入增强版本的类文件,也就是处于enhanced目录中的类文件。因此,在你的CLASSPATH中这个目录必须处于classes目录之前。作为一种可选方案,你也可以采用就地增强,用你的增强后的类文件直接替换未增强的文件。增强类代码以便存储类在其实例被JDO环境处理之前必须先被增强。JDO增强器在你的类中加入额外的数据和方法,使其实例可以
3、被JDO产品处理。增强器先从由javac编译器所产生的类文件中读取信息,再根据元数据来生成新的增强过的包含必要功能的类文件。JDO规范化了增强器所做的改变,使得增强后的类文件具有二进制兼容性,可以在其它的JDO产品中使用。这些增强后的文件也独立于任何具体的数据库。,前面已经提到,Sun公司提供的JDO参考产品中的增强器称作参考增强器。而JDO产品厂商一般可能会提供自己的增强器;在命令行调用增强器的语法可能会与这里提到的有所不同。每个产品都会向你提供文档以阐释如果在该产品上对你的类进行增强。例1-5给出了使用参考增强器对我们的Media Mania应用的类进行增强的命令行。-d参数指明将要存放增
4、强后的类文件的目录,我们已经计划放到enhanced目录下。增强器接收一系列JDO元数据文件和一系列需要增强的类文件作参数。目录之间的分隔符和续行符(line-continuation)可能会不一样,这依赖于你进行编译的操作系统。例1-5 对类进行增强java com.sun.jdori.enhancer.Main-d enhancedclasses/com/mediamania/prototype/package.jdoclasses/com/mediamania/prototype/Movie.classclasses/com/mediamania/prototype/Actor.clas
5、sclasses/com/mediamania/prototype/Role.class,尽管将元数据文件与源代码放在一起会比较方便,JDO规范还是推荐元数据文件可以作为与类文件一起作为资源被类载入器(ClassLoader)调入。元数据在编译时和运行时都需要,所以,我们将package.jdo元数据文件放在classes目录体系中的prototype包的目录中。在例1-5中,我们的对象模型中的所有.class类文件被一起列出,但你也可以将每个类文件单独增强。当这个增强命令执行时,它将增强后的新文件放到enhanced目录下。创建数据库连接和事务,现在既然我们的类已经被增强了,它们的实例也就可
6、以被储存到数据库中了。我们现在来看看应用中如果创建一个与数据库的连接并在一个事务(Transaction)中执行一些操作。我们开始写直接使用JDO接口的软件代码,所有的在应用中用到的JDO接口都定义在javax.jdo包中。JDO中有一个接口叫做PersistenceManager(存储管理器,见术语表),它具有一个到数据库的连接。一个PersistenceManager还有一个JDO中的Transaction(事务)接口的实例,用于控制一个事务的开始和结束。这个Transaction实例的获取方式是调用PersistenceManager实例的currentTransaction()方法。获
7、取一个PersistenceManagerPersistenceManagerFactory(存储管理器工厂,见术语表)用来配置和获取PersistenceManager。PersistenceManagerFactory中的方法用来设置一些配置属性,这些配置属性控制了从中获得的PersistenceManager实例的行为。于是,一个JDO应用的第一步便是获取一个PersistenceManagerFactory实例。要取得这个实例,需要调用下面的JDOHelper类的静态方法:,static PersistenceManagerFactory getPersistenceManagerFa
8、ctory(Properties props)这个Properties实例可以通过程序设置,也可以从文件中读取。例1-6列出了我们将在Media Mania应用中用到的配置文件的内容。其中,第行中的PersistenceManagerFactoryClass属性通过提供具体JDO产品的PersistenceManagerFactory接口实现类来指明采用哪个JDO产品。在本例中,我们指明Sun公司的JDO参考产品所定义的类。例1-6中列出的其它的属性包括用于连接到特定的数据库的连接URL和用户名/密码,这些一般都是连接到具体的数据库所需要的。例1-6 jdo.properties文件内容jav
9、ax.jdo.option.ConnectionURL=fostore:database/fostoredbjavax.jdo.option.ConnectionUserName=davejavax.jdo.option.ConnectionPassword=jdo4mejavax.jdo.option.Optimistic=false,这个连接URL的格式依赖于采用的具体的数据库。在JDO参考产品中包括它自己的存储机制,称作文件对象数据库File Object Store(FOStore)。例1-6中的ConnectionURL属性标明了实际使用的数据库位于database目录中,在我们的项
10、目的根目录下。在本例中,我们提供了一个相对路径;但提供绝对路径也是可以的。这个URL同时指明了FOStore数据库文件名称将以fostoredb开头。如果你使用了别的JDO产品,你需要对以上这些属性提供另外的值,可能你还得提供一些额外的属性。请参阅该产品的文档以获取需要配置的必要的属性的说明。创建一个FOStore数据库要使用FOStore我们必须先创建一个数据库。例1-7中的程序利用jdo.properties文件创建一个数据库;所有的应用都使用这个配置文件。第行将这些配置属性从jdo.properties文件中调入到一个Properties实例中。该程序的第行加入了一个com.sun.jd
11、ori.option.ConnectionCreate属性以指明数据库需要创建。将其设为true,就能引导参考产品创建该数据库。我们在第行调用getPersistenceManagerFactory()来获取PersistenceManagerFactory。第行生成一个PersistenceManager。,为完成数据库的创建,我们还需要开始并结束一个事务。第行中调用了PersistenceManager的currentTransaction()方法来访问与该PersistenceManager相关联的Transaction实例。第行和第行调用这个Transaction实例的begin()和
12、commit()方法来开始和结束一个事务。当你执行这个程序时,在database目录下就会生成一个FOStore数据库,包括两个文件:fostore.btd和fostore.btx.例1-7 创建一个FOStore数据库package com.mediamania;import java.io.FileInputStream;import java.io.InputStream;import java.util.Properties;import javax.jdo.JDOHelper;import javax.jdo.PersistenceManagerFactory;import java
13、x.jdo.PersistenceManager;import javax.jdo.Transaction;,public class CreateDatabase public static void main(String args)create();public static void create()try InputStream propertyStream=new FileInputStream(jdo.properties);Properties jdoproperties=new Properties();jdoproperties.load(propertyStream);j
14、doproperties.put(com.sun.jdori.option.ConnectionCreate,true);PersistenceManagerFactory pmf=JDOHelper.getPersistenceManagerFactory(jdoproperties);PersistenceManager pm=pmf.getPersistenceManager();Transaction tx=pm.currentTransaction();,tx.begin();mit();catch(Exception e)System.err.println(Exception c
15、reating the database);e.printStackTrace();System.exit(-1);JDO参考产品提供了这种程序化创建FODatastore数据库的方式,而大多数数据库都提供一个独立于JDO的工具来创建数据库。JDO并不规定一个与厂商无关的接口来创建数据库。数据库的创建一般都与具体使用的数据库相关。本程序中显示了在FOStore数据库中是如何完成这一步的。,另外,如果你在关系数据库上使用JDO,某些情况下可以有一个额外的步骤:根据对象模型创建或者将对象模型映射到一个现存的数据库模式(shema,即某数据库用户及其所拥有的数据表体系的合称)。创建一个数据库模式的过
16、程与你采用的具体JDO产品的有关,你需要查看该产品的文档来决定采取必要的步骤。对实例的操作 至此我们已经有了一个可以存放数据类的实例的数据库,每个程序需要获得一个PersistenceManager来访问或更新该数据库。例1-8给出了MediaManiaApp类的源码,这个类是本书中的每个应用程序的基础类,每个程序是在execute()方法中实现了具体的业务逻辑的一个具体的子类(Concrete子类,相对于抽象Abstract而言)。,MediaManiaApp有一个构造器用来从jdo.properties中读取配置信息(行)。从该文件调入配置信息后,它调用getPropertyOverrid
17、es()方法并且合并成最终的属性集(properties)到jdoproperties对象中。一个程序子类可以重载getPropertyOverrides()来提供额外的配置信息或者更改jdo.properties文件中给出的配置。这个构造器获取一个PersistenceManagerFactory(行),然后获取一个PersistenceManager(行)。我们还提供一个getPersistenceManager()方法以便在MediaManiaApp类之外获取PersistenceManager。与PersistenceManager关联的Transaction在第行获取。各个程序子类调
18、用一个在MediaManiaApp类中定义的executeTransaction()方法,这个方法在行中开始一个事务,然后在行中调用execute()方法,也即执行子类中的具体功能的方法。我们选择了一个特别的程序类的设计来简化和减少创建一个可运行的环境的冗余代码。这些并不是JDO所要求的,你也可以根据自己的应用程序环境选择最为合适的方式。,当(子类中实现的)execute()方法返回后,我们会尝试提交这个事务(行),而如果有任何异常发生的话,我们会回滚(rollback)这个事务并将异常信息打印到系统错误输出流中(System.err)。例1-8 MediaManiaApp基类package
19、com.mediamania;import java.io.FileInputStream;import java.io.InputStream;import java.util.Properties;import java.util.Map;import java.util.HashMap;import javax.jdo.JDOHelper;import javax.jdo.PersistenceManagerFactory;import javax.jdo.PersistenceManager;import javax.jdo.Transaction;,public abstract c
20、lass MediaManiaApp protected PersistenceManagerFactory pmf;protected PersistenceManager pm;protected Transaction tx;public abstract void execute();/defined in concrete application subclassesprotected static Map getPropertyOverrides()return new HashMap();,public MediaManiaApp()try InputStream propert
21、yStream=new FileInputStream(jdo.properties);Properties jdoproperties=new Properties();jdoproperties.load(propertyStream);jdoproperties.putAll(getPropertyOverrides();pmf=JDOHelper.getPersistenceManagerFactory(jdoproperties);pm=pmf.getPersistenceManager();tx=pm.currentTransaction();,catch(Exception e)
22、e.printStackTrace(System.err);System.exit(-1);public PersistenceManager getPersistenceManager()return pm;public void executeTransaction()try tx.begin();execute();,mit();catch(Throwable exception)exception.printStackTrace(System.err);if(tx.isActive()tx.rollback();存储实例我们来看看一个简单的程序,名为CreateMovie,用于存储一个
23、Movie实例,如例1-9所示。该的功能被放在execute()方法中。构造一个CreateMovie的实例后,我们调用MediaManiaApp基类中定义的executeTransaction()方法,它会调用本类中重载过的execute()方法。这个execute()方法中行初始化一个单独的Movie实例,然后在行调用PersistenceManager的makePersistent()方法保存这个实例。如果这个事务成功提交(commit),这个Movie实例就会被存储到数据库中。,例1-9 创建一个Movie实例并保存它package com.mediamania.prototype;i
24、mport java.util.Calendar;import java.util.Date;import com.mediamania.MediaManiaApp;public class CreateMovie extends MediaManiaApp public static void main(String args)CreateMovie createMovie=new CreateMovie();createMovie.executeTransaction();,public void execute()Calendar cal=Calendar.getInstance();c
25、al.clear();cal.set(Calendar.YEAR,1997);Date date=cal.getTime();Movie movie=new Movie(Titanic,date,194,PG-13,historical,drama);pm.makePersistent(movie);,现在我们来看一个更大的应用程序:LoadMovies,如例1-10中所示,它从一个包含电影信息的文件中读取并创建多个Movie实例。这个信息文件名作为参数传递到程序中,LoadMovies构造器初始化一个BufferedReader来读取信息。execute()方法通过调用parseMovieD
26、ate()每次从这个文件读取一行并分析之,从而在行创建一个Movie实例,并在行保存之。当这个事务在executeTransaction()中提交时,所有新创建的Movie实例都会被保存到数据库中。例1-10 LoadMoviespackage com.mediamania.prototype;import java.io.FileReader;import java.io.BufferedReader;import java.util.Calendar;import java.util.Date;import java.util.StringTokenizer;import javax.jd
27、o.PersistenceManager;import com.mediamania.MediaManiaApp;,public class LoadMovies extends MediaManiaApp private BufferedReader reader;public static void main(String args)LoadMovies loadMovies=new LoadMovies(args0);loadMovies.executeTransaction();public LoadMovies(String filename)try FileReader fr=ne
28、w FileReader(filename);reader=new BufferedReader(fr);catch(Exception e)System.err.print(Unable to open input file);System.err.println(filename);,e.printStackTrace();System.exit(-1);public void execute()try while(reader.ready()String line=reader.readLine();parseMovieData(line);catch(java.io.IOExcepti
29、on e)System.err.println(Exception reading input file);e.printStackTrace(System.err);public void parseMovieData(String line)StringTokenizer tokenizer new StringTokenizer(line,;);String title=tokenizer.nextToken();,String dateStr=tokenizer.nextToken();Date releaseDate=Movie.parseReleaseDate(dateStr);i
30、nt runningTime=0;try runningTime=Integer.parseInt(tokenizer.nextToken();catch(java.lang.NumberFormatException e)System.err.print(Exception parsing running time for);System.err.println(title);String rating=tokenizer.nextToken();String genres=tokenizer.nextToken();Movie movie=new Movie(title,releaseDate,runningTime,rating,genres);pm.makePersistent(movie);,