在 GlassFish 4.1 中注入 EntityManager 时出现问题。 ClassCastException(无法转换为相同 class)
Problems injecting EntityManager in GlassFish 4.1. ClassCastException (can't cast to same class)
我正在使用:
- GlassFish 4.1
- 休眠(参见 pom.xml)
- Java EE 7
- 日蚀月神
我不知道为什么 GlassFish 不能注入 EntityManager。如果我从 EntityManagerFactory 获得 EntityManager,我没有问题:
protected EntityManager em = Persistence.createEntityManagerFactory("CustomersPU").createEntityManager();
另一方面,如果我试图说 GlassFish 注入它,得到一个异常。:
@PersistenceContext(unitName="CustomersPU")
protected EntityManager em;
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.localtest</groupId>
<artifactId>customersapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven_compiler_source>1.8</maven_compiler_source>
<maven_compiler_target>1.8</maven_compiler_target>
</properties>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.8.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.3.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.common</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>4.0.5.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.8.Final</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
通用服务
package me.localtest.customersapp.services;
import java.io.Serializable;
import java.util.List;
public interface GenericService<T, PK extends Serializable> {
public T save(T t) throws Throwable;
public T update(T t) throws Throwable;
public T remove(T t) throws Throwable;
public T find(PK pk) throws Throwable;
public List<T> findAll(String namedQuery) throws Throwable;
}
GenericServiceImpl
package me.localtest.customersapp.services;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
public abstract class GenericServiceImpl<T, PK extends Serializable> implements GenericService<T, PK> {
//@PersistenceContext(unitName="CustomersPU")
protected EntityManager em = Persistence.createEntityManagerFactory("CustomersPU").createEntityManager();
protected Class<T> clazz;
public GenericServiceImpl(Class<T> clazz) {
this.clazz = clazz;
}
@Override
public T save(T t) throws Throwable {
em.persist(t);
em.flush();
return t;
}
@Override
public T remove(T t) throws Throwable {
em.remove(t);
em.flush();
return t;
}
@Override
public T update(T t) throws Throwable {
em.merge(t);
em.flush();
return t;
}
@Override
public T find(PK pk) throws Throwable {
return (T) em.find(clazz, pk);
}
@SuppressWarnings("unchecked")
@Override
public List<T> findAll(String aQuery) throws Throwable {
Query query = em.createQuery(aQuery);
return (List<T>) query.getResultList();
}
}
CustomerServiceBean
package me.localtest.customersapp.services;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.Query;
import me.localtest.customersapp.domain.entities.Customer;
@LocalBean
@Stateless
public class CustomerServiceBean extends GenericServiceImpl<Customer, Integer> {
public CustomerServiceBean() {
super(Customer.class);
}
public Customer findByDni(String dni) {
Query query = em.createNamedQuery("Customer.findByDni");
query.setParameter("dni", dni);
return (Customer) query.getSingleResult();
}
}
客户
package me.localtest.customersapp.domain.entities;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@Entity
@Table(name="customers")
@XmlRootElement(name="customer")
@XmlAccessorType(XmlAccessType.FIELD)
@NamedQueries({
@NamedQuery(name="Customer.findByDni", query="SELECT c FROM Customer c WHERE c.dni = :dni")
})
@SuppressWarnings("serial")
public class Customer implements Serializable {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
@XmlElement(name="id")
private Integer id;
@Column(name="names")
@XmlElement(name="names")
private String names;
@Column(name="surnames")
@XmlElement(name="surnames")
private String surnames;
@Column(name="dni")
@XmlElement(name="dni")
private String dni;
@Column(name="birth_date")
@XmlElement(name="birth-date")
@Temporal(TemporalType.DATE)
private Date birthDate;
@Column(name="address")
@XmlElement(name="address")
private String address;
@Column(name="email")
@XmlElement(name="email")
private String email;
@Column(name="creation_date")
@Temporal(TemporalType.DATE)
@XmlElement(name="creation-date")
private Date creationDate;
@Column(name="state")
@XmlElement(name="state")
private Boolean state;
public Customer() {
}
public Customer(Integer id, String names, String surnames, String dni,
Date birthDate, String address, String email, Date creationDate,
Boolean state) {
this.id = id;
this.names = names;
this.surnames = surnames;
this.dni = dni;
this.birthDate = birthDate;
this.address = address;
this.email = email;
this.creationDate = creationDate;
this.state = state;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNames() {
return names;
}
public void setNames(String names) {
this.names = names;
}
public String getSurnames() {
return surnames;
}
public void setSurnames(String surnames) {
this.surnames = surnames;
}
public String getDni() {
return dni;
}
public void setDni(String dni) {
this.dni = dni;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public Boolean getState() {
return state;
}
public void setState(Boolean state) {
this.state = state;
}
}
persistence.xml
<persistence-unit name="CustomersPU" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>jdbc/__customers</jta-data-source>
<properties>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform" />
</properties>
</persistence-unit>
阶段 1
尝试使用 DNI 'A' (RESTful) 查找客户:
http://localhost:8080/customersapp/api/customers/find/A
这是一段堆栈跟踪:
2015-04-06T09:19:31.088-0500|Advertencia: A system exception occurred during an invocation on EJB CustomerServiceBean, method: public me.localtest.customersapp.domain.entities.Customer me.localtest.customersapp.services.CustomerServiceBean.findByDni(java.lang.String)
2015-04-06T09:19:31.089-0500|Advertencia: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
at com.sun.ejb.containers.EJBContainerTransactionManager.checkExceptionClientTx(EJBContainerTransactionManager.java:662)
at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:507)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4566)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2074)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2044)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:220)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
at com.sun.proxy.$Proxy267.findByDni(Unknown Source)
at me.localtest.customersapp.services.__EJB31_Generated__CustomerServiceBean__Intf____Bean__.findByDni(Unknown Source)
这是原因:
Caused by: java.lang.ClassCastException: me.localtest.customersapp.domain.entities.Customer cannot be cast to me.localtest.customersapp.domain.entities.Customer
我发现这很愚蠢,怎么可能不能转换成相同的class?
谢谢。
嗯,我找不到这个问题的解决方案。我切换到 WildFly 8.2.0,没有问题。不管怎样,我希望有一天能知道为什么会这样xD。
谢谢。
似乎是 GF 4.x 在休眠版本 4.3 中遇到的类加载器问题的结果。8.Final
很可能与 HHH-9446 有关,而且它看起来像是 2 天前修复的。虽然还没有机会尝试
我正在使用:
- GlassFish 4.1
- 休眠(参见 pom.xml)
- Java EE 7
- 日蚀月神
我不知道为什么 GlassFish 不能注入 EntityManager。如果我从 EntityManagerFactory 获得 EntityManager,我没有问题:
protected EntityManager em = Persistence.createEntityManagerFactory("CustomersPU").createEntityManager();
另一方面,如果我试图说 GlassFish 注入它,得到一个异常。:
@PersistenceContext(unitName="CustomersPU")
protected EntityManager em;
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.localtest</groupId>
<artifactId>customersapp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<maven_compiler_source>1.8</maven_compiler_source>
<maven_compiler_target>1.8</maven_compiler_target>
</properties>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>4.3.8.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.1.3.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.common</groupId>
<artifactId>hibernate-commons-annotations</artifactId>
<version>4.0.5.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.1.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.3.8.Final</version>
</dependency>
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
通用服务
package me.localtest.customersapp.services;
import java.io.Serializable;
import java.util.List;
public interface GenericService<T, PK extends Serializable> {
public T save(T t) throws Throwable;
public T update(T t) throws Throwable;
public T remove(T t) throws Throwable;
public T find(PK pk) throws Throwable;
public List<T> findAll(String namedQuery) throws Throwable;
}
GenericServiceImpl
package me.localtest.customersapp.services;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
public abstract class GenericServiceImpl<T, PK extends Serializable> implements GenericService<T, PK> {
//@PersistenceContext(unitName="CustomersPU")
protected EntityManager em = Persistence.createEntityManagerFactory("CustomersPU").createEntityManager();
protected Class<T> clazz;
public GenericServiceImpl(Class<T> clazz) {
this.clazz = clazz;
}
@Override
public T save(T t) throws Throwable {
em.persist(t);
em.flush();
return t;
}
@Override
public T remove(T t) throws Throwable {
em.remove(t);
em.flush();
return t;
}
@Override
public T update(T t) throws Throwable {
em.merge(t);
em.flush();
return t;
}
@Override
public T find(PK pk) throws Throwable {
return (T) em.find(clazz, pk);
}
@SuppressWarnings("unchecked")
@Override
public List<T> findAll(String aQuery) throws Throwable {
Query query = em.createQuery(aQuery);
return (List<T>) query.getResultList();
}
}
CustomerServiceBean
package me.localtest.customersapp.services;
import javax.ejb.LocalBean;
import javax.ejb.Stateless;
import javax.persistence.Query;
import me.localtest.customersapp.domain.entities.Customer;
@LocalBean
@Stateless
public class CustomerServiceBean extends GenericServiceImpl<Customer, Integer> {
public CustomerServiceBean() {
super(Customer.class);
}
public Customer findByDni(String dni) {
Query query = em.createNamedQuery("Customer.findByDni");
query.setParameter("dni", dni);
return (Customer) query.getSingleResult();
}
}
客户
package me.localtest.customersapp.domain.entities;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@Entity
@Table(name="customers")
@XmlRootElement(name="customer")
@XmlAccessorType(XmlAccessType.FIELD)
@NamedQueries({
@NamedQuery(name="Customer.findByDni", query="SELECT c FROM Customer c WHERE c.dni = :dni")
})
@SuppressWarnings("serial")
public class Customer implements Serializable {
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
@XmlElement(name="id")
private Integer id;
@Column(name="names")
@XmlElement(name="names")
private String names;
@Column(name="surnames")
@XmlElement(name="surnames")
private String surnames;
@Column(name="dni")
@XmlElement(name="dni")
private String dni;
@Column(name="birth_date")
@XmlElement(name="birth-date")
@Temporal(TemporalType.DATE)
private Date birthDate;
@Column(name="address")
@XmlElement(name="address")
private String address;
@Column(name="email")
@XmlElement(name="email")
private String email;
@Column(name="creation_date")
@Temporal(TemporalType.DATE)
@XmlElement(name="creation-date")
private Date creationDate;
@Column(name="state")
@XmlElement(name="state")
private Boolean state;
public Customer() {
}
public Customer(Integer id, String names, String surnames, String dni,
Date birthDate, String address, String email, Date creationDate,
Boolean state) {
this.id = id;
this.names = names;
this.surnames = surnames;
this.dni = dni;
this.birthDate = birthDate;
this.address = address;
this.email = email;
this.creationDate = creationDate;
this.state = state;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getNames() {
return names;
}
public void setNames(String names) {
this.names = names;
}
public String getSurnames() {
return surnames;
}
public void setSurnames(String surnames) {
this.surnames = surnames;
}
public String getDni() {
return dni;
}
public void setDni(String dni) {
this.dni = dni;
}
public Date getBirthDate() {
return birthDate;
}
public void setBirthDate(Date birthDate) {
this.birthDate = birthDate;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public Date getCreationDate() {
return creationDate;
}
public void setCreationDate(Date creationDate) {
this.creationDate = creationDate;
}
public Boolean getState() {
return state;
}
public void setState(Boolean state) {
this.state = state;
}
}
persistence.xml
<persistence-unit name="CustomersPU" transaction-type="JTA">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>jdbc/__customers</jta-data-source>
<properties>
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform" />
</properties>
</persistence-unit>
阶段 1
尝试使用 DNI 'A' (RESTful) 查找客户:
http://localhost:8080/customersapp/api/customers/find/A
这是一段堆栈跟踪:
2015-04-06T09:19:31.088-0500|Advertencia: A system exception occurred during an invocation on EJB CustomerServiceBean, method: public me.localtest.customersapp.domain.entities.Customer me.localtest.customersapp.services.CustomerServiceBean.findByDni(java.lang.String)
2015-04-06T09:19:31.089-0500|Advertencia: javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
at com.sun.ejb.containers.EJBContainerTransactionManager.checkExceptionClientTx(EJBContainerTransactionManager.java:662)
at com.sun.ejb.containers.EJBContainerTransactionManager.postInvokeTx(EJBContainerTransactionManager.java:507)
at com.sun.ejb.containers.BaseContainer.postInvokeTx(BaseContainer.java:4566)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2074)
at com.sun.ejb.containers.BaseContainer.postInvoke(BaseContainer.java:2044)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandler.invoke(EJBLocalObjectInvocationHandler.java:220)
at com.sun.ejb.containers.EJBLocalObjectInvocationHandlerDelegate.invoke(EJBLocalObjectInvocationHandlerDelegate.java:88)
at com.sun.proxy.$Proxy267.findByDni(Unknown Source)
at me.localtest.customersapp.services.__EJB31_Generated__CustomerServiceBean__Intf____Bean__.findByDni(Unknown Source)
这是原因:
Caused by: java.lang.ClassCastException: me.localtest.customersapp.domain.entities.Customer cannot be cast to me.localtest.customersapp.domain.entities.Customer
我发现这很愚蠢,怎么可能不能转换成相同的class?
谢谢。
嗯,我找不到这个问题的解决方案。我切换到 WildFly 8.2.0,没有问题。不管怎样,我希望有一天能知道为什么会这样xD。
谢谢。
似乎是 GF 4.x 在休眠版本 4.3 中遇到的类加载器问题的结果。8.Final
很可能与 HHH-9446 有关,而且它看起来像是 2 天前修复的。虽然还没有机会尝试