【问题标题】:Intercept all Database call in Java拦截 Java 中的所有数据库调用
【发布时间】:2019-11-19 06:18:49
【问题描述】:
我想在我的数据库中拦截插入查询并想改变它的插入值
例如,如果用户在数据库中插入一个值 name = amitrai,我想将值从 amitrai 更改为 &^&WQWSAKJSJA 然后存储。
总的来说,我希望拦截在 JDBC 连接中执行查询。
【问题讨论】:
-
-
-
-
-
如果你想拦截JDBC的所有DB操作,可以试试p6spy自定义这个功能。
标签:
java
database
connection
【解决方案1】:
在数据库中使用触发器。
在我看来,实现这一点的最佳方法是直接在数据库中使用触发器。这正是他们的目的。他们将保证每个尝试插入/更新/合并user.name 值的客户端都将通过此逻辑。其他一些不知道您的客户端拦截的开发人员不会有聪明的 Perl 脚本。
您在 cmets 中提到的所有数据库产品都支持触发器。当然,缺点是您必须在尽可能多的方言中重复您的编码/散列逻辑。
在客户端执行,使用 JDBC 代理
如果您出于某种原因必须在客户端中实现此逻辑,那么 JDBC 是一个很好的层来执行此操作。当然,您可以在更高的层(例如在 Hibernate 中)实现这一点,但话又说回来,您将冒着绕过这种编码的一些 Java 客户端逻辑的风险。
在 JDBC 层,你至少可以“合理地”保证每个 Java 客户端都会执行这个逻辑。
解决这个问题的一种方法是使用类似 jOOQ 的各种连接代理,包括 MockConnection,它允许使用单一方法(有一些限制)拦截大多数 JDBC 调用,ParsingConnection,它允许解析传递给 JDBC 的 SQL 字符串,然后进行转换。如果您想生成新的 SQL 逻辑,您将使用 VisitListener 将 SQL 转换为其他内容。在你的情况下,你只是替换一个绑定变量,所以你可以更容易地做到这一点。
免责声明:我在 jOOQ 背后的公司工作。可能还有其他支持类似行为的解决方案,其本质是代理(其他人为此提到了 p6spy)和解析,以确保您只替换您实际想要替换的值。与 jOOQ 一样,此类解决方案不应强制您在客户端逻辑中实际使用 jOOQ,而是拦截您在 JDBC 层上执行的任何类型的 SQL。
注意事项
虽然以上在某种程度上是可能的,但它可能很复杂,并且可能仍然存在您忽略的东西(例如MERGE 语句或INSERT .. ON DUPLICATE KEY UPDATE 语句等)。触发器是解决此问题的最佳方法。
【解决方案2】:
按照@Mureinik 的建议使用Trigger on insert
例如对于表yourtable插入:
CREATE OR REPLACE TRIGGER NameChange
BEFORE INSERT
ON yourtable
FOR EACH ROW
BEGIN
IF :new.name = 'amitrai'
THEN
:new.name := '&^&WQWSAKJSJA';
END IF;
END;