简体   繁体   English

Bitronix + Spring + Hibernate + Persistence

[英]Bitronix + Spring + Hibernate + Persistence

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); ds = (DataSource ) NamingHelper.getInitialContext(props).lookup(jndiName); of Hibernate infra file. Hibernate infra文件。

  1. What could be the problem? 可能是什么问题呢?

  2. How does Hibernate persistence knows to refer to spring txManager bean? Hibernate持久化如何知道引用spring txManager bean?

Looks like your datasource hasn't been created yet when Persistence.createEntityManagerFactory() is called. 看起来在调用Persistence.createEntityManagerFactory()时尚未创建数据源。 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. 由于您的bitronixTransactionManager bean依赖于dataSource,您应该看到一些INFO日志告诉您BTM已经启动,这应该意味着数据源也已创建。

Another potential reason could be that Hibernate doesn't lookup the datasource in the right JNDI context. 另一个可能的原因可能是Hibernate没有在正确的JNDI上下文中查找数据源。 You could enable bitronix.tm.jndi DEBUG logs to assert that its JNDI provider is getting called. 您可以启用bitronix.tm.jndi DEBUG日志来断言其JNDI提供程序正在被调用。

What could be the problem? 可能是什么问题呢?

Are you able to consume this data source in a standalone java app, by asking for jdbc/testDS1 ? 您是否可以通过请求jdbc/testDS1在独立的Java应用程序中使用此数据源? In regular Tomcat DataSources, you'd need to ask for java:comp/env/jdbc/testDS1 , not only jdbc/testDS1 . 在常规的Tomcat DataSources中,您需要请求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将使用查找类来“查找”事务管理器:-)

Your persistence provider does its lookups on jndi. 您的持久性提供程序在jndi上执行查找。 Data sources defined in Spring application context are not bound to jndi. Spring应用程序上下文中定义的数据源不绑定到jndi。 Hence, persistence provider's lookup attempt for the data source fails as there is no such data source bound to 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应用程序中查找它们?

Are you deploying this as a WAR or EAR? 您是将其部署为WAR还是EAR? Did you declare the data source in your web.xml and set it up on the app server? 您是否在web.xml中声明了数据源并在应用服务器上进行了设置?

UPDATE: Since you've declared the data source in your WAR, make sure you've set up the JNDI data source in Tomcat. 更新:由于您已在WAR中声明了数据源,因此请确保已在Tomcat中设置 JNDI数据源。

Your error says: "Caused by: org.hibernate.HibernateException: Could not find datasource: jdbc/testDS1". 您的错误说:“由以下原因引起:org.hibernate.HibernateException:找不到数据源:jdbc / testDS1”。 That's a JNDI lookup name. 这是一个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; Spring需要Java命名和目录服务来查找与此名称关联的数据源; that's what Tomcat provides. 这就是Tomcat提供的功能。 If not Tomcat, where do you propose that Spring get it from? 如果不是Tomcat,你建议Spring从哪里获得它? The naming service is part of the Java EE app server. 命名服务是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

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! 希望有所帮助!

I think either is the persistence.xml has not been configered correctly or you have not start up the SPring container. 我认为要么persistence.xml没有正确配置,要么你还没有启动SPring容器。 here I post my persistence.xml code 在这里我发布了我的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. 它可以工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM