Is it possible to use Hibernate 5 as JPA engine in

2019-07-26 22:23发布

I use 4.3.11 in my Liberty projects but there is a bug with Hibernate solved in version 5. I have tried upgrading but I get different exceptions.

Anybody is using Hibernate 5.x.x with Liberty Profile? What jars are you including in the dataSource library in server.xml?

thanks

4条回答
叛逆
2楼-- · 2019-07-26 23:11

As of Hibernate 5.2.13, a proper transaction integration has been delivered for Liberty. If you are able to upgrade to this version of Hibernate, then it will be detected and applied automatically, and not necessary to specify hibernate.transaction.jta.platform anymore.

See this Hibernate issue for more details: https://hibernate.atlassian.net/browse/HHH-11571

查看更多
Anthone
3楼-- · 2019-07-26 23:15

Even i ended up with similar situation. The exception message was: com.ibm.ws.container.service.state.StateChangeException: javax.xml.stream.FactoryConfigurationError: Provider javax.xml.stream.XMLEventFactory could not be instantiated: java.util.ServiceConfigurationError: javax.xml.stream.XMLEventFactory: Provider com.ibm.xml.xlxp2.api.stax.XMLEventFactoryImpl not found

do you see any break through?

查看更多
对你真心纯属浪费
4楼-- · 2019-07-26 23:17

I've been able to get Hibernate 5.x at least partially working in Liberty if I include these JARs:

  <library id="hibernate">
    <file name="${server.config.dir}/hibernate/antlr-2.7.7.jar"/>
    <file name="${server.config.dir}/hibernate/classmate-1.3.0.jar"/>
    <file name="${server.config.dir}/hibernate/dom4j-1.6.1.jar"/>
    <file name="${server.config.dir}/hibernate/hibernate-commons-annotations-5.0.1.Final.jar"/>
    <file name="${server.config.dir}/hibernate/hibernate-core-5.2.6.Final.jar"/>
    <file name="${server.config.dir}/hibernate/javassist-3.20.0-GA.jar"/>
    <file name="${server.config.dir}/hibernate/jboss-logging-3.3.0.Final.jar"/>
  </library>

  <application location="myApp.war">
    <classloader commonLibraryRef="hibernate"/>
  </application>

The reason I say partially working is that it works great if using non-jta-data-source, but when trying to use jta-data-source, Hibernate can fail trying to locate vendor-specific API to suspend the current transaction. Hibernate does have some properties that you can set to tell it that it's being used by WebSphere servers, and I've explored various combinations of those without a successful outcome for jta-data-source. I think the Hibernate implementation is lacking in its awareness of Liberty, which is something that really ought to be added, (see HHH-10388 and vote for it if you would find it valuable) although in its absence you can get it working by writing your own implementation of Hibernate JtaPlatform that delegates to com.ibm.tx.jta.TransactionManagerFactory and specifying it as a persistence property.

For example in persistence.xml,

  <persistence-unit ...
    <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
    ...
    <properties>
      <property name="hibernate.transaction.jta.platform" 
                value="example.WebSphereLibertyJtaPlatform" />
    </properties>
  </persistence-unit>

Example implementation,

package example;

import com.ibm.tx.jta.TransactionManagerFactory;
import javax.naming.*;
import javax.transaction.*;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;

public class WebSphereLibertyJtaPlatform implements JtaPlatform {
    public boolean canRegisterSynchronization() {
        try {
            return getCurrentStatus() == Status.STATUS_ACTIVE;
        } catch (SystemException x) {
            throw new RuntimeException(x);
        }
    }

    public int getCurrentStatus() throws SystemException {
        return retrieveTransactionManager().getStatus();
    }

    public Object getTransactionIdentifier(Transaction transaction) {
        return transaction;
    }

    public void registerSynchronization(Synchronization synchronization) {
        try {
            retrieveTransactionManager().getTransaction().registerSynchronization(synchronization);
        } catch (IllegalStateException x) {
            throw new RuntimeException(x);
        } catch (RollbackException x) {
            throw new RuntimeException(x);
        } catch (SystemException x) {
            throw new RuntimeException(x);
        }
    }

    public TransactionManager retrieveTransactionManager() {
        return TransactionManagerFactory.getTransactionManager();
    }

    public UserTransaction retrieveUserTransaction() {
        try {
            return InitialContext.doLookup("java:comp/UserTransaction");
        } catch (NamingException x) {
            throw new RuntimeException(x);
        }
    }
}
查看更多
Lonely孤独者°
5楼-- · 2019-07-26 23:29

I know the thread is a bit old, but comparing Liberty Profile 17.0.0.2 and 17.0.0.3 I have noticed they have introduced this class

com.ibm.ws.jpa.hibernate.LibertyJtaPlatform

and now when I start the app server, the container passes some properties when calls

HibernatePersistenceProvider.createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties)

to initialize hibernate for a data-source and in the properties you have the instance of that class:

enter image description here

Hope it helps.

查看更多
登录 后发表回答