加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

JPA合并只读字段

发布时间:2020-12-15 02:20:59 所属栏目:Java 来源:网络整理
导读:我们有最简单的CRUD任务,包括JPA 1.0和JAX-WS. 假设我们有一个实体Person. @Entitypublic class Person{ @Id private String email; @OneToOne(fetch = FetchType.LAZY) @JoinColumn(insertable = false,updatable = false) private ReadOnly readOnly; @Col
我们有最简单的CRUD任务,包括JPA 1.0和JAX-WS.
假设我们有一个实体Person.

@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对象公开set,并在合并之前执行类似的操作.

Person existingPerson = entityManager.find(Person.class,person.getEmail());
person.setReadOnlyObject(existingPerson.getReadOnlyObject()); // Arghhh!

我的问题:

>这是一个功能还是只是
不一致?
>你好吗?
你)处理这种情况?请
不建议我使用DTO.

解决方法

Is it a feature or just inconsistence?

我不知道,但我会说这是合并的预期行为.以下是在实体上调用merge时发生的情况:

>现有实体在持久化上下文中加载(如果尚未存在)
>将状态从对象复制到合并到已加载的实体
>对已加载实体所做的更改将在刷新时保存到数据库中
>返回加载的实体

这适用于简单的情况,但是如果你收到一个部分值对象(有些字段或关联设置为null)要合并,则不能正常工作:数据库中的空字段将被设置为null,这可能不是你想要的.

How do you (or would you) handle such situations? Please don’t advice me to use DTOs.

在这种情况下,您应该使用“手动合并”:使用find加载现有实体并通过复制新状态自行更新要更新的字段,让JPA检测更改并将其刷新到数据库.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读