未分类 · 2025-09-30 0

Springboot JPA 拦截 SQL

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>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.31</version>
    </dependency>

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

2.配置文件

server:
  port: 8080
spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/test1
    username: root
    password: 123456
  jpa:
    hibernate:
      ddl-auto: update

3.jpa

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

    @Id
    private Integer id;

    private String name;

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

}

4.配置

public class StatementInspector1 implements StatementInspector {

    @Override
    public String inspect(String sql) {
        System.out.println("StatementInspector1 inspect: " + sql);
        return sql;
    }
}
/**
 * 注意:通常建议不要让 Interceptor 成为 Spring Bean,以避免循环依赖等问题
 */
public class EmptyInterceptor1 extends EmptyInterceptor {

    @Override
    public String onPrepareStatement(String sql) {
        // 在这里可以记录 SQL
        System.out.println("EmptyInterceptor1 onPrepareStatement: " + sql);
        // 如果你能在其他地方获取到参数(比如结合 BasicPropertyAccessor),可以打印
        // 但更推荐用日志方式看参数
        return super.onPrepareStatement(sql);
    }

    /**
     * 保存数据,会调用这个方法,在保存对象之前调用此方法
     */
    @Override
    public boolean onSave(Object entity, Serializable id, Object[] state,
                          String[] propertyNames, Type[] types) {
        System.out.println(String.format("EmptyInterceptor1 onSave: propertyNames=%s, values=%s",
                Arrays.toString(propertyNames), Arrays.toString(state)));
        return false;
    }

    /**
     * 查询数据,会调用这个方法
     */
    @Override
    public boolean onLoad(Object entity, Serializable id, Object[] state,
                          String[] propertyNames, Type[] types) {
        // 记录加载实体的信息
        System.out.println(String.format("EmptyInterceptor1 onLoad: id=%s, propertyNames=%s, state=%s",
                id, Arrays.toString(propertyNames), Arrays.toString(state)));
        return false;
    }

    /**
     * 在删除对象之前调用此方法
     */
    @Override
    public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
        System.out.println(String.format("EmptyInterceptor1 onDelete: id=%s, propertyNames=%s, state=%s",
                id, Arrays.toString(propertyNames), Arrays.toString(state)));
    }
}
@Configuration(proxyBeanMethods = false)
public class JpaConfig {

    @Bean
    public StatementInspector1 statementInspector1() {
        return new StatementInspector1();
    }

    @Bean
    public EmptyInterceptor1 emptyInterceptor1() {
        return new EmptyInterceptor1();
    }

    @Bean
    public HibernatePropertiesCustomizer hibernatePropertiesCustomizer(StatementInspector1 statementInspector1,
                                                                       EmptyInterceptor1 emptyInterceptor1) {
        return properties -> {
            properties.put(AvailableSettings.STATEMENT_INSPECTOR, statementInspector1);
            properties.put(AvailableSettings.INTERCEPTOR, emptyInterceptor1);
        };
    }
}

5.启动类

@Component
public class MyRunner implements ApplicationRunner {

    @Autowired
    private StudentRepository repository;

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("- - - 1 repository.save - - -");
        Student student1 = new Student(11, "stu1", 110);
        Student student2 = new Student(12, "stu2", 120);
        repository.save(student1);
        repository.save(student2);

        System.out.println("- - - 2 repository.findAll - - -");
        List<Student> result = repository.findAll();

        System.out.println("- - - 3 repository.delete - - -");
        repository.delete(new Student(11, null, null));
        repository.delete(new Student(12, null, null));
    }
}
@SpringBootApplication
public class WebJPABoot {

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

6.结果

- - - 1 repository.save - - -
StatementInspector1 inspect: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from t_student student0_ where student0_.id=?
EmptyInterceptor1 onSave: propertyNames=[age, name], values=[110, stu1]
StatementInspector1 inspect: insert into t_student (age, name, id) values (?, ?, ?)
StatementInspector1 inspect: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from t_student student0_ where student0_.id=?
EmptyInterceptor1 onSave: propertyNames=[age, name], values=[120, stu2]
StatementInspector1 inspect: insert into t_student (age, name, id) values (?, ?, ?)
- - - 2 repository.findAll - - -
StatementInspector1 inspect: select student0_.id as id1_0_, student0_.age as age2_0_, student0_.name as name3_0_ from t_student student0_
EmptyInterceptor1 onLoad: id=11, propertyNames=[age, name], state=[110, stu1]
EmptyInterceptor1 onLoad: id=12, propertyNames=[age, name], state=[120, stu2]
- - - 3 repository.delete - - -
StatementInspector1 inspect: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from t_student student0_ where student0_.id=?
EmptyInterceptor1 onLoad: id=11, propertyNames=[age, name], state=[110, stu1]
EmptyInterceptor1 onDelete: id=11, propertyNames=[age, name], state=[110, stu1]
StatementInspector1 inspect: delete from t_student where id=?
StatementInspector1 inspect: select student0_.id as id1_0_0_, student0_.age as age2_0_0_, student0_.name as name3_0_0_ from t_student student0_ where student0_.id=?
EmptyInterceptor1 onLoad: id=12, propertyNames=[age, name], state=[120, stu2]
EmptyInterceptor1 onDelete: id=12, propertyNames=[age, name], state=[120, stu2]
StatementInspector1 inspect: delete from t_student where id=?