Я встретился с довольно нечетным случаем в Java EE 6 где с помощью EntityManager JPA find
метод наряду с основным идентификационным пустым указателем возвратов объекта, но использование Критериев 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
пустой указатель возвратов, но Критерии находят Пользователя? Я попробовал эти два альтернативных метода в том же самом месте в программе.
Вот соответствующие части Пользовательского объекта:
@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;
}
...
}
Я выяснил проблему. Это было связано с тем, что поле в базе данных было null
, где оно не должно было быть разрешено. Это произошло из-за того, что я отредактировал его вручную. После того как я добавил значение в это поле, проблема исчезла.
Какого провайдера вы используете?
Где вы выполняете этот поиск, в транзакции или вне ее? Выполняете ли вы промывку и очистку EM перед поиском?
Используя EclipseLink в качестве провайдера и свою собственную похожую модель, я не могу воспроизвести это.
Предполагая, что ваш провайдер может регистрировать SQL, видите ли вы SQL, идущий в БД при поиске? Как выглядит SQL, правильно ли он выполняется в SQL Plus и т.д...
Дважды проверьте, что вы передаете Long
в следующем фрагменте:
// Always returns null, even for records I know for sure are in there.
user = em.find(User.class, userId);
Если это не поможет, включите логирование SQL, чтобы посмотреть, что происходит, и сравните поведение в обоих случаях.
Одна из причин может заключаться в том, что поле «id» не было правильно помечено как идентификатор для объекта «Пользователь».
В качестве проверки работоспособности отладьте свой код, выделив время перед выполнением поиска для запуска ручного запроса в базе данных самостоятельно, чтобы убедиться, что присутствует соответствующая запись пользователя с ожидаемым идентификатором.
Если его нет в базе данных, убедитесь, что диспетчер сущностей был сброшен или текущая транзакция была зафиксирована.
Например, если вы используете Hibernate в качестве провайдера, возможно, что объект «сохраняется» просто в кеше, и изменения фактически не были отправлены в базу данных. Соответственно, критерии, проходящие через реализацию Hibernate, будут извлекать объект, но поиск диспетчера сущностей не сможет найти объект.