java Bitronix + Spring + Hibernate + 持久化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5027539/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 09:06:44  来源:igfitidea点击:

Bitronix + Spring + Hibernate + Persistence

javahibernatespringpersistence

提问by Dejell

I am trying to create transaction manager and use it with Hibernate for Oracle.

我正在尝试创建事务管理器并将其与 Hibernate for Oracle 一起使用。

My persistence.xml file is:

我的 persistence.xml 文件是:

<persistence-unit name="org.drools.persistence.jpa"
        transaction-type="JTA">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>jdbc/testDS1</jta-data-source>
        <class>org.drools.persistence.session.SessionInfo</class>
        <class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class>
        <class>org.drools.persistence.processinstance.WorkItemInfo</class>

        <exclude-unlisted-classes>true</exclude-unlisted-classes>
        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.Oracle10gDialect" />
            <property name="hibernate.connection.autocommit" value="false" />
            <property name="hibernate.max_fetch_depth" value="3" />
            <property name="hibernate.jndi.class" value="bitronix.tm.jndi.BitronixInitialContextFactory"/> 
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.transaction.manager_lookup_class"
                value="org.hibernate.transaction.BTMTransactionManagerLookup" />
        </properties>
    </persistence-unit>

In applicationContext.xml of spring I added:

在 spring 的 applicationContext.xml 中,我添加了:

<bean id="dataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init" destroy-method="close"> 
           <property name="className" value="oracle.jdbc.xa.client.OracleXADataSource" /> 
           <property name="uniqueName" value="jdbc/testDS1" /> 
           <property name="minPoolSize" value="1" /> 
           <property name="maxPoolSize" value="5" /> 
           <property name="driverProperties">
            <props>
                <prop key="URL">myURL</prop>
                <prop key="user">username</prop>
                <prop key="password">password</prop>
            </props>
        </property>       
    </bean> 

    <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"> 
        <property name="transactionManager" ref="bitronixTransactionManager"/> 
        <property name="userTransaction" ref="bitronixTransactionManager"/> 
    </bean> 

    <bean id="bitronixTransactionManager" factory-method="getTransactionManager" 
          class="bitronix.tm.TransactionManagerServices" depends-on="dataSource,txManager" 
          destroy-method="shutdown"/>

However, when I run:

但是,当我运行时:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("org.drools.persistence.jpa");

I get an exception:

我得到一个例外:

Caused by: org.hibernate.HibernateException: Could not find datasource: jdbc/testDS1

The exception is on ds = (DataSource ) NamingHelper.getInitialContext(props).lookup(jndiName);of Hibernate infra file.

例外是ds = (DataSource ) NamingHelper.getInitialContext(props).lookup(jndiName);Hibernate infra 文件。

  1. What could be the problem?

  2. How does Hibernate persistence knows to refer to spring txManagerbean?

  1. 可能是什么问题呢?

  2. Hibernate持久化怎么知道指的是spring txManagerbean?

采纳答案by mcyalcin

Your persistence provider does its lookups on jndi. Data sources defined in Spring application context are not bound to jndi. Hence, persistence provider's lookup attempt for the data source fails as there is no such data source bound to jndi.

您的持久性提供程序在 jndi 上进行查找。Spring 应用程序上下文中定义的数据源不绑定到 jndi。因此,持久性提供程序对数据源的查找尝试失败,因为没有绑定到 jndi 的此类数据源。

You may want to check http://forum.springsource.org/showthread.php?t=13984.

您可能需要查看http://forum.springsource.org/showthread.php?t=13984

Can you try defining your data sources in the server context and looking them up in your spring application by their jndi names?

您可以尝试在服务器上下文中定义数据源并通过 jndi 名称在 spring 应用程序中查找它们吗?

回答by Ludovic Orban

Looks like your datasource hasn't been created yet when Persistence.createEntityManagerFactory() is called. Since your bitronixTransactionManager bean depends on the dataSource one, you should see some INFO log telling you BTM has started which should mean the datasource has been created too.

调用 Persistence.createEntityManagerFactory() 时,您的数据源似乎尚未创建。由于您的 bitronixTransactionManager bean 依赖于数据源之一,您应该会看到一些 INFO 日志告诉您 BTM 已启动,这应该意味着数据源也已创建。

Another potential reason could be that Hibernate doesn't lookup the datasource in the right JNDI context. You could enable bitronix.tm.jndi DEBUG logs to assert that its JNDI provider is getting called.

另一个潜在的原因可能是 Hibernate 没有在正确的 JNDI 上下文中查找数据源。您可以启用 bitronix.tm.jndi DEBUG 日志以断言其 JNDI 提供程序正在被调用。

回答by jpkrohling

What could be the problem?

可能是什么问题呢?

Are you able to consume this data source in a standalone java app, by asking for jdbc/testDS1? In regular Tomcat DataSources, you'd need to ask for java:comp/env/jdbc/testDS1, not only jdbc/testDS1.

您是否能够通过请求在独立的 Java 应用程序中使用此数据源jdbc/testDS1?在常规 Tomcat 数据源中,您需要请求java:comp/env/jdbc/testDS1,而不仅仅是jdbc/testDS1.

How does Hibernate persistence knows to refer to spring txManager bean?

Hibernate持久化如何知道引用spring txManager bean?

It doesn't. You are saying this to Hibernate:

它没有。你是在对 Hibernate 说这个:

        <property name="hibernate.transaction.manager_lookup_class"
            value="org.hibernate.transaction.BTMTransactionManagerLookup" />

So, Hibernate will use the lookup class to, well, "lookup" the transaction manager :-)

因此,Hibernate 将使用查找类来“查找”事务管理器 :-)

回答by Scarlett

I think either is the persistence.xml has not been configered correctly or you have not start up the SPring container. here I post my persistence.xml code

我认为要么是persistence.xml 没有被正确配置要么你没有启动SPring 容器。我在这里发布了我的persistence.xml 代码

enter code here
<persistence-unit name="org.drools.task" transaction-type="JTA">
    <provider>org.hibernate.ejb.HibernatePersistence</provider>
    <jta-data-source>jdbc/mysql</jta-data-source>
    <class>org.drools.task.Attachment</class>
<properties>
        <property name="hibernate.archive.autodetection" value="class"/>
        <property name="hibernate.current_session_context_class" value="jta" />
        <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.BTMTransactionManagerLookup" />
        <property name="hibernate.jndi.class" value="bitronix.tm.jndi.BitronixInitialContextFactory"/>
        <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
        <property name="hibernate.cache.provider_class" value="org.hibernate.cache.NoCacheProvider" />
        <property name="hibernate.show_sql" value="true" />

        <!-- after first run the application, should comment it, else it will drop and create table each time 
        <property name="hibernate.hbm2ddl.auto" value="create" /> -->
</properties>
</persistence-unit>

and my testing code:

和我的测试代码:

enter code here
    ApplicationContext ctx = new FileSystemXmlApplicationContext("applicationContext.xml");
    JtaTransactionManager txManager = (JtaTransactionManager) ctx.getBean("txManager");
    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
    TransactionStatus status = txManager.getTransaction(def);
    System.out.println("The transaction manager is "+txManager);
    System.out.println("The transaction is "+status);

the transaction manager config is same as you posted. it can work.

事务管理器配置与您发布的相同。它可以工作。

回答by duffymo

Are you deploying this as a WAR or EAR? Did you declare the data source in your web.xml and set it up on the app server?

您是将其部署为 WAR 还是 EAR?您是否在 web.xml 中声明了数据源并将其设置在应用服务器上?

UPDATE: Since you've declared the data source in your WAR, make sure you've set upthe JNDI data source in Tomcat.

更新:由于您已在 WAR 中声明数据源,因此请确保已在 Tomcat 中设置JNDI 数据源。

Your error says: "Caused by: org.hibernate.HibernateException: Could not find datasource: jdbc/testDS1". That's a JNDI lookup name.

您的错误是:“由以下原因引起:org.hibernate.HibernateException:找不到数据源:jdbc/testDS1”。这是一个 JNDI 查找名称。

So where does "I don't want to" fit into this?

那么“我不想”在哪里适合呢?

Spring needs a Java Naming and Directory service to look up the data source associated with this name; that's what Tomcat provides. If not Tomcat, where do you propose that Spring get it from? The naming service is part of the Java EE app server.

Spring 需要 Java Naming and Directory 服务来查找与此名称关联的数据源;这就是Tomcat提供的。如果不是 Tomcat,您建议 Spring 从哪里获取它?命名服务是 Java EE 应用服务器的一部分。

You either have to set up the JNDI data source and connection pool on Tomcat OR forego the benefits it provides and tell Spring to use a DriverManagerDataSource instead:

您要么必须在 Tomcat 上设置 JNDI 数据源和连接池,要么放弃它提供的好处并告诉 Spring 使用 DriverManagerDataSource 代替:

http://static.springsource.org/spring/docs/2.5.x/reference/jdbc.html

http://static.springsource.org/spring/docs/2.5.x/reference/jdbc.html

回答by Lucas de Oliveira

I believe I've got a similar scenario running. My persistence.xml is like the following:

我相信我有一个类似的场景正在运行。我的persistence.xml 是这样的:

<persistence-unit name="myPersistenceUnit" transaction-type="RESOURCE_LOCAL">
    <!-- other configuration ommited -->
    <jta-data-source>java:comp/env/jdbc/YourPersistentUnitJNDI_Name</jta-data-source>
    <!-- other configuration ommited -->
</persistence-unit>

And the spring application bean xml file is like:

而 spring 应用程序 bean xml 文件是这样的:

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="myPersistenceUnit" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"/>
        </property>
    </bean>
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
        </bean>

Hope that helps!

希望有帮助!