だからここに私の問題の簡単な説明があります。私は 2 つのテーブルを持っています。最初に個人の詳細が含まれています。
@Entity
@Converter(name = "uuidConverter", converterClass = UUIDConverter.class)
public class Person {
private UUID mId;
private String mLogin;
@Id
@UuidGenerator(name = "uuid")
@GeneratedValue(generator = "uuid")
@Column(name = "id", nullable = false)
@Convert("uuidConverter")
public UUID getId() {
return mId;
}
@Column(name = "login", nullable = false)
public String getLogin() {
return mLogin;
}
public Person setId(UUID id) {
mId = id;
return this;
}
public Person setLogin(String login) {
mLogin = login;
return this;
}
}
2 番目のテーブルには、複数の個人設定が含まれています。
@IdClass(PersonPreference.Pk.class)
@Table(name = "person_preference")
@Entity
@Converter(name = "uuidConverter", converterClass = UUIDConverter.class)
public class PersonPreference {
private Person mPerson;
private String mComponentUid;
private String mComponentProperties;
@SuppressWarnings("UnusedDeclaration")
static class Pk implements Serializable {
private String mComponentUid;
private UUID mPerson;
public String getComponentUid() {
return mComponentUid;
}
public void setComponentUid(String componentUid) {
mComponentUid = componentUid;
}
@Convert("uuidConverter")
public UUID getPerson() {
return mPerson;
}
public void setPerson(UUID person) {
mPerson = person;
}
@Override
public int hashCode() {
return Objects.hashCode(mComponentUid, mPerson);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Pk other = (Pk) obj;
return Objects.equal(this.mComponentUid, other.mComponentUid) && Objects.equal(this.mPerson, other.mPerson);
}
}
@Id
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "person_id", nullable = false)
public Person getPerson() {
return mPerson;
}
@Id
@Column(name = "component_uid", nullable = false)
public String getComponentUid() {
return mComponentUid;
}
@Column(name = "component_properties", nullable = false)
public String getComponentProperties() {
return mComponentProperties;
}
public PersonPreference setPerson(Person person) {
mPerson = person;
return this;
}
public PersonPreference setComponentUid(String componentUid) {
mComponentUid = componentUid;
return this;
}
public PersonPreference setComponentProperties(String componentProperties) {
mComponentProperties = componentProperties;
return this;
}
@Override
public int hashCode() {
return Objects.hashCode(mPerson, mComponentUid, mComponentProperties);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final PersonPreference other = (PersonPreference) obj;
return Objects.equal(this.mPerson, other.mPerson)
&& Objects.equal(this.mComponentUid, other.mComponentUid)
&& Objects.equal(this.mComponentProperties, other.mComponentProperties);
}
}
簡単なテストも書きました:
Person person = new Person()
.setLogin("PersonPreferencePersistenceTestLogin");
PersonPreference personPreference = new PersonPreference()
.setPerson(person)
.setComponentUid("4028808C3AA49ABB013AA49ABB2B0000")
.setComponentProperties("{123}");
mPersonPreferenceService.save(personPreference);
Optional<PersonPreference> newPersonPreference = mPersonPreferenceService.getByPersonAndComponentUid(
person,
"4028808C3AA49ABB013AA49ABB2B0000"
);
Assert.assertEquals(personPreference.getComponentProperties(), newPersonPreference.get().getComponentProperties());
以前は JPA プロバイダーとして Hibernate を使用していましたが、そのコードは完全に機能します。残念ながら、JPA プロバイダーを Eclipselink に切り替えた後、カスケード永続化が正しく機能しなくなりました。ログから私が見つけた:
--INSERT INTO PERSON (id, login) VALUES (?, ?)
bind => [f2ce518c-8f37-4fac-bf5b-c8225d228b28, PersonPreferencePersistenceTestLogin]
--INSERT INTO person_preference (component_uid, component_properties, person_id) VALUES (?, ?, ?)
bind => [4028808C3AA49ABB013AA49ABB2B0000, {123}, f2ce518c-8f37-4fac-bf5b-c8225d228b28]
--SELECT component_uid, component_properties, person_id FROM person_preference WHERE ((person_id = ?) AND (component_uid = ?))
bind => [null, 4028808C3AA49ABB013AA49ABB2B0000]
しかし、 person.getId() は null 値を返します。どうしてか分かりません?他のマッピングはカスケード永続化で正常に動作しますが、Eclipselink では失敗します。