使用 Hibernate 或 Spring 打印 DBMS_OUTPUT.put_line

2024-06-21

我想知道 Hibernate 或 Spring 或任何第 3 方库是否提供将 DBMS_OUTPUT.put_line 消息直接打印到 system.out 或日志文件的能力。

目的是在控制台中同时显示 PLSQL 日志消息和 java 日志消息。

我知道有一个类似的问题,其答案是将 PLSQL 过程转变为返回日志消息的函数,但这不适合我的情况。事实上,我的日志消息太复杂,不可能在函数中返回它。

我读过这个https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:45027262935845 https://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:45027262935845并得到了灵感,但我想知道是否有一个开箱即用的解决方案来避免鲸鱼繁殖。


由于没有人回答这个问题,我想没有任何现成的解决方案。所以我自己构建了它,并在这里发布了可能感兴趣的代码。

欢迎任何想要改进此解决方案的人!只是不要羞于分享你的!

基于Spring AOP的解决方案。一个注释@DbmsOutput创建用于在相关方法上添加 DBMS_OUTPUT 感知能力。

环境:Maven + Spring 4.2.6 + Hibernate 5.1.0

第1步:添加Spring AOP依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>4.2.6.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.8.4</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.8.4</version>
</dependency>

第2步:创建@DbmsOutput

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface DbmsOutput {
}

步骤 3:为所有声明的方法创建拦截器@DbmsOutput.

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.SQLException;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.jdbc.Work;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

@Aspect
@Order(Ordered.LOWEST_PRECEDENCE)
public class DbmsOutputAspect {

    private static final Logger LOGGER = Logger.getLogger(DbmsOutputAspect.class);

    @Autowired
    protected SessionFactory sessionFactory;
    /**
     * make Dbms output aware enable/disable configurable in spring bean declaration
     */
    private boolean enable = true;
    private int size = 1000000;

    public boolean isEnable() {
        return enable;
    }

    public void setEnable(final boolean enable) {
        this.enable = enable;
    }

    public int getSize() {
        return size;
    }

    public void setSize(final int size) {
        this.size = size;
    }

    @Pointcut("execution(@DbmsOutput * *(..))")
    public void DbmsOutputInterceptMethod() {
    }

    @Around("DbmsOutputInterceptMethod()")
    public Object around(final ProceedingJoinPoint point)
            throws Throwable {

        if (isEnable()) {
            LOGGER.debug("before DBMS_OUTPUT point cut");
            Query queryEnable = sessionFactory.getCurrentSession().createSQLQuery("call dbms_output.enable(:size)");
            queryEnable.setParameter("size", getSize());
            queryEnable.executeUpdate();
        }
        try {
            return point.proceed(point.getArgs());
        } finally {
            if (isEnable()) {
                sessionFactory.getCurrentSession().doWork(new Work() {

                    @Override
                    public void execute(final Connection connection)
                            throws SQLException {

                        CallableStatement show_stmt = connection.prepareCall(
                                "declare " +
                                        " l_line varchar2(255); " +
                                        " l_done number; " +
                                        " l_buffer long; " +
                                        "begin " +
                                        " loop " +
                                        " exit when length(l_buffer)+255 > :maxbytes OR l_done = 1; " +
                                        " dbms_output.get_line( l_line, l_done ); " +
                                        " l_buffer := l_buffer || l_line || chr(10); " +
                                        " end loop; " +
                                        " :done := l_done; " +
                                        " :buffer := l_buffer; " +
                                        "end;");
                        int done = 0;

                        show_stmt.registerOutParameter(2, java.sql.Types.INTEGER);
                        show_stmt.registerOutParameter(3, java.sql.Types.VARCHAR);

                        for (;;) {
                            show_stmt.setInt(1, 32000);
                            show_stmt.executeUpdate();
                            LOGGER.info(show_stmt.getString(3));
                            done = show_stmt.getInt(2);
                            if (done == 1) {
                                break;
                            }
                        }
                    }
                });
                Query queryDisable = sessionFactory.getCurrentSession().createSQLQuery("call dbms_output.disable()");
                queryDisable.executeUpdate();
                LOGGER.debug("after DBMS_OUTPUT point cut");
            }
        }
    }
}

步骤 4:配置DbmsOutputAspect and TransactionManager在春天

<!-- aspectj -->
<aop:aspectj-autoproxy proxy-target-class="true" />
<bean class="DbmsOutputAspect" />

<!-- transaction -->
<tx:annotation-driven transaction-manager="transactionManager" order="0" />
<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory">
        <ref bean="sessionFactory" />
    </property>
</bean>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Hibernate 或 Spring 打印 DBMS_OUTPUT.put_line 的相关文章

随机推荐

  • 如何在 golang 中创建 .der 文件,与 openssl 相同

    openssl rsa in prevate pem outform DER pubout out public der 你可能会考虑像这样的图书馆google trillian https github com google trilli
  • .NET 中的跟踪中的“开关”和“过滤器”有什么区别?

    NET 中的跟踪中的 开关 和 过滤器 有什么区别 他们似乎以相似的方式工作
  • 底图上的子图

    我有一张英国地图和 121 个地点 每个地点有 3 个值 我想绘制 121 个位置中每个位置的三个值的小条形图 目前 这些值绘制为markersize属性 看起来像这样 密集恐惧症情节 https i stack imgur com 5fv
  • Django css文件缓存

    我有一个 css 文件 我想修改它以满足我的需要 问题是它似乎被缓存在某个地方 因为无论我在 css 文件中做什么 我都看不到更改 我确信我指向了正确的文件 因为现在我已经对其进行了修改 并且它有效 有什么设置可以关闭缓存吗 谢谢 正如本文
  • 如何生成非 UTF-8 字符集

    我的要求之一是 文本框名称应仅接受 UTF 8 字符集 我想通过输入非 UTF 8 字符集来执行否定测试 我怎样才能做到这一点 如果您问如何构造非 UTF 8 字符 那应该很容易这个定义来自维基百科 http en wikipedia or
  • DynamoDB - 如果哈希(或哈希和范围组合)不存在则放置项目

    以下是我的用例 我有一个带有哈希 范围键的 Dynamo 表 当我将新项目放入表中时 我想进行唯一性检查 有时我想保证哈希值是唯一的 忽略范围 其他时候我想允许重复的哈希值 但保证哈希值和范围的组合是唯一的 我怎样才能做到这一点 我尝试了
  • 如何仅对农业网格中的某些行禁用编辑

    我想根据条件仅启用我的 ag grid 中的某些行 示例 2 5 editable false 没有帮助 因为它应用于整个列表 除非有一个我不知道的方法 请提供任何帮助 你只需绑定即可function to editable财产在colum
  • 将存储库接口作为参数传递给域类上的方法是否被认为是糟糕的设计?

    我们的领域模型现在非常贫乏 我们的实体大多是空壳 几乎纯粹是为了保存值和导航到集合而设计的 我们正在使用 EF 4 1 代码优先 ORM 到目前为止的设计是为了让我们的新手开发人员在早期迭代期间查询上下文时免受可怕的 LINQ to Ent
  • Infinispan 复制缓存不复制对象以供读取

    我们正在尝试在 Openshift 内的 Wildfly 11 上运行的两个 infinispan 节点上安装复制缓存 当我们在一个节点上写入一个对象时 它不会显示在另一节点上进行读取 启动时 节点在集群中连接 并且可以看到彼此 如日志中所
  • 使用 NodeJS 让 Discord 机器人发送带有消息的图片

    我有几张照片 全部在 imgur 上 带有直接图像链接 格式 https i imgur com XXXXXX jpg https i imgur com XXXXXX jpg 以及用 NodeJS 制作的 Discord 机器人 我发送这
  • Heroku 多个 dyno socket.io

    我正在使用 Socket io 开发一个 node js 应用程序 并将其部署在 Heroku Dyno 上 Socket io 使用 RedisStore 及其 PUB SUB Socket io 客户端与 Heroku 中的一个 dyn
  • 在 PHP 中将对象作为参数传递[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何使用 SwiftUI 使按钮可拖动/可移动?

    我正在尝试使用 SwiftUI 制作一个可移动的按钮 从看起来这应该可行 我尝试将带有文本的按钮放入另一个 ZStack 中 有一秒钟它可以工作 但一旦我释放按钮 拖动就会停止 我无法再拖动 我注意到尽管按钮已经移动 但水龙头仍然位于中心
  • 为什么 tkinter / window.update 在我的程序中随着时间的推移变得更慢?

    我发现当我调用 window update 时 当向窗口写入的内容较少时 它的运行速度会更快 但后来 当我向窗口写入更多元素时 window update 需要更长的时间 请参阅下面的我的代码 您可以看到它在更新窗口之前一次向屏幕 100
  • iOS9 Swift 文件使用 NSURL 创建 NSFileManager.createDirectoryAtPath

    在iOS9之前 我们创建了一个像这样的目录 let documentsPath NSSearchPathForDirectoriesInDomains DocumentDirectory UserDomainMask true 0 as S
  • 子进程改变目录

    我想在子目录 超级目录中执行脚本 我需要首先进入该子目录 超级目录 我无法得到subprocess进入我的子目录 tducin localhost Projekty tests ve python Python 2 7 4 default
  • Three.js - 在代码中包含网格数据

    我有这个 Three js 代码 其中 JSON 加载器从文件 models mountain json 加载网格 var Three new function this scene new THREE Scene this camera
  • Oracle SQL 分析查询 - 类似递归电子表格的运行总计

    我有以下数据 由A值 排序依据MM 月 The B列计算为GREATEST current value of A previous value of B 0 以类似电子表格的方式 我怎样才能计算B使用 SQL 查询 我尝试使用分析函数 但未
  • 当存在 copy_from_user 时应用 get_user

    在Linux内核编程中 我看到get user and 从用户复制从用户空间执行读取 前一个读取固定的 1 2 或 4 个字节 而后一个从用户空间读取任意数量的字节 get user 需要什么 copy from user 是否在 get
  • 使用 Hibernate 或 Spring 打印 DBMS_OUTPUT.put_line

    我想知道 Hibernate 或 Spring 或任何第 3 方库是否提供将 DBMS OUTPUT put line 消息直接打印到 system out 或日志文件的能力 目的是在控制台中同时显示 PLSQL 日志消息和 java 日志