我在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;
}
...
}
答案 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将无法找到该对象。