`
marb
  • 浏览: 422389 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用 DB2 触发器、Java UDF 和 JavaMail API 实施业务逻辑

阅读更多

 

通过使用示例应用程序,Kulvir Singh Bhogal 向您展示了在客户接近他们的信用限额时,如何自动地触发一封定制的e-mail。

简介

牛顿第三定律表明对于每一个作用力,都存在一个大小相等、方向相反的反作用力。但愿您能记住这一点。不过别担心,我不是要给您上一堂物理课。在本文中,我将指导您理解数据库应用程序中因果关系的实现方式,该数据库应用程序将 DB2 触发器、Java 用户定义函数(udf)以及 JavaMail API 这三个概念综合在一起。

下面高度概括了本文的内容:

  1. DB2 数据库中的记录被更改。
  2. 如果这个更改使数据记录满足某些基于布尔逻辑的条件,数据库触发器将调用一个 Java UDF。
  3. Java UDF 使用 JavaMail API 向指定的收件人发送一封 e-mail。

一个现实中的例子

在开始体验之前,让我们通过一个现实中的例子来看看它的实际应用。假设我们是一家信用卡公司。客户要求当他们接近信用卡限额时,公司能通过 e-mail 通知他们。

图 1 描绘了我们希望能完成的工作。为了更加明确发送 e-mail 之前需要符合的条件,让我们假定在消息发出之前,用户必须在他们信用限额的 15% 之中。


图 1. 从数据库更新到 e-mail 确认的流程
从数据库更新到 e-mail 确认的流程




创建数据库

首先,我们需要使用一个数据库。当然,一个真正的信用卡系统的数据库很可能比我们给出的这个简单模型要复杂得多。然而,出于学习目的,我们的例子将尽量简单。

  1. 首先,用下面的 SQL 语句创建数据库:
    create db cardDB

  2. 当然,我们必须连接数据库才能进行有用的操作:
    connect to cardDB

  3. 接下来,我们需要一个表来存储所有的客户数据。 表 1 给出了表的列。

    表 1 客户概要信息

    列名 所存储的内容 数据库中的显示
    lastName varchar(30)
    firstName varchar(30)
    emailAddress E-mail 地址 varchar(30)
    currentBalance 信用卡余额 decimal(7,2)
    creditLimit 信用卡限额 decimal(7,2)

    下面的 SQL 语句将创建以上描述的表:

    create table cardHolderTable
    (lastName varchar(30) not null,
    firstName varchar(30) not null,
    emailaddress varchar(30) not null,
    currentBalance decimal(7,2) not null,
    creditLimit decimal (7,2) not null)

    然后,如果我们用语句 DESCRIBE TABLE 来显示表结构,将看到表已经被正确定义 (如 图 2 所示)。


    图 2 Cardholder 表结构显示结果
    Cardholder 表结构显示结果
  4. 现在我们需要向表填入一些虚拟的数据值。 表 2 中是一些尝试插入数据库中的样本数据。


表 2. Cardholder 表的样本数据

lastName firstName emailAddress currentBalance creditLimit
Bhogal Kulvir kulvir@somewhere.com $3753.00 $5000.00
Peters Nancy nancy@someplace.com $2722.43 $3500
Clancy Jerry clancyj@somedomain.net $650.23 $1500.00
Biggs Gloria gloria@otherdomain.org $718.78 $2500.00

重要: 当我们首先将样本数据填入表中时,我们需要使客户的当前余额低于他们的信用限额的 85%。因为在创建触发器之前,即使有客户的当前余额超出了 85%,也不会受到系统的详细检查。

使用下面的 SQL 语句插入 表 2 中显示的第一行数据:

insert into cardHolderTable values
('Bhogal','Kulvir','kulvir@somewhere.com',3753.00,5000.00)

 

请执行类似的语句将 表2 中其余的虚拟数据记录插入您的样本数据库。

 




先有鸡还是先有蛋?

回到我们的“因果”主题,我们需要同时定义“原因”和“结果”。如果您是第一遍阅读和理解本文,请继续下去阅读 原因 小节。但是,如果您是第二遍阅读并且正在照此做实验,请先跳到 结果 小节。您应该在创建原因(触发器)之前先创建结果(UDF),这样一来,当您的触发器预备调用 UDF 时,它就已经在那里了。

 




创建触发器(原因)

现在让我们来定义“原因”。我们通过创建 DB2 触发器来完成。

create trigger spawnEmailTrigger
      after update of currentBalance on cardHolderTable
        referencing old as oldrow new as newrow
        for each row
      mode db2sql
when
(newrow.currentBalance>(oldrow.creditLimit*.85))
(values(mailer(oldrow.emailAddress,oldrow.lastName,oldRow.firstName,newRow.
currentBalance,oldRow.creditLimit)))

 

让我们来看一看上面创建触发器的语句。如果您不熟悉触发器,可以这么认为:当在表中进行 delete、insert 或者 update 操作时,触发器是一组作为直接结果而被激活的操作。不过,这可不是另一个牛顿的定义。这就是我们正在谈论的 DB2!

对于数据库程序设计人员来说,触发器的可用功能是十分强大的。在本文中,我们仅仅展示触发器众多功能中的一种。

实际上语法是相当简单的。在我们这个例子中,触发器是由一个 update 操作激活的。对于客户增加信用卡消费额的事务,我们计划在系统中通过更新 currentBalance 列的方式来模拟。(我们的虚拟信用卡跟踪系统是十分粗略的。如果您的信用卡公司使用这样一个骨架系统,我会为您很担忧。然而,作为一个例子,它能运作就很好了。)

让我们回到触发器的详细说明:

  • 我们将触发器命名为 spawnEmailTrigger
  • 关键字 after 表明我们的 e-mail 是在操纵 DB2 表 之后 生成的(与我们更新它 之前 相反)。
  • update of currentBalance on cardHolderTable 子句缩小了触发器关注的数据库操作的范围。总之,如果对 cardHolderTable 表中 currentBalance 列执行更新操作,我们就要激活触发器。
  • 必须加上子句 mode db2sql
  • 接下来,我们用一些布尔逻辑来限定触发器的触发条件。通过子句 when (newrow.currentBalance>(oldrow.creditLimit*.85)) ,我们指明了只有当 currentBalance 的值被更新而且超出了客户信用限额的 85% 时,触发器才被触发。执行更新操作时,特别要注意我们如何查阅操作执行前后数据库中的值。这个能力允许我们进行计算,并判断事实上触发器是否被触发了。
  • 因此,当执行一个更新操作时,如果该操作将客户抛入了信用卡限额的 15% 以内的这个“红色区域”,我们就用下面的子句调用 UDF 来生成一封 e-mail:
    (values(mailer(oldrow.emailAddress,oldrow.lastName,oldRow.firstName,oldRow.
    currentBalance,oldRow.creditLimit)))

我们将在下一小节中讨论 UDF。这里要注意的一点就是我们将参数传递给 UDF 函数(名为“mailer”),由该函数来构造我们定制的 e-mail。

 




生成 e-mail (结果)

在触发器中,如果满足指定条件,就调用 Java UDF。 但是,为什么要引用 UDF 呢?下面将花些时间来回答这个问题。然而,我们首先介绍 UDF。

安装 JavaMail jar 文件

我们将要执行的 e-mailing 任务是以 JavaMail API 为基础的。当然,您不一定就有使用这个程序接口的文件。根据使用的 Java 版本,所需的 jar 文件也许您已经处理好了。这里我假设您还没有。实际上,如果您没有所需的 jar 文件,也不需要额外花钱。JavaMail API 是免费的并且可以 下载

这里假设您已十分熟悉 JavaMail API。如果不熟悉的话,请参阅 教程

假设您已经在硬盘驱动器上安装了两个与 JavaMail API 相关联的叫做 mail.jar 和 activation.jar 的 jar 文件,需要让 DB2 知道这两个文件在哪里。所以我们将 jar 安装到数据库服务器上的“Mail” 和“Activation”名称下。

可以使用以下语句来完成这件事:

call sqlj.install_jar('file:///c:/temp/mail.jar','MAIL')

 

call sqlj.install_jar('file:///c:/temp/activation.jar','ACTIVATION')

 

在上面的语句中,我们假设这些 jar 文件在 temp 目录中。您需要调整上面的语句使之指向 jar 文件的正确位置。

使用 Java UDF

现在,让我们转向 Java UDF 代码。您或许希望 下载 代码并花时间研究它。随代码一起提供的文档将指导您学会从 JavaMail API 的使用到创建和发送定制的 e-mail 信息。

凡事都有运行法则,这里关注的 mailer 方法是一个公共的静态方法,它返回一个 String。您的 UDF 方法必须有一个返回类型。我们使用传递给方法的参数来定制 e-mail,并通知目标接受者的信用卡余额正处于“红色”状态。

在可以使用 Java UDF 之前,必须执行一些准备步骤。

  1. 编译好 JavaUDF.java 文件后,将结果类文件放到将使用该函数的 DB2 实例的 sqllib/function 目录下。如果您使用的是 Windows NT,并且安装选项是默认的,那么文件将被放入下面的位置:
    C:\\Program Files\\SQLLIB\\function

  2. 接下来,必须注册新创建的 UDF,这样 DB2 才能知道它的存在。
    create function mailer(recipientEmail varchar(30),
    lastName varchar(30),  firstName varchar(30),
    currentBalance decimal(7,2),
    creditLimit decimal(7,2))
       returns varchar(70)
       fenced
       variant
       no sql
       external action
       language java
       parameter style java
       external name 'JavaUDF!mailer'

  • 让我们花点时间来分析这条注册语句。在 CREATE FUNCTION 语句中,我们指明 DB2 中的函数名称。在这个例子中,我们使用 “mailer”。
  • 我们还必须指明函数预期得到的 SQL 参数。值得注意的是,我们在这里使用 SQL 参数,然而在实际的 Java UDF 中,是使用 Java 变量类型。如果将 Java 代码与 UDF 注册语句相对照,您将发现,对于 varchar来说,对应的 Java 变量类型是一个 String。类似地,对于 SQL 类型的 decimal (7,2),Java 中是使用 java.math.BigDecimal 类型。这种 SQL 与 Java 类型一对一的匹配关系,对于事情顺利进行是很必要的。下面是 mailer 方法的签名。
    public static String mailer(String input, String lastName,
    String firstName, BigDecimal currentBalance,
    BigDecimal creditLimit) 

  • 回到我们的注册语句,我们指明函数将返回一个 varchar(70)。它用于存储 UDF 的进度描述。
  • 我们使用 fenced 函数,因为它比 non-fenced 函数更加安全。这里不用太深究这个问题,fenced 函数独立运行于数据库管理程序的内部资源。因而即使发生错误,它也不会对管理程序构成太大威胁。
  • 往下走,我们声明函数包含 no sql,意思是它不包含 SQL 语句。
  • 子句 external action 表明函数执行一个影响数据库外部的操作。
  • 通过子句 “language java parameter style java”,通知数据库 UDF 中使用的语言和参数样式为 Java。
  • 最后,使用了子句 “external name 'JavaUDF!mailer'” ,通知数据库应查找的 Java 类文件为“JavaUDF”,以及正在注册的特定函数就是“mailer”方法。

局限性: 值得注意的事,我们的设置有一个固有的缺点。那就是我们的外部发送邮件操作无法获知没有成功的事务(例如,通过 Web 表单中止的余额更新操作)。因此,即使数据库事务没有完成,也可能生成一封 e-mail。

 




测试

如果您按照上述步骤至今没有出现任何问题,那您将很快就可以看到劳动成果了。

测试方法为:发出一条 update 语句,使得某个特定的信用卡客户处于信用限额的 15% 以内,触发器将通过创建的 Java UDF 发送一封 e-mail。

如果您使用本文开始建议的特定模拟数据,可以用下面的语句来测试:

 update cardHolderTable
set currentBalance = 4600.00
where lastName = 'Bhogal' and firstName = 'Kulvir'

 

通过发出这条 update 语句,我们已经有效地将姓为 Bhogal 名为 Kulvir 的客户置于信用限额的 15% 以内这个“红色区域”。

相应地,触发器将对这个 update 作出反应,因为它满足了调用 Java UDF 的条件。

通过将进入“红色区域”客户的 e-mail 地址改为您的 e-mail 地址,可以检查设置是否能够正常工作。有一个需要注意的陷阱就是,您的 SMTP 服务器也许不支持 e-mail 转发。这一点在 ISP 中是很普遍的,因为这样可以确保他们的 SMTP 服务器阻止垃圾邮件。因此,在 Java UDF 中要将“发送端”地址指定为 SMTP 服务器可识别的地址。如果您在邮箱中自动地接收到了一封 e-mail,我们的实验就通过了。

 






结束语

DB2 触发器对于数据库程序员来说是一项很强大的功能。在工具箱中拥有了这些触发器,就可以在数据库更新时立即执行操作。触发器允许您以一种将所执行的操作与应 用程序分离的方式来封装和定义业务逻辑。这样做实质上是将某些操作放到后台执行。这种做法在那些有几个不同程序(很可能由不同语言编写的)同时来更新数据 库的环境中特别有用。这些程序可能都有相同的基本功能(例如,发送一封 e-mail)。通过使用在本文中完成的 trigger/UDF 的联合,您可以毫不费力地用不同语言对同一功能进行重复编码。

此外,通过使用 Java UDF,您可以用触发器使 DB2 和 Java 协同工作。在本文中,当客户将要到达他的信用限额时,使用 DB2 触发器调用 Java 用户定义函数。这个 JavaUDF 又通过 JavaMail API 来生成一封定制的 e-mail。

分享到:
评论
1 楼 xpipi 2008-11-20  

牛X
我这报错了
DB2 SQL error: SQLCODE: -723, SQLSTATE: 09000, SQLERRMC: ADMINISTRATOR.XJ;-4306;42724;ADMINISTRATOR.XJUFIDASETSMUSER|SQL0811201

XJUFIDASETSMUSER是我创建的UDF名称.

请问知道是什么原因么???

先谢过~```

相关推荐

    java UDF开发分享

    hadoop 处理数据时子带函数可能不满足平常的分析需求,需要自己开发自定义的函数支持业务需求

    hive-udf(两地址间距离计算+省市区位置解析(Java代码))

    为了满足特定的业务需求,Hive提供了用户定义函数(UDF)的功能,允许用户自定义处理数据的逻辑。在这个“hive-udf”项目中,我们主要探讨的是如何利用Java编写UDF来实现两个地址间的距离计算以及省市区位置的解析。...

    DB2英文版说明文档

    为了更好地理解DB2 UDB for iSeries的工作原理,书中提供了一个示例模式,用于演示如何使用存储过程、触发器和UDF。这个示例模式可以帮助读者了解这些组件是如何被集成到数据库设计中的。 ### Order Entry应用 ###...

    DB2 Stored Procedures, Triggers & Functions

    在IBM DB2数据库系统中,存储过程、触发器和...总之,DB2的存储过程、触发器和用户定义函数是数据库开发的关键组成部分,掌握了这些技能,开发者就能更好地利用DB2的潜力,实现复杂业务逻辑,提升应用的效率和可靠性。

    触发器和用户自定义函数

    ### 触发器和用户自定义函数:深入解析 #### 触发器(Trigger) 触发器是数据库系统中一种特殊类型的存储过程,它被设计来响应特定的数据库操作,如`INSERT`、`UPDATE`、`DELETE`。当这些操作在特定的表上执行时,...

    大数据 java hive udf函数的示例代码(手机号码脱敏)

    在本文中,我们将通过实例代码,详细介绍如何开发和使用 Java Hive UDF 函数。 UDF 函数的实现 首先,我们需要在 Maven 项目中添加依赖项,包括 Hadoop 和 Hive。 Maven 项目的 POM 文件如下所示: ```xml ...

    DB2 V9 课程.rar

    - 数据库对象包括表、视图、索引、存储过程、触发器和用户定义函数(UDF)等,是DB2中实现业务逻辑的重要元素。 - 表是数据的主要容器,视图提供了一种虚拟数据表的抽象。 - 索引用于提高查询性能,而存储过程和...

    DB2培训源代码

    在这个"DB2培训源代码"中,我们可以深入学习和实践DB2的一些关键特性,包括JDBC连接、SQLJ的嵌入式使用、存储过程、用户定义函数(UDF)、触发器、大对象操作以及序列的运用。 1. **JDBC连接**:Java Database ...

    db2数据库jar包

    DB2数据库是一个由IBM开发的关系型数据库管理系统,广泛应用于企业级的...总的来说,DB2数据库JAR包是Java开发者与DB2数据库进行交互的基础,理解和正确使用这些驱动文件对于构建高效、可靠的Java数据库应用至关重要。

    udf使用心得,吐血推荐

    - 自定义逻辑:UDF允许根据业务需求定制特定功能,避免硬编码在查询中,提高代码可读性和复用性。 - 性能优化:在某些情况下,UDF的执行效率高于存储过程,尤其是在处理单行数据时。 - 数据库层扩展:通过UDF,...

    解密SQL触发器、存储过程、函数

    SQL触发器通常用于实施业务逻辑,特别是那些需要在数据更改时立即执行的操作。存储过程则更倾向于封装重复性的任务,提高代码复用,或者处理复杂的事务逻辑。函数通常用于计算和数据转换,它们可以嵌入到查询中,...

    java RSA加解密的udf函数

    这两个方法可能会使用`Cipher`类,它在Java中提供了各种加密和解密算法的实现。 KeyRSA.java文件可能包含以下关键部分: 1. **密钥对生成**:使用`KeyPairGenerator`类,通过`getInstance("RSA")`获取RSA实例,并...

    Oracle P6 集成开发API

    学习和使用Oracle P6 API需要对Java编程有基本了解,同时也需要熟悉项目管理和Oracle P6的内部工作原理。开发者通常会参考提供的API文档(如docs文件中的内容),通过实例代码和测试来熟悉API的各种功能和用法。实践...

    UDF 2.5文件系统

    - UDF 2.5采用了基于逻辑卷管理的方式组织数据,这种逻辑卷可以跨越多个物理磁盘。 - 这种设计允许文件系统更加灵活地管理和利用存储空间。 **2. 安全机制** - UDF 2.5支持多种错误检测和纠正机制,如循环冗余...

    UDF.rar_udf中x方向动量编写_动量udf

    总的来说,这个UDF实例涉及到流体动力学中的基本物理原理、编程技巧以及Fluent软件的API使用,对于理解和扩展流体模拟能力具有重要意义。通过深入学习和实践,不仅可以掌握x方向动量的计算,还可以举一反三,应用于...

    pig udf 函数(urldecode row_number tomap)

    在 CDH4.1.2 版本中使用这些 UDF 时,你需要确保与该版本兼容的 Hadoop 和 Pig 相关库。如果要在其他版本的 CDH 中使用,需要替换工程文件中的两个 jar 包,以匹配目标环境的版本。通常,这些 jar 包包含了 Pig 和 ...

    ANSYS Fluent UDF Manual.rar_ANSYS FLUENT UDF_UDF manual_UDF-flu

    《ANSYS Fluent UDF Manual》是ANSYS Fluent用户定义函数(UDF)的官方手册,为用户提供了详细的UDF编程指南和技术支持。UDF是ANSYS Fluent软件中的一个重要功能,它允许用户根据特定需求定制流体动力学模型,扩展软件...

    Fluent_UDF_中文教程.zip_fluent_fluent udf_fluent udf 教程_fluent udf手册

    《Fluent UDF中文教程》是一份针对流体动力学模拟软件Fluent用户定义函数(UDF)的详细教学资料,旨在帮助初学者理解和掌握UDF的编写与应用。UDF是用户通过C语言来扩展Fluent功能的一种方式,允许用户自定义物理模型、...

    DB2 应用设计和SQL手册

    3. **存储过程和触发器**:DB2支持创建存储过程和触发器,用于执行复杂的业务逻辑和数据验证。 **四、SQL语言** 1. **基本SQL语句**:包括SELECT、INSERT、UPDATE和DELETE,用于查询、插入、修改和删除数据。 2. **...

    修改udf,vc++udf 安装包。

    接下来,我们将深入探讨UDF、VC++以及如何使用和调试它们。 UDF(User-Defined Function)是编程中的一个关键概念,它允许程序员扩展内置函数的功能,以满足特定的需求。在数据库管理系统中,UDF可以作为存储过程的...

Global site tag (gtag.js) - Google Analytics