在 HTML 中,当控制转移到新页时,旧页的已分配 JavaScript 对象的所有句柄都会丢失。例如,在 main.html 中,您拥有一个 M-Business Anywhere 数据库连接对象:
conn = dbMgr.openConnection("..."); |
如果您在 main.html 中单击一个链接并且它将您带到一个不同的页(例如:insert.html),那么,您在 insert.html 中找不到名为 "conn" 的对象。要取回连接对象,您可能需要再次调用 dbMgr.openConnection("...")。但是,您不必执行此操作,因为连接对象仍在内存中,您仅仅丢失了它的 JavaScript 句柄。
这就是为什么在对 DataManager、Connection、ULTable、PreparedStatement 或 ResultSet 的所有 M-Business Anywhere API 调用中都有一个 persistName 参数的原因。例如,当 M-Business Anywhere 运行库接收到来自 JavaScript 对 UltraLite 连接对象的调用时,M-Business Anywhere 首先检查具有相同 persistName 的连接对象是否存在于内存中。如果运行时能够找到匹配的对象,它将返回该连接对象。否则,M-Business Anywhere 执行常规过程创建一个新的 UltraLite 数据库连接并返回它。
在 M-Business Anywhere 对象中有两种类型的层次。它们都从 DatabaseManager 和 Connection 开始:
要用永久名称检索这些 M-Business Anywhere 对象中的任何一个,您需要先用永久名称检索顶级对象,然后再沿着层次树检索所有上级 M-Business Anywhere 对象,直到检索到您想要的那一个。
例如,如果您想从 insert.html 中检索一个现有的 ULTable 对象,则需要在 main.html 中将永久名称赋给 dbMgr、conn 和 table 对象,然后在 insert.html 中使用永久名称将它们全部取回:
main.html 的代码段:
var dbMgr = CreateObject( "iAnywhere.UltraLite.DatabaseManager.simple" ); // "simple" is the persistent name here. A real database manager object is allocated var conn = dbMgr.openConnection( "CON=simple_con;..." ); // "simple_con" is the persistent name here. A real database connection is made. var custTable = conn.getTable( "ULCustomer", "simpleCustTable" ); // a real table is allocated |
insert.html 的代码段:
var dbMgr = CreateObject( "iAnywhere.UltraLite.DatabaseManager.simple" ); // "simple" is the persistent name here. // The allocated database manager object from main.html is returned var conn = dbMgr.openConnection( "CON=simple_con;..." ); // "simple_con" is the persistent name here. // The existing connection object from memory is returned. var custTable = conn.getTable( "ULCustomer", "simpleCustTable" ); // the existing table object is returned. var newTable = conn.getTable( "ULOrder", "simpleOrderTable" ); // since there is no order table from main.html, // it does not exist in memory. A real order table object is allocated. |
将常用代码置于一个 JavaScript 文件中。既然 M-Business Anywhere 应用程序中大部分的 HTML 页都需要引用 DatabaseManager、Connection 和一些主要的 ULTable 对象,那么将创建它们(或用永久名称检索它们)的代码置于一个公用 JavaScript 文件中并在使用它们的 HTML 页的顶部包含该文件是很方便的。 M-Business Anywhere "simple" 和 "CustDB" 示例程序都演示了如何实现此操作。
如果您不打算在另一页上使用对象,请关闭该对象。如果 M-Business Anywhere 应用程序只有一个 HTML 页,那么就没有必要拥有永久名称。永久名称参数可以设置为 NULL。另一方面,如果每个 HTML 页都有许多打开的 PreparedStatement 和 ResultSet 对象,那么开发人员需要在以下两点之间取得平衡:在内存中保存这些对象以使用永久名称从另一 html 页中容易地检索它们的方便性,与由于这些对象始终到处存在而浪费的内存使用量。例如,假设您拥有在 main.html 中创建的 5 个 PreparedStatement 对象和 10 个 ResultSet 对象。它们占用了相当大的内存空间。当应用程序跳转到 insert.html 时,如果您只需用永久名称引用其中的一些对象,则那些不再需要的对象就会浪费内存。如果您想在 insert.html 中创建新的 PreparedStatement 和 ResultSet 对象,则可能会使内存不足。解决方案就是在 main.html 结尾处显式关闭那些 PreparedStatement 对象或 ResultSet 对象,如果您确定在 insert.html 中不再需要这些对象。
当用永久名称检索 M-Business Anywhere 对象时,将保持每一个 M-Business Anywhere 对象的状态。如果您在第 1 页中拥有永久的 ULTable 对象,则当您使用同一永久名称在第 2 页中调用 openTable 方法时,就会取回与第 1 页中对象状态相同的同一 ULtable 对象。如果当您离开第 1 页时,游标处于表的第 n 行,那么当您在第 2 页中将它取回时,游标仍在第 n 行。游标不会是 "在第一行之前"。
对 ResultSet 要谨慎使用永久名称。当在 PreparedStatement 中有占位符时,在是否赋予 ResultSet 一个永久名称上需要特别谨慎。例如,在 main.html 中,您拥有以下代码:
var OrderStmt = Connection.prepareStatement( "SELECT order_id, disc, quant FROM ULOrder WHERE order_id = ?", "order_query_stmt" ); OrderStmt.setInt(1, 5000); var OrderResultSet = OrderStmt.executeQuery( "order_query_result" ); |
然后您在 insert.html 中需要同一个 ResultSet 对象,则必须执行以下操作:
var OrderStmt = Connection.prepareStatement( "SELECT order_id, disc, quant FROM ULOrder WHERE order_id = ?", "order_query_stmt" ); //OrderStmt.setInt(1, 5000); // no need to do this since both the OrderStmt and OrderResultSet are retrieve from "cache" without any SQL statement being actually executed var OrderResultSet = OrderStmt.executeQuery( "order_query_result" ); |
此 OrderResultSet 对象包含与设置为 5000 的 "order_id" 相同的结果。
但是,请考虑一种不同的情况。因为您想要对 Order 表执行同一查询,所以您需要相同的 PreparedStatement。但是您想要使用不是 5000 的订单 ID 进行查询。这种情况下,您可以为 PreparedStatement 指派一个永久名称,但是 ResultSet 不需要永久名称。既然这次的订单 ID 不同,那么结果集也与前一个有所不同。在 main.html 中,仍需要执行以下操作:
var OrderStmt = Connection.prepareStatement( "SELECT order_id, disc, quant FROM ULOrder WHERE order_id = ?", "order_query_stmt" ); // with persistent name OrderStmt.setInt(1, 5000); var OrderResultSet = OrderStmt.executeQuery( null ); // notice here, no persistent name |
在 insert.html 中,执行以下操作以获取一个新的 ResultSet:
var OrderStmt = Connection.prepareStatement( "SELECT order_id, disc, quant FROM ULOrder WHERE order_id = ?", "order_query_stmt" ); // get the prepared statement from memory with persistent name OrderStmt.setInt(1, 6000); // set a different place holder value var OrderResultSet = OrderStmt.executeQuery( null ); // a real query is executed here! |
在以上示例中,因为占位符值不同或者对 Order 表执行了一些预期返回的结果集将不同的其它操作,所以在调用 executeQuery 时对 ResultSet 不使用永久名称。
Copyright © 2009, iAnywhere Solutions, Inc. - SQL Anywhere 11.0.1 |