使用 Hibernate 作为持久性提供程序构建实体管理器工厂时无法查找 JNDI 名称

Unable to lookup JNDI name when building entity manager factory with Hibernate as persistence provider

我的persistence.xml:

<persistence-unit name="manager1" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<jta-data-source>java:comp/env/jdbc/mysql</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
  <property name="javax.persistence.schema-generation.database.action" value="create"/>
</properties>

我的 class 智能手机服务:

@Stateless
@LocalBean
public class SmartphoneService implements IDao<Smartphone> {

    private static final String JPQL_SELECT_PAR_ID = "SELECT u FROM Smartphone u WHERE u.idSmartphone=:id";

    private EntityManagerFactory emf;
    private EntityManager em;

    public SmartphoneService() {        
        emf = Persistence.createEntityManagerFactory("manager1");
        em = emf.createEntityManager();
    }
    @Override
    public boolean create(Smartphone smart) {
        try {
            em.getTransaction().begin();
            em.persist(smart);
            em.getTransaction().commit();
            return true;

        } catch (Exception e) {
            if (em.getTransaction() != null) {
                em.getTransaction().rollback();
            }
        }
        return false;
    }}

我的 servlet:

@EJB
SmartphoneService ss;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    processRequest(request, response);


    ss=new SmartphoneService();
    Smartphone smart=new Smartphone(000, 000, null, null, null);
    ss.create(smart);
}

我创建了一个没有表的数据库+池连接(ping成功)+ jndi name=jdbc/mysql

the project was successfully deployed

当我 运行 我的 servlet 创建表并保留我的对象时.. 我收到此错误:

    Infos:   HCANN000001: Hibernate Commons Annotations {4.0.4.Final}
Grave:   Exception while invoking class org.glassfish.ejb.startup.EjbDeployer load method
java.lang.RuntimeException: EJB Container initialization error
    at org.glassfish.ejb.startup.EjbApplication.loadContainers(EjbApplication.java:234)
    at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:291)
    at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:99)
    at org.glassfish.internal.data.ModuleInfo.load(ModuleInfo.java:206)
    at org.glassfish.internal.data.ApplicationInfo.load(ApplicationInfo.java:313)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:496)
    at com.sun.enterprise.v3.server.ApplicationLoaderService.processApplication(ApplicationLoaderService.java:406)
    at com.sun.enterprise.v3.server.ApplicationLoaderService.postConstruct(ApplicationLoaderService.java:243)
    at org.jvnet.hk2.internal.ClazzCreator.postConstructMe(ClazzCreator.java:329)
    at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:377)
    at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:461)
    at org.glassfish.hk2.runlevel.internal.AsyncRunLevelContext.findOrCreate(AsyncRunLevelContext.java:227)
    at org.glassfish.hk2.runlevel.RunLevelContext.findOrCreate(RunLevelContext.java:84)
    at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2258)
    at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:105)
    at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:87)
    at org.glassfish.hk2.runlevel.internal.CurrentTaskFuture$QueueRunner.oneJob(CurrentTaskFuture.java:1162)
    at org.glassfish.hk2.runlevel.internal.CurrentTaskFuture$QueueRunner.run(CurrentTaskFuture.java:1147)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: javax.persistence.PersistenceException: Unable to build entity manager factory
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:81)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
    at com.fussa.service.SmartphoneService.<init>(SmartphoneService.java:38)
    at com.fussa.service.__EJB31_Generated__SmartphoneService__Intf____Bean__.<init>(Unknown Source)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:408)
    at java.lang.Class.newInstance(Class.java:438)
    at com.sun.ejb.containers.BaseContainer.instantiateOptionalEJBLocalBusinessObjectImpl(BaseContainer.java:3866)
    at com.sun.ejb.containers.StatelessSessionContainer.initializeHome(StatelessSessionContainer.java:237)
    at com.sun.ejb.containers.StatelessContainerFactory.createContainer(StatelessContainerFactory.java:63)
    at org.glassfish.ejb.startup.EjbApplication.loadContainers(EjbApplication.java:221)
    ... 20 more
Caused by: org.hibernate.engine.jndi.JndiException: Unable to lookup JNDI name [java:comp/env/jdbc/mysql]
    at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:117)
    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.configure(DatasourceConnectionProviderImpl.java:115)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:89)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:206)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:178)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(JdbcServicesImpl.java:260)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:94)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:89)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:206)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:178)
    at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1885)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1843)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.perform(EntityManagerFactoryBuilderImpl.java:850)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.perform(EntityManagerFactoryBuilderImpl.java:843)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:399)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:842)
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:73)
    ... 33 more
Caused by: javax.naming.NamingException: Lookup failed for 'java:comp/env/jdbc/mysql' in SerialContext[myEnv={java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NamingException: Invocation exception: Got null ComponentInvocation ]
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:491)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:438)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:622)
    at javax.naming.InitialContext.lookup(InitialContext.java:421)
    at javax.naming.InitialContext.lookup(InitialContext.java:421)
    at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:114)
    ... 49 more
Caused by: javax.naming.NamingException: Invocation exception: Got null ComponentInvocation 
    at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.getComponentId(GlassfishNamingManagerImpl.java:842)
    at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:714)
    at com.sun.enterprise.naming.impl.JavaURLContext.lookup(JavaURLContext.java:159)
    at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:471)
    ... 54 more

Grave:   Exception during lifecycle processing
java.lang.RuntimeException: EJB Container initialization error
    at org.glassfish.ejb.startup.EjbApplication.loadContainers(EjbApplication.java:234)
    at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:291)
    at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:99)
    at org.glassfish.internal.data.ModuleInfo.load(ModuleInfo.java:206)
    at org.glassfish.internal.data.ApplicationInfo.load(ApplicationInfo.java:313)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:496)
    at com.sun.enterprise.v3.server.ApplicationLoaderService.processApplication(ApplicationLoaderService.java:406)
    at com.sun.enterprise.v3.server.ApplicationLoaderService.postConstruct(ApplicationLoaderService.java:243)
    at org.jvnet.hk2.internal.ClazzCreator.postConstructMe(ClazzCreator.java:329)
    at org.jvnet.hk2.internal.ClazzCreator.create(ClazzCreator.java:377)
    at org.jvnet.hk2.internal.SystemDescriptor.create(SystemDescriptor.java:461)
    at org.glassfish.hk2.runlevel.internal.AsyncRunLevelContext.findOrCreate(AsyncRunLevelContext.java:227)
    at org.glassfish.hk2.runlevel.RunLevelContext.findOrCreate(RunLevelContext.java:84)
    at org.jvnet.hk2.internal.Utilities.createService(Utilities.java:2258)
    at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:105)
    at org.jvnet.hk2.internal.ServiceHandleImpl.getService(ServiceHandleImpl.java:87)
    at org.glassfish.hk2.runlevel.internal.CurrentTaskFuture$QueueRunner.oneJob(CurrentTaskFuture.java:1162)
    at org.glassfish.hk2.runlevel.internal.CurrentTaskFuture$QueueRunner.run(CurrentTaskFuture.java:1147)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)

您可以切换到 JTA 并添加 @PersistenceContext 注释以自动注入 EntityManager:

@PersistenceContext
private EntityManager em;

将您的 persistence.xml 更改为如下所示:

<persistence-unit name="manager1" transaction-type="JTA">

如果只有一个PersistenceUnit,则不需要在注解中指定。如果您有多个 PersistenceUnits,您可以像这样指定要使用的一个:

@PersistenceContext(unitName = "manager1")
private EntityManager em;

如果您使用 JTA,则不必自己管理事务,因此请确保使用 em.getTransaction() 删除所有内容。这是推荐的方法

如果您想使用 RESOURCE_LOCAL,另一种方法是使用 EntityManagerFactory 来获取 EntityManager.

的实例
EntityManager em = Persistence.createEntityManagerFactory("manager1")
.createEntityManager();

@PersistenceUnit(unitName = "manager1")
private EntityManagerFactory emf;

更新

对于这两种方法,您应该将数据源更改为如下所示:

<jta-data-source>jdbc/mysql</jta-data-source>

如果您想使用 RESOURCE_LOCAL,您还应该将其更改为 non-jta-data-source(但在 Glassfish 中它也可以与 jta-data-source 一起使用)。

示例:

<non-jta-data-source>jdbc/mysql</non-jta-data-source>

另请参阅:

  • Java EE 6 Tutorial - Persistence Units
  • PersistenceContext EntityManager injection NullPointerException
  • Persistence unit as RESOURCE_LOCAL or JTA?
  • persistence.xml different transaction-type attributes