2017-09-22 1 views
1

저는 Spring Boot + Rest + Jpa로 작업하고 있습니다. 사용자가 직원 엔티티 (empId, salary, age, location , 역할, 경험) 열을 변경하려면 이전 및 새 변경 사항을 추적하고 열이 변경된 감사 테이블에 입력해야합니다.업데이트 된 엔티티를 이전 엔티티와 비교하고 데이터베이스에 업데이트 된 값만 저장하는 방법

public EmployeeEntity update(int empId, EmployeeEntity employeeEntity) { 

    em = emf.createEntityManager(); 
    EmployeeEntity beforeObj = em.find(EmployeeEntity .class,empId); 

    try { 
     em.getTransaction().begin(); 
     em.merge(employeeEntity); 
     em.getTransaction().commit(); 
    } 
    finally { 
     em.close(); 
    } 

    return employeeEntity; 
} 

그래서 지금은 예를 업데이트하는 경우에만 급여 및 위치는 대한, 그래서 내가있는 그 업데이트를 추적해야 beforeObj (이전 값과 직원 단체)와 employeeEntity (업데이트 된 값)와 엔티티가 감사 테이블 최소한의 트랜잭션 만 발생할 수 있기 때문에 Envers 또는 다른 JPA 도구를 사용하는 것보다 간단하게 처리해야합니다. 같은 필요한

@Entity 
@Table(name = "TEMPLOYEE") 
public class EmployeeEntity implements Serializable { 

private static final long serialVersionUID = 1L; 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
@Column(name = "EMP_NO") 
private int EMP_NO; 

@Column(name = "SALARY_VAL") 
private int SALARY_VA; 

@Column(name = "ROLE_NAME") 
private String ROLE_NAME; 

@Column(name = "EXPERIENCE") 
private int EXPERIENCE; 

@Column(name = "LOCATION") 
private String LOCATION; 

// Getters and Setters 

통찰력 :

이 내 엔티티 클래스입니다.

답변

1

JPA로 작업 할 때 "이전"또는 "새"객체 같은 것은 없습니다. 일반적으로 EntityManager을 통해 데이터베이스에서 개체를 검색하여 수정하고 해당 개체의 현재 상태가 데이터베이스에 유지되는 트랜잭션을 커밋합니다.

두 가지 옵션이 있습니다. 여기 :

1) 직원 테이블에 대한 업데이트시 감사 테이블을 채우는 데이터베이스 트리거를 만듭니다. 이 작업을 수행 할 경우 감사 테이블을 JPA 매핑에서 멀리 떨어지게두면 JPA 매핑을 데이터베이스에만 보관하십시오.

2) 직원에 대한 변경 로그 엔티티를 생성하십시오.

public enum EmployeeChangeType { 
    SALARY_UPDATED, 
    LOCATION_UPDATED 
} 

@Entity 
public class Change { 

    @Id 
    @GeneratedValue 
    private Long id; 

    private EmployeeChangeType changeType; 

    private String oldValue; 

    private String newValue; 

    private String changedByUser; 

    //... 
} 

@Entity 
public class Employee { 
    //... 
    @OneToMany 
    private List<Change> changes = new ArrayList<>(); 

    //... 
    public void updateSalary(final Integer newSalary, final String updatedBy) { 
     changes.add(new Change(EmployeeChangeType.SALARY_UPDATED, SALARY_VAL, newSalary, updatedBy)); 
     SALARY_VAL = newSalary; 
    } 

하지 완벽한 예, 그러나 희망 당신은 사진을 찍어 .. 또한

, 모든 대문자를 개체에 변수 이름을 사용할 필요가 없다는 JPA의 요점은 데이터베이스를 분리하는 것입니다 자바 디자인의 디자인.

업데이트 : 보너스 솔루션 : 경우에 따라 엔티티의 개정판을 사용합니다. 그런 다음 엔터티를 업데이트하면 데이터베이스에 새로운 행이 생깁니다.

final Employee currentVersion = employeeRepo.getCurrentVersion(employeeId); 
final Employee newVersion = new Employee(currentVersion); 
//do changes to employee 
employeeRepo.persist(newVersion); 

그것은 종류의 JPA의 오용으로 저를 친다 :

@Entity 
public class Employee { 

    @Lazy 
    @OneToOne 
    private Employee lastVersion; 

    //some identifier that is common for all versions of employee 
    private Integer employeeNumber; 

    public Employee(final Employee currentVersion) { 
     //copy all fields from currentVersion to this, except id 
     this.lastVersion = currentVersion; 
    } 
    //... 
} 

당신은 일반적으로 이렇게 .. 내 생각에이 그것을 해결하는 아주 예쁜 방법이 아니다,주의를 요합니다 그러나 어떤 경우에는 적용 가능할 수도 있습니다 ..

+0

답변을위한 노력에 감사드립니다. – DinaMike

+0

이 질문에도 관심이 있습니다. 모든 필드를 추적하려면 문자열, 이중 등을 처리하기 위해 oldValue 및 newValue를 객체로 간주하고 changeType 열거 형 목록의 모든 필드를 고려해야합니까? 'OneToMany' 관계에서는'add '와'remove' 연산에 대한 것이라고 생각합니다. 나 맞아 ? – Al1

+0

'String'인 이유는 그것을 데이터베이스의 특정 열에 매핑해야하기 때문입니다. 그리고'String'을'int'에 넣을 수 없으므로'String'을 사용하고 데이터 형이 무엇이든간에 문자열 표현을 사용해야합니다. 이는 주로 정보를 다루는 변경 로그를 표시하는 것 외에 문서화를위한 것입니다. 컬렉션의 경우 일반적으로 추가 및 제거 로그를 남깁니다. 동일한 객체의 버전/버전을 통해이 문제를 해결할 수있는 또 다른 방법이 있습니다. 내 대답을 업데이트 할게. – Tobb

0

@Tobb은 이미 답변을 제출했지만, 실제로 살기 전에 직원 기록 변경이 승인되어야하는 경우에 사용할 수있는 또 다른 경로가 있습니다. "감사 기록"테이블을 "직원 기록"으로 구현할 수 있습니다. "직원 기록"에는 "직원"이 수행하는 모든 열과 누가 언제 어떤 데이터를 변경했는지 추적하는 열이 있습니다. "만료 된 타임 스탬프"및 "활성 타임 스탬프"열을 사용하여 실제 "직원"테이블의 활성 레코드와 일치해야하는 "기록"레코드를 추적 할 수 있습니다.

일반 사용자가 직원 기록을 변경하면 변경된 기록은 "직원 기록"테이블에만 저장되고 "감사 요청"이 트리거되어 검토하고 승인해야하는 사람에게 경고 할 수 있습니다 변경 사항을 실제 "직원"테이블에 기록 할 수 있습니다. 검토자가 감사를 수행하면 "기록"테이블에는 이전의 변경되지 않은 직원 기록 레코드 (NULL이 만료 된 시간 소인과 가장 최근의 활성 시간 소인)와 새 제안 변경 직원 기록이 기록됩니다 (둘 다 만기 된 기록 활성 시간 소인은 NULL입니다. 검토자가 감사를 수행 한 후에 변경되지 않은 이전 직원 기록에는 현재 만료 된 시간 소인이 있고 새로 업데이트 된 직원 기록에는 NULL 만료 된 시간 소인과 가장 최근의 활성 시간 소인이 있습니다. 새로 업데이트 된 직원 기록은 업데이트 된 관련 직원 기록과도 일치합니다. 이

http://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#events

당신은 일반적인 방법으로 그것을 구현하는 방법을 볼 수 있습니다 :

+0

답변을위한 노력에 감사드립니다. – DinaMike

0

당신은 JPA와 최대 절전 모드에서 이벤트에 대한 최대 절전 모드 문서를 살펴 있어야합니다. 도움이되기를 바랍니다.

+0

답변을위한 노력에 감사드립니다. – DinaMike