1

I have a Foo entity that's linked to a Status entity in a one-by-one relationship:

@Entity
@NamedQueries({
  @NamedQuery(name = "Foo.findById", query = "select o from Foo o where o.fooId = :fooId")
})
public class Foo implements Serializable {
    @Id
    @Column(name="FOO_ID")
    private Long fooId;

    @OneToOne(mappedBy = "foo")
    private Status status;

    public Long getFooId() {
        return fooId;
    }

    public void setFooId(Long fooId) {
        this.fooId = fooId;
    }

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }
}
@Entity
public class FooCurrentStatus implements Serializable {
    @Id
    private Long fooId;

    @OneToOne
    @JoinColumn(name = "FOO_ID")
    private Foo foo;

    public Long getFooId() {
        return fooId;
    }

    public void setFooId(Long fooId) {
        this.fooId = fooId;
    }

    public Foo getFoo() {
        return foo;
    }

    public void setFoo(Foo foo) {
        this.foo = foo;
        if (foo != null) {
            this.fooId = foo.getFooId();
        }
    }
}

I understand this is not completely wrong because when I fetch a Foo instance I automatically get its status.

From the application point of view, the status is read-only. It is managed elsewhere, by some other unrelated process that modifies the database information.

Unfortunately, the side effect is that whenever the status changes my managed entity gets outdated.

How can I instruct EJB/JPA to grab a fresh status?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Álvaro González
  • 142,137
  • 41
  • 261
  • 360

1 Answers1

4

refresh() on the EntityManager API is particularly used for such use-case, which can force refreshing the state of an already loaded instance from the database:

entityManager.refresh(foo.getStatus());
Ken Chan
  • 84,777
  • 26
  • 143
  • 172
  • I confirm it works. It just needed some tweaks when I create a new foo because `foo.getStatus()` is `null` (I solved it with a `Status.findById` named query). – Álvaro González Jun 04 '20 at 07:31
  • I spoke too soon. I get `EJB Exception: : java.lang.IllegalArgumentException: Can not refresh not managed object` in a seemingly random fashion :-? – Álvaro González Jun 04 '20 at 08:24
  • It is because the `entityManager` that is used to load the entity being refreshed is already closed , so the entity to be refreshed is not managed by JPA anymore and become detached. I believe you can make a detached entity to be managed by JPA by using `entityManager#merge().` You can also check if an object is managed by the JPA using `entityManger#contain()` first. – Ken Chan Jun 04 '20 at 08:43
  • I obviously have a problem in my app flow because the status is either `null`, managed or detached for reasons that aren't obvious to me. But the information in this answer and comments was all I needed to write a workaround. Thank you very much. – Álvaro González Jun 04 '20 at 09:11