EntityManager.find找不到实体,但使用Criteria API

时间:2010-07-08 15:28:47

标签: hibernate java-ee jpa-2.0 java-ee-6 criteria-api

我在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;
    }
    ...
}

6 个答案:

答案 0 :(得分:11)

我弄明白了这个问题。这是因为数据库中的字段为null,不应该允许它。这是因为我手工编辑。在我向该字段添加值后,问题就消失了。

答案 1 :(得分:3)

您使用的是哪家提供商?

您在哪里执行此查找,进出交易?您是否在寻找之前冲洗并清除EM?

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

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

答案 2 :(得分:3)

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

答案 3 :(得分:1)

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

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

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

作为一个完整性检查调试您的代码,在执行查找之前花时间自己在数据库上运行手动查询,以确保具有您期望的ID的相应用户记录。

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

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