7

我在 Java EE 6 中遇到了一个相当奇怪的情况,其中使用 JPA EntityManager 的find方法以及实体的主 ID 返回 null,但使用 Criteria API 选择具有该 ID 的所有实体工作正常。

这是我使用的代码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 但 Criteria 找到了用户吗?我在程序的完全相同的位置尝试了这两种替代方法。

以下是用户实体的相关部分:

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

6 回答 6

12

我解决了这个问题。这是由于数据库中的一个字段null不应该被允许。这是由于我手动编辑它。在我向该字段添加值后,问题就消失了。

于 2010-07-09T15:26:08.977 回答
3

您使用的是什么提供商?

你在哪里执行这个查找,在事务中还是在事务之外?您是否在发现之前冲洗并清除了 EM?

使用 EclipseLink 作为提供者,以及我自己的类似模型,我无法重现这一点。

假设您的提供程序可以记录 SQL,您是否看到 SQL 在查找时进入数据库?SQL 是什么样子的,它在 SQL Plus 等中是否正确执行......

于 2010-07-08T16:23:02.583 回答
3

我确认解决方案。这样的事情我也经历过。我将列标记为NOT NULL,然后在我的应用程序中进行测试期间,我关闭了数据库中两个列(外键)的限制,但没有更改实体类optional = false中关系的 ( ) 属性。@ManyToOne删除属性后,模型与数据库一致,一切开始正常。奇怪的是环境不会产生某种警告或异常。

于 2014-02-11T22:54:15.763 回答
1

仔细检查您是否Long在以下代码段中传递了 a:

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

如果这没有帮助,请激活 SQL 日志记录以查看正在发生的情况并比较两种情况下的行为。

于 2010-07-08T16:44:23.443 回答
0

一个原因可能是“id”字段未正确标记为用户实体的 id。

于 2010-07-08T15:48:32.390 回答
0

作为健全性检查调试您的代码,在执行 find 之前花点时间自己在数据库上运行手动查询,以确保存在具有您期望的 id 的适当用户记录。

如果它不在数据库中,请确保实体管理器已被刷新或当前事务已被提交。

例如,如果您使用 Hibernate 作为提供程序,则该对象可能只是“持久化”在缓存中,而更改实际上并未推送到数据库中。因此,通过 Hibernate 实现的标准将检索对象,但实体管理器 find 将无法定位该对象。

于 2010-07-08T16:42:09.833 回答