まあ、質問がほとんどすべてを物語っています。JPARepository を使用してエンティティを更新するにはどうすればいいですか?
JPARepository にはsaveメソッドしかありませんが、実際には create か update かはわかりません。たとえば、3 つのフィールド (、) を持つ単純なオブジェクトをデータベース User に挿入するとしfirstname
ます。lastname
age
@Entity
public class User {
private String firstname;
private String lastname;
//Setters and getters for age omitted, but they are the same as with firstname and lastname.
private int age;
@Column
public String getFirstname() {
return firstname;
}
public void setFirstname(String firstname) {
this.firstname = firstname;
}
@Column
public String getLastname() {
return lastname;
}
public void setLastname(String lastname) {
this.lastname = lastname;
}
private long userId;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public long getUserId(){
return this.userId;
}
public void setUserId(long userId){
this.userId = userId;
}
}
次に、 を呼び出しますsave()
。これは、この時点では実際にはデータベースへの挿入です。
User user1 = new User();
user1.setFirstname("john"); user1.setLastname("dew");
user1.setAge(16);
userService.saveUser(user1);// This call is actually using the JPARepository: userRepository.save(user);
ここまでは順調です。今度は、このユーザーを更新して、年齢を変更したいと思います。この目的のために、QueryDSL または NamedQuery のいずれかのクエリを使用できます。ただし、spring-data-jpa と JPARepository だけを使用したい場合、挿入ではなく更新を行うことをどのように伝えればよいでしょうか。
具体的には、同じユーザー名と名を持つユーザーが実際には EQUAL であり、既存のエンティティが更新されるはずであることを spring-data-jpa に伝えるにはどうすればよいでしょうか。equals をオーバーライドしても、この問題は解決されませんでした。
ベストアンサー1
エンティティの ID は、その主キーによって定義されます。 と は主キーの一部ではないためfirstname
、lastname
が異なる を持つ場合、User
同じfirstname
とを持つ を同等として扱うように JPA に指示することはできません。lastname
userId
User
したがって、と で識別されるを更新する場合はfirstname
、クエリでlastname
それを見つけて、見つかったオブジェクトの適切なフィールドを変更する必要がありますUser
。これらの変更はトランザクションの終了時に自動的にデータベースにフラッシュされるため、これらの変更を明示的に保存するために何もする必要はありません。
編集:
JPA の全体的なセマンティクスについて詳しく説明する必要があるかもしれません。永続性 API の設計には、主に 2 つのアプローチがあります。
挿入/更新アプローチ。データベースを変更する必要がある場合は、永続性 API のメソッドを明示的に呼び出す必要があります。
insert
オブジェクトを挿入するか、update
オブジェクトの新しい状態をデータベースに保存するために呼び出します。作業単位アプローチ。この場合、永続ライブラリによって管理されるオブジェクトのセットがあります。これらのオブジェクトに加えたすべての変更は、作業単位の終了時 (つまり、通常は現在のトランザクションの終了時) に自動的にデータベースにフラッシュされます。データベースに新しいレコードを挿入する必要がある場合は、対応するオブジェクトを管理対象にします。管理対象オブジェクトは主キーによって識別されるため、定義済みの主キーが管理対象であるオブジェクトを作成すると、同じ ID のデータベース レコードに関連付けられ、このオブジェクトの状態がそのレコードに自動的に伝播されます。
JPA は後者のアプローチに従います。Spring save()
Data では JPA はプレーン JPA によってサポートされているmerge()
ため、エンティティは上記のように管理されますsave()
。つまり、定義済み ID を持つオブジェクトを呼び出すと、新しいレコードが挿入されるのではなく、対応するデータベース レコードが更新されます。また、save()
が呼び出されない理由も説明されますcreate()
。