Hibernate日誌打印sql參數

本文將從多個方面介紹如何在Hibernate中打印SQL參數。Hibernate作為一種ORM框架,可以通過打印SQL參數方便開發者調試和優化Hibernate應用。

一、通過配置開啟SQL參數日誌打印

在Hibernate的配置文件中,可以通過設置show_sqlformat_sql選項來開啟打印SQL語句和格式化打印。

<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>

如果在Hibernate應用中開啟了這兩個選項,Hibernate會在控制台輸出每個執行的SQL語句以及其參數。但是這種方式無法輸出參數的值。

二、通過自定義日誌打印器實現SQL參數日誌打印

在Hibernate中,可以通過實現org.hibernate.resource.jdbc.spi.StatementInspector接口來自定義SQL語句的日誌打印行為。


public class MyStatementInspector implements StatementInspector {

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

    @Override
    public String inspect(String sql) {
        LOGGER.info("SQL執行語句: {}", sql);
        return sql;
    }

    @Override
    public  T inspect(T entity) {
        return entity;
    }
}

通過實現StatementInspector接口並重寫inspect()方法,可以在每次SQL執行語句時記錄SQL語句並輸出到日誌中。如果想要輸出SQL語句中的參數,可以將sql字符串轉換為PreparedStatement對象,並調用getParameter()方法獲取參數的實際值。


public class MyStatementInspector implements StatementInspector {

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

    @Override
    public String inspect(String sql) {
        LOGGER.info("SQL執行語句: {}", sql);
        try {
            PreparedStatement preparedStatement = JdbcServicesImpl.GROUP_JDBC_SERVICES.prepare(sql, false);
            ParameterMetaData parameterMetaData = preparedStatement.getParameterMetaData();
            for (int i = 1; i <= parameterMetaData.getParameterCount(); i++) {
                Object paramValue = preparedStatement.getParameter(i);
                LOGGER.info("參數{}: {}", i, paramValue);
            }
        } catch (Exception e) {
            LOGGER.error("獲取參數出錯", e);
        }
        return sql;
    }

    @Override
    public  T inspect(T entity) {
        return entity;
    }
}

可以通過將自定義的StatementInspector實例設置到Hibernate的physical-sql-inspector屬性中來啟用該功能:

<session-factory>
  <property name="hibernate.physical-sql-inspector">mypackage.MyStatementInspector</property>
</session-factory>

三、通過AOP攔截器實現SQL參數日誌打印

除了自定義StatementInspector外,還可以利用AOP攔截器的方式來實現SQL參數的日誌打印。


@Aspect
@Component
public class SqlParamLogAspect {

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

    @Around("execution(* org.hibernate.SQLQuery.uniqueResult(..)) " +
            "|| execution(* org.hibernate.SQLQuery.list(..)) " +
            "|| execution(* org.hibernate.internal.AbstractQueryImpl.uniqueResult(..)) " +
            "|| execution(* org.hibernate.internal.AbstractQueryImpl.list(..)) " +
            "|| execution(* org.hibernate.loader.Loader.executeQueryStatement(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        String sql = null;
        Object[] args = pjp.getArgs();
        if (args.length > 0) {
            sql = (String) args[0];
        }
        try {
            Object result = pjp.proceed();
            LOGGER.info("SQL執行語句: {}", sql);
            if (args.length > 1 && args[1] instanceof QueryParameters) {
                QueryParameters queryParams = (QueryParameters) args[1];
                TreeMap map = new TreeMap<>();
                int i = -1;
                for (TypedValue tv : queryParams.getPositionalParameterValues()) {
                    i++;
                    LOGGER.info("參數{}: {}", i, tv.getValue());
                }
                LOGGER.info("");
            }
            return result;
        } catch (Throwable throwable) {
            LOGGER.error("SQL執行出錯: {}", sql, throwable);
            throw throwable;
        }
    }
}

通過在Hibernate執行SQL語句的關鍵方法上添加AOP切面,可以截獲執行的SQL語句以及參數,將SQL語句和參數同時輸出到日誌中。

四、通過ORM框架實現SQL參數日誌打印

除了上述方法以外,我們還可以使用第三方ORM框架來實現SQL參數的日誌打印。如:P6Spy

P6Spy是一個Java開發的ORM框架,可以截獲Java應用程序發往數據庫的SQL語句並將其輸出到日誌中。可以通過添加P6Spy的JDBC Driver來替換Hibernate默認的JDBC Driver,以截獲Hibernate執行的SQL語句,並在日誌中輸出SQL參數。

<!-- 引入P6Spy JDBC Driver -->
<dependency>
    <groupId>p6spy</groupId>
    <artifactId>p6spy</artifactId>
    <version>3.6.0</version>
</dependency>

接下來,在hibernate.cfg.xml文件中將hibernate.connection.driver_class屬性設置為P6Spy的JDBC Driver:

<property name="hibernate.connection.driver_class">com.p6spy.engine.spy.P6SpyDriver</property>

最後,在p6spy.properties文件中配置日誌輸出:

module.log=com.p6spy.engine.logging.P6LogFactory,com.p6spy.engine.logging.appender.StdoutLogger
realdriver=org.sqlite.SQLiteDriver
driverlist=org.sqlite.JDBC

配置完成後,P6Spy會攔截Hibernate執行的每個SQL語句,並將其輸出到控制台或文件中,同時也會輸出SQL語句的參數。

原創文章,作者:ZPNAH,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/375368.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
ZPNAH的頭像ZPNAH
上一篇 2025-04-29 12:49
下一篇 2025-04-29 12:49

相關推薦

  • 三星內存條參數用法介紹

    本文將詳細解釋三星內存條上面的各種參數,讓你更好地了解內存條並選擇適合自己的一款。 一、容量大小 容量大小是內存條最基本的參數,一般以GB為單位表示,常見的有2GB、4GB、8GB…

    編程 2025-04-29
  • Python3定義函數參數類型

    Python是一門動態類型語言,不需要在定義變量時顯示的指定變量類型,但是Python3中提供了函數參數類型的聲明功能,在函數定義時明確定義參數類型。在函數的形參後面加上冒號(:)…

    編程 2025-04-29
  • Python input參數變量用法介紹

    本文將從多個方面對Python input括號里參數變量進行闡述與詳解,並提供相應的代碼示例。 一、基本介紹 Python input()函數用於獲取用戶輸入。當程序運行到inpu…

    編程 2025-04-29
  • Cron執行日誌用法介紹

    本文將從多個方面對cron執行日誌進行詳細闡述,包括cron執行日誌的定義、cron執行日誌的產生原因、cron執行日誌的格式以及如何解讀cron執行日誌。 一、定義 Cron是一…

    編程 2025-04-29
  • Spring Boot中發GET請求參數的處理

    本文將詳細介紹如何在Spring Boot中處理GET請求參數,並給出完整的代碼示例。 一、Spring Boot的GET請求參數基礎 在Spring Boot中,處理GET請求參…

    編程 2025-04-29
  • Python Class括號中的參數用法介紹

    本文將對Python中類的括號中的參數進行詳細解析,以幫助初學者熟悉和掌握類的創建以及參數設置。 一、Class的基本定義 在Python中,通過使用關鍵字class來定義類。類包…

    編程 2025-04-29
  • Python函數名稱相同參數不同:多態

    Python是一門面向對象的編程語言,它強烈支持多態性 一、什麼是多態多態是面向對象三大特性中的一種,它指的是:相同的函數名稱可以有不同的實現方式。也就是說,不同的對象調用同名方法…

    編程 2025-04-29
  • Hibernate註解聯合主鍵 如何使用

    解答:Hibernate的註解方式可以用來定義聯合主鍵,使用@Embeddable和@EmbeddedId註解。 一、@Embeddable和@EmbeddedId註解 在Hibe…

    編程 2025-04-29
  • 使用SQL實現select 聚合查詢結果前加序號

    select語句是數據庫中最基礎的命令之一,用於從一個或多個表中檢索數據。常見的聚合函數有:count、sum、avg等。有時候我們需要在查詢結果的前面加上序號,可以使用以下兩種方…

    編程 2025-04-29
  • 理解Mybatis中的SQL Limit用法

    Mybatis是一種非常流行的ORM框架,提供了SQL映射配置文件,可以使用類似於傳統SQL語言的方式編寫SQL語句。其中,SQL的Limit語法是一個非常重要的知識點,能夠實現分…

    編程 2025-04-29

發表回復

登錄後才能評論