私はJPAとHibernateを使用してRecipe
オブジェクトのリストを追跡するSpringブートアプリケーションを持っています。私はJUnitの成功したテストを数少ないのですが、という名前の新しいテストをレシピに追加したいのです。Hibernate/EntityManagerを使用して一意の値を持つアイテムを更新する
それぞれRecipe
には一意の名前が必要です。
関連するコードスニペット:
コントローラー:
@RequestMapping(value = "/recipe/{recipeId}", method = RequestMethod.PATCH)
@Transactional
public ResponseEntity<String> renameRecipe(@PathVariable Long recipeId,
@RequestParam(name = "name") String newRecipeName) {
Recipe recipe = recipeManager.get(recipeId);
recipe.setName(newRecipeName);
recipeManager.save(recipe);
return new ResponseEntity<>(recipe.toJSONString(), HttpStatus.OK);
}
マネージャー:
@Repository
public class RecipeManager {
....
public Recipe save(Recipe recipe) {
System.out.println("save(): All recipes: " + getAll());
if (lookupByName(recipe.getName()) != null) {
throw new IllegalArgumentException("A recipe with this name already exists");
}
em.persist(recipe);
return recipe;
}
試験:
テストと問題はIllegalArgumentException
私は Hibernateのローカルキャッシュメカニズムであると信じるものをの結果として、スローされるということです。 をrenameRecipe()
メソッドで取得したRecipe
インスタンスに呼び出すと、実際にはローカルにキャッシュされたインスタンスのこのプロパティが変更されます。したがって、マネージャがsave()
のRecipe
に接続しようとすると、それはそのローカルキャッシュに与えられ、のはの属性変更がまだ反映されていないことがわかります
save()
方法では、直前のデュープチェックに、私のユニットテストを実行している、私は以下を参照してくださいライブ実行し、ポストマンを通じてテストするとき save(): All recipes: [{"name":"Pesto Pasta","id":1}]
これも発生します。
この問題を回避するにはどうすればよいですか?変更/永続化を実行する前に、のという名前を確認するビジネス層を導入する必要がありますか?
これは現在の問題を解決するものではありませんが、新しいものを防止します。* save()*メソッドが[EntityManager.persist()](http://docs.oracle.com/javaee/7 /api/javax/persistence/EntityManager.html#persist-java.lang.Object-)、新しい永続エンティティを作成しようとしますが、ほとんど確実に 'EntityExistsException'がスローされます。あなたが実際に存在するエンティティを更新することを望んでいる - > [JPAでエンティティを更新する最善の方法は何ですか](http://stackoverflow.com/questions/8307578/what-is-the-best-way-to -update-the-entity-in-jpa) – dic19