EntityManager.find не может найти сущность, но использование Criteria API делает - PullRequest
7 голосов
/ 08 июля 2010

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

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

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

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

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

Вот соответствующие части сущности User:

@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 ]

11 голосов
/ 09 июля 2010

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

3 голосов
/ 12 февраля 2014

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

3 голосов
/ 08 июля 2010

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

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

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

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

1 голос
/ 08 июля 2010

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

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

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

0 голосов
/ 08 июля 2010

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

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

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

0 голосов
/ 08 июля 2010

Одной из причин может быть то, что поле "id" не было правильно помечено как идентификатор для объекта User.

...