복붙노트

[SPRING] Hibernate / JPA를 사용하여 삽입 / 업데이트 / 삭제 이전에 사용자를 DB에 알리는 방법은 무엇입니까?

SPRING

Hibernate / JPA를 사용하여 삽입 / 업데이트 / 삭제 이전에 사용자를 DB에 알리는 방법은 무엇입니까?

요약 (세부 정보) :

어떤 엔티티가 Spring / JPA 스택을 사용하여 저장 / 업데이트 / 삭제되기 전에 저장된 proc 호출을 만들고 싶습니다.

지루한 내용 :

우리는 오라클 / JPA (Hibernate) / 스프링 MVC (Spring Data repos) 애플리케이션을 가지고 있습니다.이 애플리케이션은 트리거를 사용하여 일부 테이블의 히스토리를 히스토리 테이블 (감사 할 테이블 당 하나의 히스토리 테이블)에 기록합니다. 이 엔티티들 각각은 EmptyInterceptor를 갱신 또는 삽입 할 때 확장하는 클래스를 통해 설정된 modifiedByUser를 가지고 있습니다. 트리거가 삽입 또는 업데이트를 보관하면이 열을 사용하여 누가 변경을했는지 쉽게 알 수 있습니다 (우리는 데이터베이스 사용자가 아닌 애플리케이션 사용자에 관심이 있습니다). 문제는 삭제의 경우 x에서 y라는 일반 삭제 일 뿐이므로 실행 된 SQL에서 마지막으로 수정 된 정보를 가져 오지 않습니다.

이를 해결하기 위해 스토어드 프로 시저를 실행하여 어떤 작업을 실행하기 전에 어떤 앱 사용자가 로그인했는지 데이터베이스에 알리고 싶습니다. 그런 다음 감사 트리거는 삭제가 발생하면이 값을보고 누가 삭제를 실행했는지 기록합니다.

시작 트랜잭션이나 다른 방법으로 SQL 또는 저장 프로 시저를 실행하여 DB에 어떤 작업이 수행되기 전에 트랜잭션에서 삽입 / 업데이트 / 삭제를 실행하는지 알려주는 방법이 있습니까?

나는 데이터베이스 측이 어떻게 작동하는지에 대한 세부 사항을 밝히지 만 필요하다면 더 많은 것을 얻을 수있다. 요지는 저장 프로 시저가 세션 변수를 보유 할 컨텍스트를 생성하고 트리거가 삭제시 해당 컨텍스트를 쿼리하여 사용자 ID를 얻는 것입니다.

해결법

  1. ==============================

    1.데이타베이스 끝에서, 이것에 대한 약간의 토론이 있습니다 :

    데이타베이스 끝에서, 이것에 대한 약간의 토론이 있습니다 :

    https://docs.oracle.com/cd/B19306_01/network.102/b14266/apdvprxy.htm#i1010372

    Spring / JPA 측에서 8.2 절을 참조하십시오.

    http://docs.spring.io/spring-data/jdbc/docs/current/reference/html/orcl.connection.html

    Spring 문서에 주어진 예제는 XML 설정을 사용한다. Java config를 사용하고 있다면 다음과 같습니다 :

    @Component
    @Aspect
    public class ClientIdentifierConnectionPreparer implements ConnectionPreparer
    {
      @AfterReturning(pointcut = "execution(* *.getConnection(..))", returning = "connection")
      public Connection prepare(Connection connection) throws SQLException
      {
        String webAppUser = //from Spring Security Context or wherever;
    
        CallableStatement cs = connection.prepareCall(
                     "{ call DBMS_SESSION.SET_IDENTIFIER(?) }");
        cs.setString(1, webAppUser);
        cs.execute();
        cs.close();
    
        return connection;
      }
    }
    

    Configuration 클래스를 통해 AspectJ 사용하기 :

    @Configuration
    @EnableAspectJAutoProxy
    public class SomeConfigurationClass
    {
    
    }
    

    이것은 Spring의 Oracle 확장에 관련된 섹션에서 숨겨져 있지만, 8.2 절 (8.1과 다름)에는 오라클 특정 (실행 된 선언문 제외) 인 것으로 보이며 일반적인 접근법은 관련 프로 시저 호출 또는 SQL을 지정하여 데이터베이스 :

    Postgres를 다음과 같이 예로 들었으므로 Postgres를 사용하는 모든 사람이이 접근법을 아래에서 사용할 수없는 이유를 알 수 없습니다.

    https://www.postgresql.org/docs/8.4/static/sql-set-role.html

  2. ==============================

    2.스토어드 프로 시저가 설명한 것 이상을 수행하지 않는 한 클리너 솔루션은 Envers (Entity Versioning)를 사용하는 것입니다. Hibernate는 엔티티의 버전을 별도의 테이블에 자동으로 저장하고 모든 CRUD 작업을 추적 할 수 있으며, 동일한 세션 내에서 발생하기 때문에 실패한 트랜잭션에 대해 걱정할 필요가 없습니다.

    스토어드 프로 시저가 설명한 것 이상을 수행하지 않는 한 클리너 솔루션은 Envers (Entity Versioning)를 사용하는 것입니다. Hibernate는 엔티티의 버전을 별도의 테이블에 자동으로 저장하고 모든 CRUD 작업을 추적 할 수 있으며, 동일한 세션 내에서 발생하기 때문에 실패한 트랜잭션에 대해 걱정할 필요가 없습니다.

    누가 변경했는지 추적하는 데는 새로운 칼럼을 추가 (By By updated)하고 Security Principal (예 : Spring Security User)에서 사용자의 로그인 ID를 얻으십시오.

    @CreationTimestamp 및 @UpdateTimestamp도 확인하십시오.

  3. ==============================

    3.나는 당신이 찾고있는 것이 트랜잭션 이벤트라고 생각한다.

    나는 당신이 찾고있는 것이 트랜잭션 이벤트라고 생각한다.

    @Service
    public class TransactionalListenerService{
    
       @Autowired
       SessionFactory sessionFactory;
    
       @TransactionalEventListener(phase = TransactionPhase.BEFORE_COMMIT)
        public void handleEntityCreationEvent(CreationEvent<Entity> creationEvent) {
              // use sessionFactory to run a stored procedure
        }
    }
    

    그런 다음 거래 서비스에서 필요한 경우 이벤트를 등록합니다.

    @Service
    public class MyTransactionalService{
    
         @Autowired
         private ApplicationEventPublisher applicationEventPublisher;
    
         @Transactional
         public void insertEntityMethod(Entity entity){
             // insert 
    
              // Publish event after insert operation
              applicationEventPublisher.publishEvent(new CreationEvent(this, entity));
    
             // more processing
         }
    
    }
    

    다음과 같은 요구 사항이있는 경우에도 트랜잭션 경계 외부에서 작동 할 수 있습니다.

  4. from https://stackoverflow.com/questions/41897957/how-can-i-use-hibernate-jpa-to-tell-the-db-who-the-user-is-before-inserts-update by cc-by-sa and MIT license