2014-10-07 108 views
0

當我將Java EE應用程序部署到Glassfish時,我有一個非常好奇的問題。我有一個Eclipse EAR項目,它引用了一個Web項目(包含一個Servlet)和一個EJB項目(擁有一個EJB)和一個JPA項目(擁有一個@Entity)。在我的servlet我調用EJB,又執行下面的查詢:JPA實體類實例

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

我已經調試上述休眠類,即MetamodelImpl,並且我看到它已經註冊了我的實體(在實體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。

My 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; 

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

JPA有時是一個爛攤子。1.聲明的實體persistence.xml,或者2.確保它們和ejb – maress 2014-10-07 15:04:13

+0

在同一個jar裏謝謝,我也試過了,t無法在EJB項目中創建最簡單的實體,只需一個空的公共構造函數就可以創建一個id和一個getter/setter。然後在EJB代碼中,我檢查這個類,它與MetamodelImpl中註冊的類不同。在我用MyEntity.class引用它的時候,我在構造函數中定義的類以及運行時的getters和setter類沒有任何構造函數或方法,這沒有任何意義。這些聲明哪裏去了? – Raoul 2014-10-08 06:53:15

回答

0

你檢查了你的persistence.xml嗎?實體類是否明確聲明或exclude-unlisted-classes屬性設置爲false?

或者也許在類路徑中的實體類的多個定義(什麼可以解釋在元模型中註冊但未解決的實例的存在)?

+0

謝謝,但我已經試過了也: 'code' <持久性單元名稱= 「試JPA」> org.hibernate.jpa.HibernatePersistenceProvider MySQLResource net。 .ejb.MyEntity <排除,非流通類>真 'code' 是的,有在部署的應用程序只有一個myEntity所的類文件。我也認爲會有兩個,但事實並非如此。我查看了所有文件夾和罐子。它只是沒有意義,有同一類的兩個類實例。 – Raoul 2014-10-08 06:55:14

+0

您是否試圖顯式調用[Metamodel#entity(...)](http://docs.oracle.com/javaee/6/api/javax/persistence/metamodel/Metamodel.html#entity(java.lang .Class))]方法與你的類對象,以檢查Hibernate解決它的方式? – bdulac 2014-10-08 08:21:55

+0

我試過了,但它是相同的結果。 MyEntity不是一個實體。 MetamodelImpl.entity(...)只是在地圖中查找實體,並將MyEntity類用作關鍵字。然而,正如我上面提到的,實體註冊MetamodelImpl(在實體映射)是正確的(它有一個構造函數和公共方法),但如果我在調試器中檢查MyEntity.class,我看到它是一個「不同的」MyEntity類沒有構造函數,也沒有公共方法。就好像Hibernate已經註冊了正確的實體,但是在運行時(在EJB中),MyEntity.class是一個沒有方法的錯誤類!奇怪! – Raoul 2014-10-08 08:51:34

1

解決!這link幫助,特別是關於persistence.xml的評論。

我仍然不明白如何爲一個類創建兩個不同的Class實例,但如果您有單獨的EJB,WEB和JPA項目,它似乎只是一種特殊的方式,如下所示:

  1. 不添加的persistence.xml到JPA項目(或項目包含@Entity實例 ),而是將其添加到Web 項目(我把它添加到的src/META-INF,雖然有其他 的可能性,我還沒有測試)。

  2. 在persistence.xml中,您必須提及類「fqn-of-Class」即EVEN的類 ,儘管這些類應由註釋拾取。設置 「排除-非流通類(真正的)是不相關的 。它與沒有這個。

這樣做就意味着查詢現在沒有惱人拋出:IllegalArgumentException說明實體是作品」不是一個實體」

測試在JBoss EAP 6.3,Java 7中,JPA 2.1,EJB 3.1,但我相信它也將在Glassfish與EJB 3.2的工作。