JPA实体类实例 [英] JPA Entity Class Instances

查看:189
本文介绍了JPA实体类实例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我将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);
最终根<国家> root = criteriaQuery.from(Country.class);

在上述代码的第三行,我收到一个例外:

 严重:java.lang.IllegalArgumentException:不是实体:class< package> .entity.Country 
在org.hibernate.jpa.internal。 metamodel.MetamodelImpl.entity(MetamodelImpl.java:203)
在org.hibernate.jpa.criteria.QueryStructure.from(QueryStructure.java:139)
在org.hibernate.jpa.criteria.CriteriaQueryImpl。 from(CriteriaQueryImpl.java:173)
at< package> .CountrySessionBean.getCountries(CountrySessionBean.java:35)
...

我已经调试了上述Hibernate类,即MetamodelImpl,我看到它已经注册了我的Entity(在实体Map中)。类名与我要求的类完全相同(网...国家)。但是,这个类与我在servlet中的以下代码不同:

  final Class<?> countryClass = Country.class; 

我说这是不同的,因为'declaredConstructors'字段和'declaredPublicMethods'是不同的。在servlet中,这些字段为null(奇怪的是,请参阅Country.java以下!),但在MetamodelImpl类中,这些字段包含了在实体中定义的构造函数和公共方法。因为MetamodelImpl使用Map,所以它不能在注册的类中找到实体,因为class是不同的(即存储在内存中的不同位置),当然它会引发IllegalArgumentException。我已经检查了Glassfish部署的内容是否只包含一个Country.class文件,所以这真的令人困惑,为什么同一个类有两个不同的Class实例,并且它们彼此不同!



任何人都有任何想法?



参考:Hibernate v4.3.6,EJB v3.2,Glassfish v4.1,JPA v2。 1。



我的Country.java实体在下面。如你所见,它包含一个构造函数和公共方法,所以令我惊讶的是,在servlet中,该类没有declaredConstructors或declaredPublicMethods。这是怎么做的?

  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; $ c
$ b @ \\\(\\)] {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的评论。



我仍然不明白你如何可以为一个类有两个不同的Class实例,但它确实似乎如果您有单独的EJB,WEB和JPA项目,那就是一个特殊的方法,如下所示:


  1. 添加持久性.xml不是JPA项目(或项目
    包含@Entity实例),而是将其添加到web
    项目(我添加到src / META-INF,虽然还有其他
    可能性,我还没有测试)。


  2. 在persistence.xml中,你必须提到
    fqn -of-Class,即使这些类应该被注释。设置
    exclude-unlisted-classes(true)不是
    相关,它可以和没有这个。


这样做意味着查询现在工作没有烦人的IllegalArgumentException说明实体是不是一个实体。



在JBoss EAP 6.3,Java 7,JPA 2.1,EJB 3.1,尽管我认为它也可以在Glassfish上使用EJB 3.2。


I have a very curious problem when I deploy my Java EE application to Glassfish. I have an Eclipse EAR project that references a web project (containing a servlet), and an EJB project (that has one EJB) and a JPA Project (that has one @Entity). In my servlet I call the EJB, which in turn performs the following query:

final CriteriaBuilder criteriaBuilder = this.entityManager.getCriteriaBuilder();
final CriteriaQuery<Country> criteriaQuery = criteriaBuilder.createQuery(Country.class);
final Root<Country> root = criteriaQuery.from(Country.class);

On the third line of the above code I get an exception:

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)
...

I have debugged the above mentioned Hibernate class, namely MetamodelImpl, and I see that it has registered my Entity (in the entities Map). The class name is exactly the same as the one I'm asking for (net...Country). However, this class is different from the following code which I place in the servlet:

final Class<?> countryClass = Country.class;

I say it is "different", because the 'declaredConstructors' field and the 'declaredPublicMethods' are different. In the servlet these fields are 'null' (strange, see Country.java below!), but in the MetamodelImpl class these fields contain the constructors and public methods that I have defined in the entity. Because MetamodelImpl uses a Map, it cannot find the entity amongst the registered classes because the "class" is different (i.e. stored at a different location in memory), and of course it throws the IllegalArgumentException. I have checked that what is deployed to Glassfish only ever contains one Country.class file, so this is really confusing why there are two different Class instances of the same class, and that they are different from each other!

Anyone have any idea?

For reference: Hibernate v4.3.6, EJB v3.2, Glassfish v4.1, JPA v2.1.

My Country.java entity is below. As you can see, it contains a constructor and public methods, so it astonishes me that in the servlet the class does NOT have 'declaredConstructors' or 'declaredPublicMethods'. How can this be?

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();
}
}

解决方案

Solved! This link helped, particularly the comment about the persistence.xml.

I still don't understand how you could ever have two different Class instances for one class, but it indeed seems just to be a particular way if you have separate EJB, WEB and JPA projects, which is as follows:

  1. Add the persistence.xml NOT to the JPA project (or the project containing the @Entity instances), but rather add it to the web project (I added it to src/META-INF, although there's other possibilities, which I haven't yet tested).

  2. In the persistence.xml, you have to mention the classes with "fqn-of-Class", EVEN though the classes should be picked up by the annotation. The setting "exclude-unlisted-classes (true) is not relevant. It works with and without this.

Doing this means the query now works without the annoying IllegalArgumentException stating the Entity is "not an Entity".

Tested on JBoss EAP 6.3, Java 7, JPA 2.1, EJB 3.1, although I assume it will also work on Glassfish with EJB 3.2.

这篇关于JPA实体类实例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆