Через EntityManager.найти не удается найти объект, но с помощью API критериев

я столкнулся с довольно странным случаем в Java EE 6, где использование JPA EntityManager find метод вместе с основным идентификатором сущности возвращает null, но использование API критериев для выбора всех сущностей с этим идентификатором работает нормально.

вот код, который я использую для find:

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

...и вот код, который я использую с 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();

любая идея, почему find возвращает null, но критерии находят пользователя? Я попробовал эти два варианта методы в одном и том же месте в программе.

вот соответствующие части сущности пользователя:

@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;
    }
    ...
}

6 ответов


Я понял, проблема. Это было связано с полем в базе данных null где это не должно было быть разрешено. Это благодаря тому, что я редактировал ее вручную. После того, как я добавил значение в это поле, проблема исчезла.


какой провайдер вы используете?

где вы выполняете эту находку, в или из транзакции? Вы смываете и очищаете EM до Находки?

используя EclipseLink в качестве поставщика и мою собственную аналогичную модель, я не могу воспроизвести это.

предполагая, что ваш провайдер может регистрировать SQL, вы видите, что SQL собирается в БД при поиске? Как выглядит SQL, и правильно ли он выполняется в SQL Plus и т. д...


Я подтверждаю решение. То же самое произошло и со мной. У меня были collumns помечены как NOT NULL, затем во время теста в моем приложении я отключил ограничение в базе данных для двух collumns (внешние ключи), однако не меняя (optional = false атрибутом)@ManyToOne отношения в моем классе сущностей. После удаления атрибута, чтобы модель соответствовала базе данных, все начало работать нормально. Странно, что окружающая среда не создает какого-либо предупреждения или исключения.


дважды проверьте, что вы передаете в Long в следующем фрагменте:

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

Если это не поможет, включите ведение журнала SQL, чтобы увидеть, что происходит и сравнить поведение в обоих случаях.


одной из причин может быть то, что поле " id " не было правильно помечено как id для сущности пользователя.


в качестве проверки здравомыслия отладьте свой код, потратив время перед выполнением find для запуска ручного запроса в базе данных самостоятельно, чтобы убедиться, что соответствующая запись Пользователя присутствует с идентификатором, который вы ожидаете.

если его нет в базе данных, убедитесь, что диспетчер сущностей был сброшен или текущая транзакция была зафиксирована.

например, если вы используете Hibernate в качестве поставщика, возможно, что объект "сохраняется" только в кэш и изменения фактически не были перенесены в базу данных. Соответственно, критерии, проходящие через реализацию Hibernate, будут извлекать объект, но поиск диспетчера сущностей не сможет найти объект.