2017-02-03 19 views
2

JPA/HibernateでSpringBootを使用していますので、監査を追加したいと思います。updatable = falseのエンティティを更新すると、フィールドがNULLに設定されます

私は次のように抽象的実体を作成しました:

@CreatedDate 
@NotNull 
@Column(columnDefinition = "DATETIME(3)", updatable = false) 
private ZonedDateTime createdDate; 

@LastModifiedDate 
@Column(columnDefinition = "DATETIME(3)") 
private ZonedDateTime lastModifiedDate; 

アプリケーション

私は実体上の簡単なCRUDとRESTfulなAPIを研究開発をしています。 マイリソース(コントローラ)

問題を作成し、更新するためのJPAリポジトリに保存()メソッドを使用している:

私はそれを更新するために、エンティティにrepository.save()を呼んでいるときは、 "createdDate"は無視されます(これは正常ですが)。メソッドによって返されるエンティティは、 "createdDate"がnullに設定されています。

エンティティはキャッシュに置かれ、次のgetはcreatedDateの値もnullになります。

フィールドcreatedDateの変更とJpaCrudRepositoryの変更を許可せずにエンティティを更新するにはどうすればよいですか?

更新

リポジトリの定義:

public interface ModelRepository extends JpaRepository<Model, Long> { 

RESTコントローラー:UPDを

:エンドポイントで返さ

public ResponseEntity<Model> createModel(@RequestBody Model model) throws URISyntaxException { 
     Model result = modelRepository.save(model); 
     return ResponseEntity.created(new URI("/api/v1/models/" + result.getId())) 
      .body(result); 
} 

JSONが含まれている "ヌルCreatedDateに"

@Override 
    public Model save(Model model) { 
     Model result = modelRepository.save(model); 
     return result; 
    } 

    @Override 
    public Model update(Long id, Model model) { 
     Model existingModel = modelRepository.findOne(id); 
     if (existingModel == null) { 
      return null; 
     } 
     // Non updatable fields 
     model.setId(id); 
     model.setCreatedDate(existingModel.getCreatedDate()); 
     Model result = modelRepository.save(model); 
     return result; 
} 

は、この作業を行うには、私も持っていることから、結果を防ぐためにCreatedDateにフィールドから「更新可能な= false」を削除している:私はこのようなサービスを作成してこの問題を解決するには

2を食べました保存後の日付はnullです。

後で手動で処理する必要がある場合は、「updatable = false」という目的を理解できません。

+0

エンティティを保存するコードを表示できますか? – Patrick

答えて

0

ただちにHibernateを考えると、updatable=falseをマッピングに指定するのは完全に合法ですが、明らかに、Hibernateが挿入時にどの値を配置するかを知るために値を初期化する必要があります。

あなた自身で値を設定することで解決できるのは、厳密にHibernateのユーザーが行う必要があることです。

あなたのモデルが@CreatedDate注釈を使用していることがわかりました。私の簡単なグーグルでは、Spring Dataが公開しているもので、Hibernateとは何の関係もありません。それは私には何かがここで適切に構成されていないかもしれないことを意味します。

私はこれをSpringデータから使用したことはありませんが、別の投稿hereを見つけることができます。おそらく、あなたの設定がどこでオフになっているのか、そしてあなたが意図したように@CreatedDate注釈がフィールドを初期化していない理由を強調するのに役立ちます。

UPDATEあなたがそのようなあなたのupdate方法の場合、既存のエンティティの上に適用する必要がある状態で、外部電源を供給しますが、あなたが最初のエンティティを取得し、オーバーレイする必要がある状況で

あなたそれに応じて入力します。

// Some controller or business method 
public Object updateModel(Model input) { 
    final Model model = modelRepository.findOne(input.getId()); 
    if (model != null) { 
    // replicate business case fields 
    // sometimes this can be done using frameworks like ObjectMapper, etc. 
    // this is just a simple case. 
    model.setField1(input.getField1()); 
    model.setField2(input.getField2()); 
    return modelRepository.update(model); 
    } 
    throw new UnknownObjectException("No Model found with id: " + input.getId()); 
} 

希望します。

+0

@CreatedDateは私が理解しているところからうまく機能しています。 完全に作成されたエンティティ(取得されていない)と更新可能なfalseをマージしたもので、元の値を更新(DBから選択)していません。 私はなぜそれが行われていないのか理解できますが、私は本当にここで最善のアプローチであり、人々が何をしているのかは分かりません。 オブジェクトを取得し、更新不可能なフィールドを除くすべてのフィールドを更新しますか?またはオブジェクトを取得して、新しいオブジェクトの更新不可能なフィールドを(私の例のように)強制しますか?または、最後に、保存した後、entityManagerを介してエンティティを再取得(リフレッシュ)しますか? –

+0

あなたの投稿は 'save'と' update'ではなく、私の混乱を呼んでいました。私は私の答えを更新します。 – Naros

+0

JpaRepositoryには「保存」メソッドしかありません。そのため、私はsave()を使用していました。 しかし、これを実行することで、問題が同じであれば、更新可能= falseを使用することはできません。 updatableがfalseに設定されている場合、フィールドはnullになります。フィールドを更新したくないという理由だけで、すべてのエンティティの更新メソッドと完全なマッピングを行う必要はありません。どのようにして簡単なことが監査と読み取り専用の作成日として複雑になるのでしょうか? –

0

私は、エンティティマネージャをフラッシュしクリアしてデータを再選択することで、この問題を回避することができました。

entityManager.flush(); entityManager.clear();

0

@CreatedDate(org.springframework.data.annotation.CreatedDate)が間違った注釈ですか?私の小さな春ブートJPA/HibernateはCRUDサーバは、作成日時の欄に注釈@CreationTimestamp(org.hibernate.annotations.CreationTimestamp)を使用しています。

@CreationTimestamp 
@Column(name = "CREATED_DATE", nullable = false, updatable = false, columnDefinition = "TIMESTAMP") 
private Date created; 

要求をヌル作成日で到着。 repo.save()メソッドを呼び出すと、魔法が発生し、結果のドメインオブジェクトにはnull以外の作成日があります。私は、エンティティマネージャー、ノーフラッシュ、ノーダラをしていません。

カラムに「updatable = false」の注釈があっても、既存のエンティティで作成された日付の値を変更してrepo.save()メソッドを呼び出すと、その変更は不満なく続きます。それは私を驚かせた。

関連する問題