TopLink 是位居第一的 Java 对象关系可持续性体系结构,原署WebGain公司的产品,现在被Oracle收购,并重新包装为 Oracle AS TopLink。TOPLink为在关系数据库表中存储 Java 对象和企业 Java 组件 (EJB) 提供高度灵活和高效的机制。TopLink 为开发人员提供极佳的性能和选择,可以与任何数据库、任何应用服务器、任何开发工具集和过程以及任何 J2EE 体系结构协同工作。本文仍然以业界已广为使用的TOPLink 3.5为参考版本,简单讲述TOPLink的使用要点。本文并不是一个Step by Step的入门实例教程,而是着眼与TOPLink的一些基本概念,总结了一些使用要点,从中也可以窥探TOPLink的使用方式和它的设计原理。
一、连接数据库
? Create a login object
project.getLogin()
new DatabaseLogin()
? Specifying database and driver information
//project.getLogin().useOracle();
project.getLogin().setDriverClass(oracle.jdbc.driver.OracleDriver.class);
project.getLogin().setConnectionString(“jdbc:oracle:thin@dbserver:1521:orc1”)
? Setting login parameters
project.getLogin().setUserName(“scott”);
project.getLogin().setPassword(“tiger”);
? 实例代码1
DatabaseLogin.setLicensePath(“c:\\Program Files\\Common Files\\WebGain Shared\\”)
Project project = new MyProject();
project.getLogin().setUserName(“userid”);
project.getLogin().setPassword(“passwd”);
DatabaseSession session = project.createDatabaseSession();
session.login();
? 实例代码2
DatabaseLogin.setLicensePath(...);
DatabaseLogin login = new DatabaseLogin();
login.set...
...
Project project = new Project(login);
DatabaseSession session = project.createDatabaseSession();
session.login();
二、DatabaseSession的使用
一个应用必须创建一个DatabaseSession,其中存储了如下内容:
1. 一个Project、DatabaseLogin实例(存储了数据库登录、配置信息)
2. 一个DatabaseAccessor实例(包装了JDBC连接,处理数据库访问)
3. 应用的所有持久类的descriptors
4. 作为cache的一个对象Map
DatabaseSession的实例必须由Project的实例创建得到,project对象必须由正确的数据库配置参数初始化,比如JDBC Driver、DB Url。
? 注册descriptors(在login前,login后也可但要注册的应不同于任何已注册的descriptor)
DatabaseSession.addDescriptors(Vector) or DatabaseSession.addDescriptor(Descriptor)
? 连接数据库
DatabaseSession.login(),连接后就可以使用此Session访问数据库了,使用“Query Framework”
? 缓存
可使用initializeIdentityMaps()方法来刷新缓存。注意:使用前要确认缓存中的对象没有被使用。
? 登出数据库
DatabaseSession.logout(),再次登入时不需要注册descriptors
可以通过下面代码指定DatabaseSession的例外处理过程:
session.setExceptionHandler(new ExceptionHandler(){
public handleException(RuntimeException ex){
if((ex instanceof DatabaseException) && (ex.getMessage().equals(“connection reset by peer”)){
ex.getAccessor().reestablishConnection(ex.getSession());
return ex.getSession().executeQuery(ex.getQuery());
}
}
});
三、一段使用TOPLink的完整的实例代码
import TOPLink.Public.Sessions.*;
DatabaseLogin.setLicensePath(“”);
DatabaseLogin loginInfo = new DatabaseLogin();
loginInfo.useJDBCODBCBridge();
loginInfo.useSQLServer();
loginInfo.setDataSourceName(“dbserver”);
loginInfo.setUserName(“”);
loginInfo.setPassword(“”);
Project project = new Project(loginInfo);
DatabaseSession session = project.createDatabaseSession();
session.addDescriptors(this.buildAllDescriptors());
try {
session.login();
} catch(DatabaseException exception){
throw new RuntimeException(“Database error occurred at login: “+exception.getMessage());
System.out.println(“Login failed.”);
}
...
session.logout();
四、查询框架(Query Framework)
直接调用DatabaseSession对象提供的方法,完成查询、更新等操作。在更新操作时,会使用UnitOfWork,以提供优化的性能。
? 示例代码
Employee employee = (Employee)session.readObject(Employee.class,
new ExpressionBuilder().get(“lastName”).equals(“Smith”));
Vector employees = session.readAllObjects(Employee.class,
new ExpressionBuilder().get(“salary”).greaterThan(“1000”));
五、使用Expression
Toplink提供一种叫Expression的机制允许基于对象模型的查询机制,Toplink翻译这些Expressions为SQL语句,再把查询结果转换为对象返回。
1. 创建Expression
Expression总是通过Expresson或ExpressionBuilder的.get()方法得到,ExpressionBuilder可看作一个所查询对象的替身。一般命名为相应对象的名字。
一个ExpressionBuilder的实例与一个特定的Query相关联,不要企图使用同一个Builder来生成多个Expression。
2. 子查询
ReportQuery是为了得到一个对象集的信息,而不是对象本身。常用方法:
addAttribute(String),addAverage(String),addCount(String)等。
1) 示例代码1
查询包含5个以上被管理职员的职员
ExpressionBuilder emp = new ExpressionBuilder();
ExpressionBuilder managedEmp = new ExpressionBuilder();
ReportQuery subQuery = new ReportQuery(Employee.class,managedEmp);
subQuery.addCount();
subQuery.addSelectionCriteria(managedEmp.get(“manager”).equals(emp)); //?
Expression exp = emp.subQuery(subQuery).greaterThan(5);
2) 示例代码2
查询住址在Ottawa的工资最高的职员
ExpressionBuilder emp = new ExpressionBuilder();
ExpressionBuilder ottawaEmp = new ExpressionBuilder();
ReportQuery subQuery = new ReportQuery(Employee.class,ottawaEmp);
subQuery.addMax(“salary”);
subQuery.setSelectionCriteria(ottawaEmp.get(“address”).get(“street”).equals(“Ottawa”));
Expression exp = emp.get(“salary”).equals(subQuery).
and(emp.get(“address”).get(“street”).equals(“Ottawa”));
3. Parallel Expressions
Parallel Expression必须拥有它自己的ExpressionBuilder,并且这个Builder的构造方法必须以一个class作为参数。只存在唯一的主 ExpressionBuilder,这个主Builder使用空参数的构造器,它的类将从Query中得到。
1) 实例代码
查询所有具有相同lastName不同性别的职员
ExpressionBuilder emp = new ExpressionBuilder(); //主Builder
ExpressionBuilder spouse = new ExpressionBuilder(Employee.class); // Parallel Builder
Expression exp = emp.get(“lastName”).equal(spouse.get(“lastName”)) //基于对象模型的思考
.and(emp.get(“spouse”).equal(spouse.get(“spouse”))
.and(emp.notEqual(spouse));
4. 参数化Expressions、finders
1) 参数化表达式示例
//构造查询用的表达式,注意带一个firstName的参数
ExpressionBuilder emp = new ExpressionBuilder();
Expression firstNameExpression =
emp.get(“firstName”).equal(emp.getParameter(“firstName”));
//生成一个ReadObjectQuery对象,设置Query的参考类、查询条件、参数
ReadObjectQuery query = new ReadObjectQuery();
query.setReferenceClass(Employee.class);
query.setSelectionCriteria(firstNameExpression);
query.setArgument (“firstName”);
//进行查询
Vector v = new Vector();
v.addElement(“Sarah”);
Employee e = (Employee) session.excuteQuery(query,v);
2) 嵌套参数化表达式示例
ExpressionBuilder emp = new ExpressionBuilder();
Expression addressExpression;
//生成嵌套的参数化表达式
addressExpression = emp.get (“address”).get (“city”).equal (
emp.getParameter (“employee”).get (“address”).get (“city”));//嵌套的表达式
ReadObjectQuery query = new ReadObjectQuery (Employee.class);
query.setSelectionCriteria (addressExpression);
query.addArgument (“employee”); // ?
//设置参数,执行查询
Vector v = new Vector ();
v.addElement (employee);
Employee e = (Employee) session.excuteQuery (query,v);
Java 开发人员需要使用关系数据库获得可持续性。使用 TopLink 可以消除在构造持久层时所涉及的内在风险。TOPLink几乎能够处理持久性方面的任何情况。TopLink提供一个持久性基础架构,使开发人员能够将来自多种体系结构的数据(包括EJB(CMP和BMP)、常规的Java对象、servlet、JSP、会话bean和消息驱动bean)集成在一起。TopLink允许Java应用程序访问作为对象存储在关系数据库中的数据,从而极大地提高了开发人员的工作效率。TopLink还具有通过最大限度地降低数据库命中率和网络流量及利用由JDBC和数据库提供的最优化来提升应用程序性能的特性。TopLink是通过创建一个元数据"描述符"(映射)集来实现上述特性的,这些元数据描述符定义了以一个特定的数据库模式存储对象的方式。TopLink在运行时使用这些映射动态地生成所需的SQL语句。这些元数据描述符(映射)独立于语言和数据库,开发人员能够在无需对它们所表示的类进行重编译的情况下修改它们。