2014-10-07 3 views
0

У меня возникла очень любопытная проблема при развертывании приложения Java EE в Glassfish. У меня есть проект Eclipse EAR, который ссылается на веб-проект (содержащий сервлет) и проект EJB (который имеет один EJB) и проект JPA (который имеет один @Entity). В моем сервлете я называю EJB, который, в свою очередь, выполняет следующий запрос:JPA Entity Class Instances

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, и я вижу, что он зарегистрировал мою Entity (в карте сущностей). Имя класса точно такое же, как и тот, который я прошу (сеть ... Страна). Тем не менее, этот класс отличается от следующего кода, который я отношу в сервлет:

final Class<?> countryClass = Country.class; 

Я говорю, что это «другой», потому что поле «declaredConstructors» и «declaredPublicMethods» различны. В сервлете эти поля «null» (странно, см. Раздел Country.java ниже!), Но в классе MetamodelImpl эти поля содержат конструкторы и общедоступные методы, которые я определил в сущности. Поскольку MetamodelImpl использует карту, он не может найти сущность среди зарегистрированных классов, потому что «класс» отличается (т. Е. Хранится в другом месте в памяти) и, конечно же, генерирует исключение IllegalArgumentException. Я проверил, что то, что развертывается в Glassfish, когда-либо содержит один файл Country.class, так что это действительно запутывает, почему существуют два разных экземпляра класса одного и того же класса и что они отличаются друг от друга!

У кого-нибудь есть идеи?

Для справки: Hibernate v4.3.6, EJB v3.2, Glassfish v4.1, JPA v2.1.

Суть моей страны.ява ниже. Как вы можете видеть, он содержит конструктор и общедоступные методы, поэтому меня удивляет, что в сервлете класс НЕ имеет «объявленныхконструкторов» или «declarepublicMethods». Как это может быть?

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

+0

Спасибо. Я тоже пробовал это, t o не воспользоваться, создав самый простой объект в проекте EJB, используя только пустой публичный конструктор id и getter/setter для него. Затем в коде EJB я проверяю класс, и это другой класс, чем тот, который зарегистрирован в MetamodelImpl. Просто не имеет смысла, что класс, который я определяю с помощью конструктора, getters и seters во время выполнения, не имеет никакого конструктора или метода, когда я обращаюсь к нему с MyEntity.class. Куда пропали эти декларации? – Raoul

ответ

0

Вы проверили свой persistence.xml? Является ли класс класса явно указанным или значение exclude-unlisted-classes установлено в false?

Или, возможно, несколько определений класса сущности в пути к классам (что могло бы объяснить наличие экземпляра, зарегистрированного в метамодели, но не разрешенного)?

+0

Спасибо, но я пробовал также: 'code' <живучесть-единица имя = "пробы JPA"> org.hibernate.jpa.HibernatePersistenceProvider MySQLResource сеть. .ejb.MyEntity <исключают-UNLISTED-классы> True 'code' И да, есть только один файл MyEntity класс в развернутом приложении. Я также думал, что их будет два, но это не так. Я смотрел во все папки и банки. Просто не имеет смысла, что есть два экземпляра класса одного класса. – Raoul

+0

Вы пытались явно вызвать функцию [Metamodel # entity (...)] (http://docs.oracle.com/javaee/6/api/javax/persistence/metamodel/Metamodel.html#entity (java.lang .Class))] с вашим объектом класса, чтобы проверить, как спящий режим разрешает его? – bdulac

+0

Я пробовал, но это тот же результат. MyEntity не является объектом. MetamodelImpl.entity (...) просто ищет объект на карте и использует класс MyEntity в качестве ключа. Однако, как я упоминал выше, объект, зарегистрированный MetamodelImpl (в Карте объектов), является правильным (он имеет конструктор и общедоступные методы), но если я проверю MyEntity.class в отладчике, я вижу, что это «другой» класс MyEntity у которого нет конструкторов и нет общедоступных методов. Это похоже на то, что Hibernate зарегистрировал правильный объект, но во время выполнения (в EJB) класс MyEntity.class - это неправильный класс без методов! Странный! – Raoul

1

Решенный! Это link помогло, особенно комментарий о persistence.xml.

Я до сих пор не понимаю, как вы могли бы иметь два разных экземпляра класса для одного класса, но это действительно просто особый способ, если у вас есть отдельные проекты EJB, WEB и JPA, которые выглядят следующим образом:

  1. Добавить persistence.xml НЕ проекта JPA (или проект , содержащий экземпляры @Entity), а добавить его в проект веб (я добавил его в SRC/META-INF, хотя есть другие возможностей, которые я еще не тестировал).

  2. В файле persistence.xml вы должны указать классы с «fqn-of-Class», ДАЖЕ, хотя классы должны быть подхвачены аннотацией.В настройках «исключающие-UNLISTED-классов (истинные) не актуален. Он работает и без этого.

Делая это означает, что запрос теперь работает без раздражающего IllegalArgumentException с указанием Субъекта» не Субъект ».

Проверено на JBoss EAP 6.3, Java 7, JPA 2.1, EJB 3.1, хотя я предполагаю, что он также будет работать на Glassfish с EJB 3.2.