2017-09-22 18 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を通してオブジェクトを取得し、変更し、トランザクションをコミットします(問題のオブジェクトの現在の状態がデータベースに保持されます)。

2つのオプションがありますここでは:

1)従業員テーブルの更新に関する監査テーブルを作成するデータベーストリガーを作成します。これを行う場合は、監査テーブルを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の全体のポイントは、データベースを分離することですあなたのJavaデザインからのデザイン。

更新: ボーナスソリューション: 場合によっては、エンティティのリビジョンを使用しています。次に、エンティティを更新すると、データベースに新しい行が作成されます。

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'を使い、そのデータ型が何であっても何らかの文字列表現を使用しなければなりません。これは主にドキュメンテーションのためのものであり、おそらく情報では何もしない変更ログを表示していることに注意してください。コレクションの場合、通常は追加と削除をログに記録します。同じオブジェクトのバージョン/リビジョンを通して、これを解決するもう1つの方法があります。私は私の答えを更新します。 – Tobb

0

@Tobbは既に回答を提出していますが、実際にライブになる前に従業員レコードの変更を承認する必要がある場合には、別の方法があります。あなたの「監査」テーブルを「従業員履歴」として実装することができます。「従業員履歴」には、「従業員」に加えて、誰がどのデータをいつ変更したのかを追跡する列があります。 「期限切れのタイムスタンプ」列と「アクティブなタイムスタンプ」列を使用して、実際の「従業員」表のアクティブなレコードと一致する「履歴」レコードを追跡できます。

通常のユーザーが従業員レコードを変更すると、変更されたレコードは「従業員履歴」テーブルにのみ保存され、レビューと承認を必要とする人に警告するための「監査要求」がトリガーされますその変更を実際の "従業員"テーブルに書き込むことができます。レビュー担当者が監査を実行すると、「履歴」テーブルには、古い変更されていない従業員履歴レコード(NULLが期限切れのタイムスタンプ、最新のアクティブなタイムスタンプ)と新しい提案変更の従業員履歴レコード(期限切れの両方アクティブなタイムスタンプはNULLです)。レビュー担当者が監査を行った後、古い変更されていない従業員履歴レコードには現在の有効期限切れのタイムスタンプがあり、更新された従業員履歴レコードにはNULLが期限切れのタイムスタンプと最新のアクティブなタイムスタンプが付きます。新しい更新された従業員履歴レコードは、更新された関連従業員レコードとも一致します。

+0

回答のための努力を感謝します。 – DinaMike

関連する問題