我們使用JPA 1.0和JAX-WS進行最簡單的CRUD任務。
假設我們有一個實體Person。JPA合併只讀字段
@Entity
public class Person
{
@Id
private String email;
@OneToOne(fetch = FetchType.LAZY)
@JoinColumn(insertable = false, updatable = false)
private ReadOnly readOnly;
@Column
private String name;
@XmlElement
public String getEmail()
{
return email;
}
public void setEmail(String email)
{
this.email = email;
}
@XmlElement
public Long getReadOnlyValue()
{
return readOnly.getValue();
}
// more get and set methods
}
這裏是場景。 客戶端使Web服務請求創建人。在服務器端,一切都很簡單。 它確實按預期工作。
@Stateless
@WebService
public class PersonService
{
@PersistenceContext(name = "unit-name")
private EntityManager entityManager;
public Person create(Person person)
{
entityManager.persist(person);
return person;
}
}
現在客戶端嘗試更新的人,這就是,對我來說,JPA顯示其不一致。
public Person update(Person person)
{
Person existingPerson = entityManager.find(Person.class, person.getEmail());
// some logic with existingPerson
// ...
// At this point existingPerson.readOnly is not null and it can't be null
// due to the database.
// The field is not updatable.
// Person object has readOnly field equal to null as it was not passed
// via SOAP request.
// And now we do merge.
entityManager.merge(person);
// At this point existingPerson.getReadOnlyValue()
// will throw NullPointerException.
// And it throws during marshalling.
// It is because now existingPerson.readOnly == person.readOnly and thus null.
// But it won't affect database anyhow because of (updatable = false)
return existingPerson;
}
爲了避免這個問題,我需要暴露設置爲readOnly對象,並在合併之前做這樣的事情。
Person existingPerson = entityManager.find(Person.class, person.getEmail());
person.setReadOnlyObject(existingPerson.getReadOnlyObject()); // Arghhh!
我的問題:
- 它是一個功能或者只是 不一致?
- 你(或你會) 你如何處理這種情況?請 不建議我使用DTO。
你有沒有找到一個更好的替代方案來輕鬆使用不可更新的字段? – Kevin 2015-07-31 02:09:03