Question

I've encountered a rather odd case in Java EE 6 where using the JPA EntityManager's find method along with an entity's primary id returns null, but using the Criteria API to select all entities with that id works fine.

Here is the code I'm using for find:

// Always returns null, even for records I know for sure are in there.
user = em.find(User.class, userId);

...and here's the code I'm using with the Criteria API:

CriteriaBuilder builder = em.getCriteriaBuilder();
CriteriaQuery<User> criteria = builder.createQuery(User.class);
Root<User> u = criteria.from(User.class);
TypedQuery<User> query = em.createQuery(
    criteria.select(u).where(builder.equal(u.get("id"), userId)));
user = query.getSingleResult();

Any idea why find returns null but Criteria finds the User? I tried these two alternate methods in the exact same spot in the program.

Here are the relevant portions of the User entity:

@Entity
@Table(name = "USERS")
@Access(AccessType.PROPERTY)
public class User implements Serializable {
    ...
    private Long id;
    ...
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_id_generator")
    @SequenceGenerator(name = "user_id_generator", sequenceName = "user_sequence", allocationSize = 1)
    @Column(name="id")
    public Long getId() {
        return this.id;
    }

    public void setId(Long id) {
        this.id = id;
    }
    ...
}
Was it helpful?

Solution

I figured out the problem. It was due to a field in the database being null where it should not have been permitted. This was due to me editing it by hand. After I added a value to that field, the problem went away.

OTHER TIPS

What provider are you using?

Where are you executing this find, in or out of a transaction? Are you flushing and clearing the EM prior to the find?

Using EclipseLink as a provider, and my own similar model, I am not able to reproduce this.

Assuming your provider can log SQL, are you seeing SQL going to the DB on the find? What does the SQL look like, and does it execute properly in SQL Plus etc...

I confirm the solution. The same thing happened to me. I had collumns marked as NOT NULL, then during test in my app I switched the limitation off in the database for two collumns (foreign keys), however not changing the (optional = false) attribute of @ManyToOne relationship in my entity class. After deleting the attribute, so the model was consistent with the database, everything started to work fine. Strange that the environment does not produce a warning or exception of some kind.

Double check that you are passing a Long in the following snippet:

// Always returns null, even for records I know for sure are in there.
user = em.find(User.class, userId);

If this doesn't help, activate SQL logging to see what is happening and compare the behavior in both cases.

One reason could be that the "id" field has not been correctly marked as the id for the User entity.

As a sanity check debug your code, taking the time before executing the find to run a manual query on the database yourself to ensure that an appropriate User record is present with the id you expect.

If it's not in the database, ensure that the entity manager has been flushed or the current transaction has been committed.

For instance, if you are using Hibernate as the provider, it is possible that the object is "persisted" merely in cache and the changes have not actually been pushed to the database. Accordingly, the criteria going through Hibernate's implementation will retrieve the object, but the entity manager find will not be able to locate the object.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top