java · 2025-04-30 0

jpa 配置 StatementInspector,获得生成的 sql

一、hibernate

1.pom

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.2.18.Final</version>
</dependency>

<dependency>
    <groupId>org.postgresql</groupId>
    <artifactId>postgresql</artifactId>
    <version>42.2.27</version>
</dependency>

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>

<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.26</version>
    <scope>provided</scope>
</dependency>

2.实体类

@Setter
@Getter
@Entity
@Table(name = "t_student")
public class Student {

    @Id
    private Integer id;

    private String name;
}

3.定义拦截器

public class CustomSqlStatementInterceptor implements StatementInspector {

    @Override
    public String inspect(String sql) {
        System.out.println("sql: " + sql);
        return sql;
    }
}

4.配置文件及配置拦截器生效

配置 hibernate.session_factory.statement_inspector 指定拦截器

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
             http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
             version="2.0">

    <persistence-unit name="myjpa">
        <!-- jpa的实现产品 -->
        <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
        <properties>
            <!-- 数据库连接配置 -->
            <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver"/>
            <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://127.0.0.1:5432/postgres"/>
            <property name="javax.persistence.jdbc.user" value="postgres"/>
            <property name="javax.persistence.jdbc.password" value="123456"/>
            <!-- hibernate的配置 -->
            <property name="hibernate.hbm2ddl.auto" value="update"/>
            <property name="hibernate.show_sql" value="true"/>
            <property name="hibernate.format_sql" value="true"/>
            <property name="hibernate.session_factory.statement_inspector" value="org.example.config.CustomSqlStatementInterceptor"/>
        </properties>
    </persistence-unit>
</persistence>

5.测试

@Test
public void testPersist() {
    /**
     * 通过 Persistence 获取 EntityManagerFactory, 传入参数对应配置文件中持久化单元 persistence-unit 的 name
     * 通过 EntityManagerFactory 创建 EntityManager 获取 EntityTransaction 开启事务
     */
    EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("myjpa");
    EntityManager entityManager = entityManagerFactory.createEntityManager();
    EntityTransaction transaction = entityManager.getTransaction();
    transaction.begin();

    Student stu = new Student();
    stu.setId(1);
    stu.setName("stu1");

    // 转换为托管状态
    entityManager.persist(stu);

    /**
     * 提交事务 关闭 entityManager 关闭 entityManagerFactory
     */
    transaction.commit();
    entityManager.close();
    entityManagerFactory.close();
}

二、spring-boot-jpa

1.pom

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.7.2</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    <dependency>
        <groupId>org.postgresql</groupId>
        <artifactId>postgresql</artifactId>
        <version>42.2.27</version>
    </dependency>

    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.26</version>
        <scope>provided</scope>
    </dependency>
</dependencies>

2.实体类和dao

@Setter
@Getter
@Entity
@Table(name = "t_student")
public class Student {

    @Id
    private Integer id;

    private String name;
}
@Repository
public interface StudentRepository extends JpaRepository<Student, Long> {

    List<Student> findAllByNameContaining(String name);
}

3.定义拦截器

public class CustomSqlStatementInterceptor implements StatementInspector {

    @Override
    public String inspect(String sql) {
        System.out.println("sql: " + sql);
        return sql;
    }
}

4.配置拦截器生效

方式一:

applicaiton.yml 配置文件中通过 spring.jpa.properties.hibernate.session_factory.statement_inspector 指定拦截器

spring:
  datasource:
    url: jdbc:postgresql://127.0.0.1:5432/postgres
    username: postgres
    password: 123456
    driver-class-name: org.postgresql.Driver
  jpa:
    show-sql: true
    open-in-view: true
    hibernate:
      ddl-auto: update
    properties:
      hibernate:
        session_factory:
          statement_inspector: org.example.config.CustomSqlStatementInterceptor

方式二:

配置 HibernatePropertiesCustomizer 指定

@Configuration(proxyBeanMethods = false)
public class JpaConfig {

    @Bean
    public HibernatePropertiesCustomizer hibernatePropertiesCustomizer(CustomSqlStatementInterceptor inspector) {
        return properties -> properties.put(AvailableSettings.STATEMENT_INSPECTOR, inspector);
    }

    @Bean
    public CustomSqlStatementInterceptor interceptor() {
        return new CustomSqlStatementInterceptor();
    }
}

5.测试

@Component
public class MyRunner implements ApplicationRunner {

    @Autowired
    private StudentRepository repository;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        repository.findAll();
    }
}
@SpringBootApplication
public class WebJPABoot {

    public static void main(String[] args) {
        SpringApplication.run(WebJPABoot.class, args);
    }
}