当我将Java EE应用程序部署到Glassfish时,我有一个非常奇怪的问题。我有一个Eclipse EAR项目,它引用了一个Web项目(包含一个servlet),一个EJB项目(有一个EJB)和一个JPA项目(有一个@Entity)。在我的 servlet 中,我调用 EJB,它又执行以下查询:
final CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
final CriteriaQuery<Country> criteriaQuery = criteriaBuilder.createQuery(Country.class);
final Root<Country> root = criteriaQuery.from(Country.class);
在上面代码的第三行,我得到了一个异常:
Severe: java.lang.IllegalArgumentException: Not an entity: class <package>.entity.Country
at org.hibernate.jpa.internal.metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)
at org.hibernate.jpa.criteria.QueryStructure.from(QueryStructure.java:139)
at org.hibernate.jpa.criteria.CriteriaQueryImpl.from(CriteriaQueryImpl.java:173)
at <package>.CountrySessionBean.getCountries(CountrySessionBean.java:35)
...
我已经调试了上面提到的Hibernate类,即MetamodelImpl,我看到它已经注册了我的实体(在实体Map中)。类名与我要求的类名完全相同(net... Country)。但是,这个类与我在servlet中放置的以下代码不同:
final Class<?> countryClass = Country.class;
我说它是“不同的”,因为“声明的构造函数”字段和“声明的公共方法”是不同的。在 servlet 中,这些字段是“null”(奇怪,请参阅下面的 Country.java!),但在 MetamodelImpl 类中,这些字段包含我在实体中定义的构造函数和公共方法。因为 MetamodelImpl 使用 Map,所以它无法在注册的类中找到实体,因为“类”是不同的(即存储在内存中的不同位置),当然它会抛出 IllegalArgumentException。我已经检查过部署到Glassfish的内容只包含一个国家.class文件,所以这真的令人困惑,为什么同一类有两个不同的类实例,并且它们彼此不同!
有人知道吗?
供参考:Hibernate v4.3.6、EJB v3.2、Glassfish v4.1、JPA v2.1。
我的Country.java实体在下面。正如您所看到的,它包含一个构造函数和公共方法,所以令我惊讶的是,在servlet中,类没有“声明的构造函数”或“声明的公共方法”。这是怎么回事?
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
@Entity
public class Country implements Serializable {
private static final long serialVersionUID = -3119088680575312729L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;
@Pattern(regexp = ".[\\p{L} \\.\\[\\]\\?\\-\\(\\)]{1,30}+")
@NotNull
private String name;
public Country() {
super();
}
public String getName() {
return this.name;
}
public void setName(final String name) {
this.name = name;
}
public Integer getId() {
return this.id;
}
public void setId(final Integer id) {
this.id = id;
}
@Override
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append(this.name);
builder.append(" (");
builder.append(this.id);
builder.append(")");
return builder.toString();
}
}
检查过persistence.xml了吗?是显式声明实体类还是将排除未列出类属性设置为false?
或者类路径中实体类的多个定义(什么可以解释在元模型中注册但未解析的实例的存在)?
解决!这个链接有所帮助,特别是关于持久性.xml的评论。
我仍然不明白一个类怎么可能有两个不同的类实例,但如果您有单独的EJB、WEB和JPA项目,这似乎是一种特殊的方式,如下所示:
>
不将persistence.xml添加到JPA项目(或包含@Entity实例的项目),而是将其添加到Web项目(我将其添加到src/META-INF,尽管还有其他可能性,我还没有测试)。
在persistence.xml中,您必须提到带有“fqn-of-Class”的类,即使这些类应该由注释选择。设置“排除-未列出-类别(true)”不相关。不管有没有这个都可以。
这样做意味着查询现在可以正常工作,而无需烦人的 IllegalArgumentException 声明实体“不是实体”。
在JBoss EAP 6.3、Java 7、JPA 2.1和EJB3.1上进行了测试,尽管我认为它也可以在Glassfish和EJB2.2上运行。
我有一个JPA项目(Eclipse Link),工作正常,但我想持久化一个不是实体的类(或在相同的持久化上下文中不是实体),目前我持久化引用id,然后我执行调用以检索对象。我需要知道什么是最好的方式做到这一点…我不希望在bean中添加代码作为侦听器事件,因为我希望有一个干净的bean(构造、属性、不带注释的setter和getter), 我的想法是扩展PersistenceContext(但是,我
问题内容: 我有一个JPA实体已经存在于数据库中。 我想要一个副本(具有不同的ID),并修改了某些字段。 最简单的方法是什么?喜欢: 将其设置为字段并坚持下去会起作用吗? 我是否需要为实体创建一个克隆方法(复制以外的所有字段)? 还有其他方法(例如使用克隆框架)吗? 问题答案: 使用。它使bean不再链接到EntityManager。然后将ID设置为新ID(如果为自动,则为null),更改所需的字
主要内容:JPA实体删除示例要从数据库中删除记录,可以使用接口提供方法。方法使用主键来删除特定的记录。 JPA实体删除示例 在这里,我们将演示如何根据主键删除指定学生的信息。 完整的项目代码如下所示 - 这个例子包含以下步骤 - 第1步: 在包下创建一个名为的实体类,它包含属性:,和。 文件:StudentEntity.java 的代码如下 - 第2步: 将实体类和其他数据库配置映射到文件中。 文件:persistence.
主要内容:JPA实体更新示例JPA允许我们通过更新实体来更改数据库中的记录。 JPA实体更新示例 在这里,我们将演示如何根据主键更新学生的年龄。 完整的项目代码如下所示 - 这个例子包含以下步骤 - 第1步: 在包下创建一个名为的实体类,它包含属性:,和。 文件:StudentEntity.java 的代码如下 - 第2步: 将实体类和其他数据库配置映射到文件中。 文件:persistence.xml 的代码如下 - 在包下
主要内容:JPA实体查找示例要找到一个实体,接口提供了方法,该方法根据主键搜索一个元素。 JPA实体查找示例 在这里,我们将搜索指定的记录并在控制台输出它的值。 完整的项目代码如下所示 - 这个例子包含以下步骤 - 第1步: 在包下创建一个名为的实体类,它包含属性:,和。 文件:StudentEntity.java 的代码如下 - 第2步: 将实体类和其他数据库配置映射到文件中。 文件:persistence.xml 的代码
主要内容:JPA实体插入示例在JPA中,我们可以通过实体轻松地将数据插入到数据库中。 提供方法来插入数据记录。 JPA实体插入示例 在这里,我们将演示如何使用实现插入学生的记录。 创建一个JPA项目,其项目目录结构如下所示 - 这个例子包含以下步骤 - 第1步: 在包下创建一个名为StudentEntity.java的实体类,这个类包含以下几个属性:, 和 。 文件:StudentEntity.java 的代码如下 - 第2