编写高性能 Java 数据访问应用程序,第 2 部分: pureQuery 内联方法风格简介

简介

pureQuery

pureQuery 是为 IBM Data Studio 提供的一个特性,可以通过 IBM Data Studio pureQuery RuntimeIBM Data Studio Developer 获得。

pureQuery 为 SQL 执行引入了两种编程风格:内联方法编程风格和带注释的方法编程风格。这些编程风格为存储和检索对象(例如 Java bean 和 map)提高了现成的支持,从而简化了 Java 数据访问开发。内联编程风格还支持使用定制的用户定义的结果处理。

带注释的方法风格提供一种基于注释的数据访问方法。在带注释的方法风格中,SQL/XQUERY 字符串是在一个 pureQuery 注释(Annotation)中定义的。这些注释被放在用户定义接口中的方法声明上。代码生成器对接口进行预处理,生成每个带注释的方法的实现代码。生成的实现代码使用 pureQuery 运行时执行注释中定义的 SQL 语句。要了解关于带注释的方法风格的更多信息,请参阅本系列的 第 1 部分pureQuery 文档

pureQuery 内联编程风格的目的是减少使用 JDBC 查询或更新数据库时常见的一些重复任务。内联方法风格引入了一组定义良好的、有效的 API,它们比 JDBC 更简单,更易于使用。在内联风格中,可以在代码中像 Java String 对象一样 “内联” 地创建 SQL/XQUERY 语句。这种动态生成的语句被作为 String 参数传递给 pureQuery Data 接口方法。内联风格使用 JDBC 最佳实践,并利用特定于数据库的 API 来提高性能。内联方法风格的一个例子是使用批量更新和改进的结果集处理。在带注释的方法风格中,SQL 必须在编译时定义,而内联方法则不同,它支持在运行时动态创建和执行 SQL 语句。在应用程序中,SQL 是 “内联” 和可见的,因此更容易发现错误并做出更正。内联风格还有一个可插入式定制结果处理,用于轻松地映射数据库列。

表 1 中的代码片段演示了内联方法风格的简单性和易用性。


表 1. JDBC 与 pureQuery 内联风格之间的代码比较

JDBC pureQuery 内联风格
try  {



  //SQL for insert
  String sqlins="'insert into CUSTOMER ("
  +    "NAME, COUNTRY, STREET, CITY, PROVINCE, ZIP,"
  +    "PHONE,INFO)"
  +    "values( ?, ?, ?, ?, ?, ?, ?, ?)";



  //prepare the INSERT statement
  PreparedStatement pstmt = 
       con.prepareStatement(sqlins );

  // setup parameters
  pstmt.setString (1, "custName");
  pstmt.setString (2, "custCountry");
  pstmt.setString (3, "custStreet");
  pstmt.setString (4, "custCity");
  pstmt.setString (5, "custProvince");
  pstmt.setString (6, "custZip");
  pstmt.setString (7, "custPhone");
  pstmt.setString (8, "custInfo");

  
  //execute the INSERT statement
  pstmt.execute();



  //close the prepared statement
  pstmt.close();

  // SQL for SELECT
  String sqlSel = "select Name, Country, Street, "
  + "Province,Zip from CUSTOMER where Customer = ?"; 

  //prepare the SELECT statement 
  pstmt =  con.prepareStatement(sqlSel);
  
  //set the Input parameter
  pstmt.setString (1, "custCountry");

  //execute SELECT statement
  pstmt.execute();



  //get the results and set values in Customer Bean
  ResultSet result = pstmt.getResultSet ();
  List<Customer> custList = 
  new ArrayList<Customer>();
  while (result.next ()) {
  Customer cust = new Customer();
  cust.name = result.getString (1);
  cust.country = result.getString (2);
  cust.street = result.getString (3);
  cust.province = result.getString (4);
  cust.zip = result.getString (5);
  custList.add (cust);
   }
}
catch (SQLException e) {
  e.pringStackTrace ();
}


  

//Get Instance of Data  
Data data = DataFactory.getData(con);

// SQL for insert  
String sqlins = "insert into CUSTOMER (" 
+     "NAME,COUNTRY,STREET,CITY,PROVINCE,ZIP, "
+     "PHONE, INFO)" 
+    "values( ?, ?, ?, ?, ?, ?, ?, ?)";


















//execute the INSERT statement
data.update (sqlins, "custName", 
"custCountry", "custStreet", "custCity", 
"custProvince", "custZip", "custPhone", "custInfo");




// SQL for SELECT
String sqlSel = "select Name, Country, Street, " 
+ "Province,Zip from CUSTOMER where Customer = ?"; 







//execute the Select and get the list of customer
List<Customer> customerList = data.queryList (sqlSel, Customer.
class , "custCountry");












本文内容包括:

  • 详尽描述需要使用内联编程风格的代码的各个方面
  • 通过一个案例研究揭示内联风格的特性
  • 介绍内联风格提供的查询功能,包括 pureQuery 的默认映射支持和定制的查询映射支持
  • 介绍单个更新和批量更新支持,以及用于检索自动生成的值的 API
  • 介绍 pureQuery 的可插入式回调机制

开发内联方法

下面是编写内联方法风格应用程序所需的不同对象和 API:

  1. Data 接口

    com.ibm.pdq.runtime.Data 接口定义了方便的 API,用户可以用这些 API 执行数据库中的操作。当使用内联方法编程风格时,用户可以调用 Data 接口中定义的方法,将 SQL 语句作为方法调用中的一个参数。Data 接口提供执行查询、执行 SQL CALL 语句和返回输出参数的方法。它还提供了访问存储过程创建的动态结果集的方法,以及作为单独的操作或类型相同的批处理操作执行 SQL 数据操纵语言(DML)语句(例如更新、插入或删除)的方法。很多 Data 接口的查询方法是通用的,所以它们可以返回包括集合在内的不同类型的实例。

  2. DataFactory 类

    com.ibm.pdq.runtime.factory.DataFactory 类为构造 Data 接口的实现提供了途径。创建 Data 接口的实现的一种方法是将一个 Connection 对象传递给 DataFactory.getData() 方法。

  3. pureQuery bean

    pureQuery bean 可用于表示关系数据,例如数据库表、视图、结果集等。虽然 pureQuery API 方法可以处理定义为非结构化类型的参数和返回值,但是使用 pureQuery bean 可以为用户提供更好的从关系数据到 Java 对象的映射能力。 pureQuery 分析 bean 中声明的属性、方法和注释,以决定如何在 bean 的属性与 SQL 语句的输入/输出属性之间进行映射。有关 pureQuery bean 的约定和需求的更多信息,可以在 pureQuery 文档 中找到。

  4. 使用内联方法的 Java 应用程序

    在这种 Java 文件中,用户可以创建 Data 接口的实例,并调用不同的查询、更新或调用方法。

Silver Castle 示例

本节介绍一个示例,看看虚构的 Silver Castles 公司的数据访问开发小组如何使用 pureQuery。本文使用这里描述的背景信息展示针对每个 pureQuery 内联特性的例子和用例。

Silver Castle 示例的背景信息

Silver Castles 是一家正在发展中的公司,销售各种银制品。这家公司正在开发一个新的基于 Web 的店面,并且已经决定使用 pureQuery 环境作为开发应用程序持久层的工具。开发小组对 pureQuery 工具环境有了深刻的理解后,他们开始深入研究 pureQuery 内联编程风格的各个技术特性。

示例内联方法风格编程

Silver Castle 开发小组定义了 Customer 表,如下所示:


清单 1. 数据库中定义的 Customer 表

                
CREATE TABLE PDQ_SC.customer(
  Cid     INTEGER NOT NULL GENERATED ALWAYS AS IDENTITY (STARRT WITH 100, INCREMENT BY 1),
  Name       VARCHAR(128),
  Country    VARCHAR(128),
  Street     VARCHAR(128),
  City       VARCHAR(128),
  Province   VARCHAR(128),
  Zip        VARCHAR(128),
  Phone      VARCHAR(128),
  Info       VARCHAR(128),
  CONSTRAINT CID_PK primary key(Cid));

用于这个 Customer 表的 pureQuery bean 可以使用 Data Studio tool 生成。这个 Customer bean 定义如下:


清单 2. Customer 类
public class Customer { // Class variables @Id @GeneratedKey public int cid; public String name; public String country; public String street; public String city; public String province; public String zip; public String phone; public String info; public Customer(){} public Customer(String name, String country, String street, String city, String province, String zip, String phone, String info){ this.name = name; this.country = country; this.street = street; this.city = city; this.province = province; this.zip = zip; this.phone = phone; this.info = info; } }

现在,Silver Castles 开发小组尝试创建一个测试程序(清单 3),执行以下操作:

  1. 获得一个到数据库的连接
  2. 获得 Data 接口实现的一个实例
  3. 删除数据库中的所有行
  4. 使用 pureQuery bean 作为输入参数插入一行
  5. 查询数据库并在 pureQuery bean 的一个迭代器中检索行


清单 3. 使用内联方法风格操纵数据对象

package com.ibm.db2.demo; import java.sql.Connection; import java.sql.DriverManager; import java.util.Iterator; import java.util.List; import com.ibm.db2.pureQuery.Customer; import com.ibm.pdq.runtime.Data; import com.ibm.pdq.runtime.factory.DataFactory; public class InlineTest { public static void main(String args[]) { Connection con = null; String sql = null; String insertSql = null; try { // connection to the database con = DriverManager.getConnection (); // Get an instance to the implementation of a Data interface Data data = DataFactory.getData (con); //delete all rows from the table data.update ("delete from PDQ_SC.customer"); //Insert using a pureQuery Bean insertSql = "INSERT INTO PDQ_SC.customer (Name, Country, Street, City, " + "Province, Zip, Phone)" + "VALUES(:name,:country,:street,:city,:province,:zip,:phone)"; Customer addCustomer = new Customer("Customer2","US","BlackBerry Street", "San Jose","Santa Clara","82652","408-273-4856",null); int insertCount = data.update (insertSql,addCustomer ); System.out.println ("Rows Inserted " + insertCount ); sql = "select * from PDQ_SC.Customer where Country = ?"; //Query with Iterator using default handler Iterator<Customer> iterator = data.queryIterator (sql, Customer.class, "US"); con.close (); } catch (Exception e) { System.out.println ("Error encountered"); e.printStackTrace (); } } public static Connection getConnection () { Connection connection = null; try { Class.forName ("com.ibm.db2.jcc.DB2Driver").newInstance (); java.util.Properties info = new java.util.Properties (); info.put ("retrieveMessagesFromServerOnGetMessage", "true"); info.put ("user", "USER"); info.put ("password", "PASSWORD"); String url = "jdbc:db2://atom.blue.test.com:298/SAMPLE:deferPrepares=false;"; connection = DriverManager.getConnection (url, info); } catch (Exception e) { e.printStackTrace (); } return connection; } }

创建 Data 对象的一个实例

要创建 com.ibm.pdq.runtime. Data 的一个实例,需要一个到数据库的连接,其形式应该为 java.sql.Connection 对象或 javax.sql.DataSource 对象。建立好连接后,用户可以调用 com.ibm.pdq.runtime.factory.DataFactory 中的 getData() 方法创建 Data 接口的一个实例。除了执行 SQL 语句的方法以外,Data 接口还支持 close()、commit()、rollback() 和 setAutoCommit() JDBC 方法。

清单 3 中,Silver Castle 小组使用 getConnection() 方法创建一个数据库连接。该方法使用 Driver Manager API,通过传递一个数据库连接 URL String 来创建这个连接。然后,该连接被传递给 DataFactory.getData() 方法,以获得 Data 接口的实例。

输入参数选项

Silver Castle 开发人员可能希望使用 pureQuery 提供的参数占位符或主机变量风格。他们可以根据偏好选择内联方法的输入参数的数量或类型。传入方法调用的参数要与 SQL 中的参数匹配。pureQuery 根据 参数占位符规则 确定 SQL/XQUERY 中声明的参数与传递给内联方法的参数之间的映射。在最简单的形式中,两组参数之间有一对一的映射。pureQuery 还可以带各种类型的参数,例如 pureQuery Bean 或 java.util.Map。

查询数据库中的对象

内联方法风格提供了一些便利方法,并提供对将数据库结果映射到 map 和 pureQuery bean 的现成支持。Data 接口的重载方法 queryArray()、queryIterator() 和 queryList() 可用于以 Array、Iterator 或 List 对象的形式返回查询的结果集。

查询方法可以以原语类型、bean、集合等类型返回结果,包括:

  • java.sql.ResultSet
  • JDBC 直接支持基本包装器类型或简单的 Object 类型(不包括用户定义的类型)
  • java.util.Map 对象,其中列名成为 String 键,列值成为 Object 值
  • 组成 Array、Collection 或 Iterator 的 java.util.Map 对象
  • 单个的 pureQuery bean,用户可以将查询的结果存储在一个 pureQuery Bean 中(@Column 注释提供将 select 列表中的列与 pureQuery bean 各个属性相关联所需的信息;有关 pureQuery 注释的更多信息可以在 pureQuery 文档 中找到)。
  • 组成 Array、Collection 或 Iterator 的 pureQuery bean,返回 bean 的类作为参数传递

决定了目标数据类型后,用户需要考虑是否使用定制的处理程序将从数据源选择的信息转换成目标数据。pureQuery bean 的实例可以用 pureQuery 的从 SELECT 语句的 select 列表到目标 Bean 类的默认映射来创建,也可以使用一个用户定义的处理程序创建。

查询 Silver Castle Customer 表

Silver Castle 开发人员想通知澳大利亚(Australia)的所有客户即将举办一次盐和胡椒搅拌器的特价活动。用于打印所有宣传册的通用打印实用方法以一个 java.util.List 作为输入。开发人员查询 Customer 表,选择居住在 Australia 的所有客户,并将返回的行放在一个 List 中。他们可以使用 queryList() API,并以国家名作为输入参数。然后,返回的列表(在下面的例子中是 customerList)被传递到打印实用程序,以便为列表中适当的客户打印宣传册。


清单 4. 查询 Customer 表

                
      sql = "select * from  PDQ_SC.Customer where Country = ?";
      //Query with List using default handler
      List<Customer> customerList = data.queryList (sql, Customer.class, "Australia");

用户定义的定制结果集映射

RowHandlerResultHandler 接口使用户可以提供定制的用户定义映射。可以告诉 pureQuery 如何使用 RowHandler 或 ResultHandler 接口中的 handle() 方法将结果集中的列映射到不同的 Java 对象。Row Handlers 和 Result Handlers 为开发人员带来更大的灵活性和代码重用的潜力,因为他们可以使用 ResultSet 的 ResultSetMetaData 来处理 select 列表中的变化。这可以用于省略一些属性,或者指定不需要的属性。

在某些情况下,应用程序开发人员可能需要对整个查询结果进行某种形式的串行化。例如,惟一可以对查询结果做的处理是串行化到 JSON 或 XML 中,或者将数据发送到另一个(或相同的)数据源。用户可以使用 ResultHandler 来执行这样的定制操作。

映射结果集中的一行

RowHandler 接口用于将结果集的一行映射到一个对象。 RowHandler 接口中惟一的方法是 handle()。这是一个泛型方法,其输入为一个 ResultSet 对象,可能还有 <T> 类的一个实例,它或者产生一个新的 <T> 类的 Java 对象,或者更新给定的 <T> 实例。如果 ResultSet 对象为空,或者读完 ResultSet 对象的最后一行,则不调用 handle() 方法。当 handle() 方法被调用时,传递给该方法的 ResultSet 对象被定位到要处理的行上。当 pureQuery 自动执行这个动作时,handle() 方法不能对输入 ResultSet 对象调用 next() 方法。

将结果集映射到对象

ResultHandler 接口用于将整个结果集映射到一个对象。用户可以使用 ResultHandler 接口中的 handle() 方法将查询结果转换成另一个对象,例如 XML,后者可以传递给另一个以 XML 作为输入的应用程序。

更新数据库中的对象

Data 接口的 update() 方法可用于执行对数据库对象的单个更新,而 updateMany() 方法则可用于基于单个 SQL 语句的批量更新。受支持的方法有 INSERT、DELETE 和 UPDATE 操作。

单个更新

Data 接口中的 update() 方法可用于单个操作,它返回一个更新计数。清单 5 是在应用程序中调用重载方法 update() 的一个例子。


清单 5. 调用重载方法 update() 的应用程序

insertSql = "INSERT INTO PDQ_SC.customer (Name, Country, Street, City, " + "Province, Zip, Phone) VALUES (:name, :country, :street, " + ":city, :province,:zip,:phone)"; //Create an instance of Customer Bean with the values to be inserted Customer addCustomer = new Customer("Customer2","US","BlackBerry Street","San Jose", "Santa Clara","82652","408-273-4856", null); //Insert using a Bean int updateCount = data.update (insertSql, addCustomer);

批量更新

在 Data 接口中,updateMany() 方法表明一条语句要运行多次。updateMany() 方法允许传递一个集合的数据来进行遍历。

和在 JDBC 中一样,返回的 int 数组表明 SQL 语句的每次运行是成功还是失败(以及相关的更新计数)。这包括 JDBC 的更新计数、 Statement.EXECUTE_FAILED 和 SUCCESS_NO_INFO。如果出现失败,则抛出 com.ibm.pdq.runtime.exception.UpdateManyException 异常。这个运行时异常包含 JDBC 在 java.sql.BatchUpdateException 中报告的信息。

更新 Silver Castle Customer 表

每两个月,客户就可能与 Silver Castle 管理小组联系,以更新地址或电话号码。Silver Castle 开发人员可以使用单个更新 API 以新的信息更新这个表。清单 6 展示了这种 API 的使用。


清单 6. 用于更新表的单个更新 API

                
//Update the Street name for Customer
String updateSql = "UPDATE PDQ_SC.customer SET Street= 'Townsend' WHERE name= ?";
int updateCount = data.update (updateSql,"Customer3");
System.out.println ("Rows Updated " + updateCount);

Silver Castle 小组还有一个网站,新客户可以登录到这个网站上,让 Silver Castle 将目录邮递给他们。每个月都会运行一个实用程序来更新 Customer 数据库,以添加这些新客户。为此,开发人员可以创建一个任务,批量处理所有请求并使用一个内联方法将它们插入到数据库中。在这种情况下,他们可以使用批量更新 API,以高效地更新数据库。清单 7 展示了批量更新 API。


清单 7. 批量更新 API

//Example Using UpdateMany Customer addFirstCustomer = new Customer("Customer3","Costa Rica","Main Street","Arenal", "La Fortuna","90291","506-375-0273",null); Customer addSecondCustomer = new Customer("Customer4","Puerto Rico","Church Street", "Puerto Nuevo","San Juan","38364","293-484-8244",null); ArrayList<Customer> customerList = new ArrayList<Customer>(); customerList.add (addFirstCustomer); customerList.add (addSecondCustomer); insertSql = "INSERT INTO PDQ_SC.customer (Name, Country, Street, City, " + "Province, Zip, Phone) VALUES (:name, :country, :street, " + ":city, :province,:zip,:phone)"; int[] updateCount = data.updateMany( sql, customerList); if (updateCount != null) System.out.println ("Rows Inserted:” + updateCount.length);

检索自动生成的值

update() 方法的重载使用户可以有选择地请求与自动生成的列相关的信息。Silver Castle 开发人员可以用很多方法根据提供给更新方法的输入获取数据库生成的值。下面展示了一个例子,在这个例子中,Silver Castle 开发人员使用不同的方法编写应用程序,以获得插入后数据库生成的值。

使用 pureQuery bean 自动生成的值

在这个例子中,插入的输入是一个 pureQuery bean。Customer 对象是在一个 @GeneratedKey 注释中定义的,列 CID 被定义为标识列,它总是生成一个整数。在 update() 方法调用返回控制之前,CID 列中的值被传递到 CID 属性中。自动生成的值是在 customer 对象的 CID 属性中设置的。


清单 8. 获得 Customer bean 的 CID 属性中自动生成的值

insertSql = "INSERT INTO PDQ_SC.customer (Name, Country, Street, City, " + "Province, Zip, Phone) VALUES (:name, :country, :street, " + ":city, :province,:zip,:phone)"; //Create an instance of Customer Bean with the values to be inserted Customer customer = new Customer("Customer2","US","BlackBerry Street","San Jose", "Santa Clara","82652","408-273-4856", null); //Insert using a Bean int updateCount = data.update (insertSql, customer); System.out.println ("Generated Key Value:" + customer.cid);

不使用 pureQuery Bean 自动生成的值

The Silver Castle developer can pass values without a pureQuery bean and still retrieve auto-generated values by using the following version of the update() method:

   <T> T update(java.lang.String sql, Class<T> returnClass, 
 String[] columnNames, Object... parameters) 

取决于指定的返回类型,该方法返回一个或多个生成的值。返回类型为 Class<T> 的值必须是以下两者之一:

  • Object[].class
  • 一个可直接从 JDBC 指定的简单的类,例如 Integer.class 或 String.class

当返回类型为一个简单的可直接指定的 JDBC 类时,会返回给定类型的一个生成的值。而更新计数不会返回。下面展示了 Silver Castle 开发人员如何将自动生成的值放入到一个简单的类(例如 int.class)中。


清单 9. 将自动生成的值放入一个简单的类中

Object[] customerArray = new Object[7]; customerArray[0] = "CustomerForGenKey"; customerArray[1] = "US"; customerArray[2] = "Bixby Street"; customerArray[3] = "San Martin"; customerArray[4] = "Santa Clara"; customerArray[5] = "62826"; customerArray[6] = "408-272-6565"; insertSql = "INSERT INTO PDQ_SC.customer (Name, Country, Street," + "City, Province, Zip, Phone) VALUES(?,?,?,?,?,?,?)"; String[] colunmName = new String[] { "cid" }; int i = data.update (insertSql, int.class, colunmName, customerArray); System.out.println ("AutoGenerated Keys as Int " + i + "/n");

当返回类型为 Object[].class 时,数组的前 n 个元素是从 columnName 参数中的列生成的 n 个值。数组中的最后一个元素是更新计数。下面展示了 Silver Castle 开发人员如何使用一个 Object[] 获得生成的键值。自动生成的值在 Object[0] 中返回,更新计数在 Object[1] 中返回,如清单 10 所示。


清单 10. 将自动生成的值放在一个 Object[ ] 中

Object[] customerArray = new Object[7]; customerArray[0] = "CustomerForGenKey"; customerArray[1] = "US"; customerArray[2] = "Barnaby Street"; customerArray[3] = "Gilroy"; customerArray[4] = "Santa Clara"; customerArray[5] = "62823"; customerArray[6] = "408-273-6568"; insertSql = "INSERT INTO PDQ_SC.customer (Name, Country, Street," + " City, Province, Zip, Phone) VALUES(?,?,?,?,?,?,?)"; String[] colunmName = new String[] { "cid" }; Object[] output = data.update (insertSql, Object[].class, colunmName, customerArray);

使用 Hook 接口的可插入式回调机制

com.ibm.pdq.runtime.Hook 接口可用于创建在内联方法之前或之后运行的方法。假设 Silver Castle 开发人员知道他们的产品不能发送给某些国家的客户。对于这里的例子,我们可以假设有发货限制的这些国家是 Costa Rica 和 Australia。Hook 接口使开发人员只需定义一次这样的检查,而不必在每次更新 Customer 表时在多个位置添加代码来检查客户的国家。

当 Data 实例创建时,必须将 Hook 注册到 Data 实例。如果内联方法使用的 Data 对象注册了 Hook,那么当应用程序调用 Data 接口的一个方法时,会出现以下步骤:

  • 在 Data 接口的方法做任何事情之前,先调用注册的 Hook 的 pre() 方法。
  • 被调用方法执行它的工作。
  • 当被调用方法完成所有工作之后,调用注册的 Hook 的 post () 方法。

定义内联方法的 Data 接口包含很多 Connection 对象上的 JDBC 方法,例如 close ()、commit ()、rollback ()、setAutoCommit () 和 getAutoCommit ()。注册的 Hook 的 pre () 和 post () 方法不会包装这些方法。

pre () 和 post () 方法需要使用以下参数来定义:

  • String methodName: pureQuery 将方法的签名传递给 pre () 方法
  • Data dataInstance: pureQuery 传递实现 Data 接口的对象
  • SqlStatementType statementType: pureQuery 传递 SQL 语句的类型(例如 SELECT、UPDATE、INSERT)
  • Object... parameters: pureQuery 传递传给内联方法的参数
  • Object returnValue: 将调用值返回给内联方法

下面的例子演示了 Hook 接口的使用。Silver Castle 应用程序开发人员在应用程序的一个 HookCall 类中定义 pre() 和 post() 方法。pre() 方法检查输入参数,即客户的国家,看它是否有效,并防止将无效的行插入到数据库中。方法调用的输出可以使用 post() 方法检查。


清单 11. Hook 接口的使用

public static class HookCall implements Hook { public void pre (String methodName, Data objectInstance, SqlStatementType statementType, Object... parameters) { String country = ((Customer)parameters[0]).country; If (!statementType.equalsIgnoreCase ("update") || !statementType.equalsIgnoreCase("insert")) return; if (!(country.equals ("Australia") || country.equals ("Costa Rica")) ) throw new DataRuntimeException ("This Country " + country + " is not part of our customer base"); } public void post (String methodName, Data objectInstance, Object retValue, SqlStatementType statementType, Object... parameters) { //Do nothing } }

应用程序可以像下面清单 12 中那样注册 Hook。当 pre() 方法被调用时,它会验证用于 Customer bean 的 country 属性的输入值。


清单 12. 注册 hook

Connection con = DriverManager.getConnection(...); HookCall hookCall = new HookCall (); Data db = DataFactory.getData(con, hookCall); sql = "INSERT INTO PDQ_SC.customer (Name, Country, Street, City, Province, Zip, Phone)" + "VALUES(:name,:country,:street,:city,:province,:zip,:phone)"; Customer addCustomer2 = new Customer ("Customer2", "Costa Rica", "BlackBerry Street", "San Jose", "Santa Clara", "82652","408-273-4856", null); int insertCount = db.update (sql, addCustomer2);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值