EntityManager.find не удается найти объект, но использование Criteria API позволяет
-
13-09-2020 - |
Вопрос
Я столкнулся с довольно странным случаем в Java EE 6, где с помощью JPA EntityManager find
метод вместе с основным идентификатором объекта возвращает null, но использование 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
возвращает null, но критерии находят пользователя?Я попробовал эти два альтернативных метода в одном и том же месте программы.
Вот соответствующие части объекта 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;
}
...
}
Решение
Я выяснил проблему.Это было связано с полем в базе данных, будучи генеракодицетагкодом, где ему не должно быть разрешено.Это было связано со мной редактирование его вручную.После того, как я добавил значение для этого поля, проблема ушла.
Другие советы
Какой поставщик вы используете?
Где вы выполняете эту находку, в или вне транзакции?Вы промываете и очищаете их до поиска?
Использование ECLIPSELINK в качестве провайдера, а моя собственная подобная модель, я не могу воспроизвести это.
Предполагая, что ваш провайдер может войти в систему SQL, вы видите SQL, иду на DB на Find?Как выглядит SQL, и он выполняется правильно в SQL Plus etc ...
Я подтверждаю это решение.То же самое случилось и со мной.У меня были столбцы , помеченные как NOT NULL
, затем во время тестирования в моем приложении я отключил ограничение в базе данных для двух столбцов (внешних ключей), однако не изменил (optional = false
) атрибут @ManyToOne
отношение в моем классе сущностей.После удаления атрибута, чтобы модель соответствовала базе данных, все начало работать нормально.Странно, что среда не выдает какого-либо предупреждения или исключения.
Дважды проверьте, что вы передаете генеракодицетагкод в следующем фрагменте:
// Always returns null, even for records I know for sure are in there.
user = em.find(User.class, userId);
.
Если это не поможет, активируйте регистрацию SQL, чтобы увидеть, что происходит и сравнить поведение в обоих случаях.
Одна из причин может быть, что поле «ID» не было правильно помечено как идентификатор для объекта пользователя.
В качестве здравоохранения проверьте ваш код, находящее время, прежде чем выполнить поиск, чтобы самостоятельно выполнить ручное запрос на базе данных, чтобы убедиться, что соответствующая запись пользователя присутствует с ожидаемым идентификатором.
Если это не в базе данных, убедитесь, что менеджер объекта был покрасен, или текущая транзакция была совершена.
Например, если вы используете Hibernate в качестве провайдера, возможно, что объект «сохраняется» просто в кэше, и изменения на самом деле не были нажаты в базу данных.Соответственно, критерии, проходящиеся через реализацию Hibernate, получат объект, но INTER Manager Find не сможет найти объект.