網頁

2021/6/23

Spring Data JPA 使用 @EntityListener 攔截entity存取操作

Spring Data JPA使用@EntityListener攔截entity存取資料庫操作範例。


在entity類別名稱前掛上JPA的@EntityListener可指定攔截操作的處理器類別。

範例環境:

  • Java 8
  • Spring Boot 2.3.2.RELEASE
  • Spring Data JPA
  • H2 database
  • JUnit 5

例如下面在Employee entity類加上@EntityListener,指定EntityLogListener負責對此entity的資料庫操作進行攔截。

Employee

package com.abc.demo.entity;

import com.abc.demo.entity.listener.EntityLogListener;

import javax.persistence.*;
import java.io.Serializable;

@EntityListeners(EntityLogListener.class)
@Entity
public class Employee implements Serializable {
    private static final Long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String name;
    private Integer age;
    
    // constructors, getters, setters, hashCode(), equals(), toString()
}

Repository類EmployeeRepository提供對Employee的持久操作方法。

EmployeeRepository

package com.abc.demo.repository;

import com.abc.demo.entity.Employee;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}

下面為自訂的攔截處理器EntityLogListener,搭配JPA callback annotation在CRUD操作的前後插入印出log的邏輯。

EntityLogListener

package com.abc.demo.entity.listener;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.persistence.*;

public class EntityLogListener {
    
    Logger log = LoggerFactory.getLogger(EntityLogListener.class);

    /** 查詢後 */
    @PostLoad
    private void logPostLoad(Object entity) {
        log.info("retrieved entity={}", entity);
    }

    /** 新增前 */
    @PrePersist
    private void logPrePersist(Object entity) {
        log.info("pre-insert entity={}", entity);
    }

    /** 新增後 */
    @PostPersist
    private void logPostPersist(Object entity) {
        log.info("post-insert entity={}", entity);
    }

    /** 更新前 */
    @PreUpdate
    private void logPreUpdate(Object entity) {
        log.info("pre-udpate entity={}", entity);
    }

    /** 更新後 */
    @PostUpdate
    private void logPostUpdate(Object entity) {
        log.info("post-update entity={}", entity);
    }

    /** 刪除前 */
    @PreRemove
    private void logPreRemove(Object entity) {
        log.info("pre-delete entity={}", entity);
    }

    /** 刪除後 */
    @PostRemove
    private void logPostRemove(Object entity) {
        log.info("post-delete entity={}", entity);
    }

}

測試

EmployeeRepositoryTests測試類中對Employee執行CRUD操作觀察是否有插入log。

EmployeeRepositoryTests

package com.abc.demo.repository;

import com.abc.demo.entity.Employee;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
public class EmployeeRepositoryTests {

    @Autowired
    private EmployeeRepository employeeRepository;

    @Test
    public void test() {
        // insert
        Employee employee = new Employee(4, "Jack", 26);
        employee = employeeRepository.save(employee);

        // update
        employee.setName("Jackson");
        employeeRepository.save(employee);

        // delete
        employeeRepository.delete(employee);

    }

}

執行可看到console中確實在CRUD前後印出EntityLogListener插入的log。

2021-06-23 14:45:06.660 DEBUG 9188 --- [           main] o.h.SQL                                  : select employee0_.id as id1_0_0_, employee0_.age as age2_0_0_, employee0_.name as name3_0_0_ from employee employee0_ where employee0_.id=?
2021-06-23 14:45:06.664 TRACE 9188 --- [           main] o.h.t.d.s.BasicBinder                    : binding parameter [1] as [BIGINT] - [4]
2021-06-23 14:45:06.671  INFO 9188 --- [           main] c.a.d.e.l.EntityLogListener              : pre-insert entity=Employee(id=4, name=Jack, age=26)
2021-06-23 14:45:06.679 DEBUG 9188 --- [           main] o.h.SQL                                  : insert into employee (id, age, name) values (null, ?, ?)
2021-06-23 14:45:06.681 TRACE 9188 --- [           main] o.h.t.d.s.BasicBinder                    : binding parameter [1] as [INTEGER] - [26]
2021-06-23 14:45:06.681 TRACE 9188 --- [           main] o.h.t.d.s.BasicBinder                    : binding parameter [2] as [VARCHAR] - [Jack]
2021-06-23 14:45:06.685  INFO 9188 --- [           main] c.a.d.e.l.EntityLogListener              : post-insert entity=Employee(id=1, name=Jack, age=26)
2021-06-23 14:45:06.692 DEBUG 9188 --- [           main] o.h.SQL                                  : select employee0_.id as id1_0_0_, employee0_.age as age2_0_0_, employee0_.name as name3_0_0_ from employee employee0_ where employee0_.id=?
2021-06-23 14:45:06.693 TRACE 9188 --- [           main] o.h.t.d.s.BasicBinder                    : binding parameter [1] as [BIGINT] - [1]
2021-06-23 14:45:06.696 TRACE 9188 --- [           main] o.h.t.d.s.BasicExtractor                 : extracted value ([age2_0_0_] : [INTEGER]) - [26]
2021-06-23 14:45:06.696 TRACE 9188 --- [           main] o.h.t.d.s.BasicExtractor                 : extracted value ([name3_0_0_] : [VARCHAR]) - [Jack]
2021-06-23 14:45:06.697  INFO 9188 --- [           main] c.a.d.e.l.EntityLogListener              : retrieved entity=Employee(id=1, name=Jack, age=26)
2021-06-23 14:45:06.698  INFO 9188 --- [           main] c.a.d.e.l.EntityLogListener              : pre-udpate entity=Employee(id=1, name=Jackson, age=26)
2021-06-23 14:45:06.701 DEBUG 9188 --- [           main] o.h.SQL                                  : update employee set age=?, name=? where id=?
2021-06-23 14:45:06.702 TRACE 9188 --- [           main] o.h.t.d.s.BasicBinder                    : binding parameter [1] as [INTEGER] - [26]
2021-06-23 14:45:06.702 TRACE 9188 --- [           main] o.h.t.d.s.BasicBinder                    : binding parameter [2] as [VARCHAR] - [Jackson]
2021-06-23 14:45:06.702 TRACE 9188 --- [           main] o.h.t.d.s.BasicBinder                    : binding parameter [3] as [BIGINT] - [1]
2021-06-23 14:45:06.704  INFO 9188 --- [           main] c.a.d.e.l.EntityLogListener              : post-update entity=Employee(id=1, name=Jackson, age=26)
2021-06-23 14:45:06.705 DEBUG 9188 --- [           main] o.h.SQL                                  : select employee0_.id as id1_0_0_, employee0_.age as age2_0_0_, employee0_.name as name3_0_0_ from employee employee0_ where employee0_.id=?
2021-06-23 14:45:06.706 TRACE 9188 --- [           main] o.h.t.d.s.BasicBinder                    : binding parameter [1] as [BIGINT] - [1]
2021-06-23 14:45:06.708 TRACE 9188 --- [           main] o.h.t.d.s.BasicExtractor                 : extracted value ([age2_0_0_] : [INTEGER]) - [26]
2021-06-23 14:45:06.708 TRACE 9188 --- [           main] o.h.t.d.s.BasicExtractor                 : extracted value ([name3_0_0_] : [VARCHAR]) - [Jackson]
2021-06-23 14:45:06.709  INFO 9188 --- [           main] c.a.d.e.l.EntityLogListener              : retrieved entity=Employee(id=1, name=Jackson, age=26)
2021-06-23 14:45:06.710  INFO 9188 --- [           main] c.a.d.e.l.EntityLogListener              : pre-delete entity=Employee(id=1, name=Jackson, age=26)
2021-06-23 14:45:06.715 DEBUG 9188 --- [           main] o.h.SQL                                  : delete from employee where id=?
2021-06-23 14:45:06.716 TRACE 9188 --- [           main] o.h.t.d.s.BasicBinder                    : binding parameter [1] as [BIGINT] - [1]
2021-06-23 14:45:06.717  INFO 9188 --- [           main] c.a.d.e.l.EntityLogListener              : post-delete entity=Employee(id=1, name=Jackson, age=26)


沒有留言:

張貼留言