上山打老虎 发表于 2021-7-4 11:04:32

LDAP 与 MySql 连用 的JPA事物问题

  本事甚是喜欢JPA简单方便明了,所以在LDAP项目要加上MYSQL数据库,但LDAP没有与jpa连用的事物处理 是一个很头疼的事,找到源码发现里面只有2种对组合事物的支持:

  ContextSourceAndDataSourceTransactionManagerLDAP与JDBC的组合支持
  ContextSourceAndHibernateTransactionManager   LDAP与Hibernate的组合支持
  如果使用这个 就是要说自己还要去封装jdbc 非常不爽,所以找到了个老外给的解决方法,自己写一个方法,来完成LDAP与JPA的组事物,下面就是 那段代码
  

import org.springframework.ldap.core.ContextSource;
import org.springframework.ldap.transaction.compensating.TempEntryRenamingStrategy;
import org.springframework.ldap.transaction.compensating.manager.ContextSourceTransactionManagerDelegate;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionSuspensionNotSupportedException;
import org.springframework.transaction.support.DefaultTransactionStatus;
public class ContextSourceAndJpaTransactionManager extends JpaTransactionManager {
    private static final long serialVersionUID = 1L;
private ContextSourceTransactionManagerDelegate ldapManagerDelegate =
      new ContextSourceTransactionManagerDelegate();
/**
* @see org.springframework.orm.jpa.JpaTransactionManager#isExistingTransaction(Object)
*/
protected boolean isExistingTransaction(Object transaction)
{
    ContextSourceAndJpaTransactionObject actualTransactionObject =
            (ContextSourceAndJpaTransactionObject) transaction;
    return super.isExistingTransaction(actualTransactionObject
                                             .getJpaTransactionObject());
}
/**
* @see org.springframework.orm.jpa.JpaTransactionManager#doGetTransaction()
*/
protected Object doGetTransaction() throws TransactionException
{
    Object dataSourceTransactionObject = super.doGetTransaction();
    Object contextSourceTransactionObject =
            ldapManagerDelegate.doGetTransaction();
    return new ContextSourceAndJpaTransactionObject(
            contextSourceTransactionObject, dataSourceTransactionObject
    );
}
/**
* @see org.springframework.orm.jpa.JpaTransactionManager#doBegin(java.lang.Object,
*      org.springframework.transaction.TransactionDefinition)
*/
protected void doBegin(Object transaction, TransactionDefinition definition)
      throws TransactionException
{
    ContextSourceAndJpaTransactionObject actualTransactionObject =
            (ContextSourceAndJpaTransactionObject) transaction;
    super.doBegin(actualTransactionObject.getJpaTransactionObject(),
                  definition);
    ldapManagerDelegate.doBegin(
            actualTransactionObject.getLdapTransactionObject(),
            definition
    );
}
/**
* @see org.springframework.orm.jpa.JpaTransactionManager#doCleanupAfterCompletion(java.lang.Object)
*/
protected void doCleanupAfterCompletion(Object transaction)
{
    ContextSourceAndJpaTransactionObject actualTransactionObject =
            (ContextSourceAndJpaTransactionObject) transaction;
    super.doCleanupAfterCompletion(actualTransactionObject
                                           .getJpaTransactionObject());
    ldapManagerDelegate.doCleanupAfterCompletion(actualTransactionObject
                                                 .getLdapTransactionObject());
}
/**
* @see org.springframework.orm.jpa.JpaTransactionManager#doCommit(org.springframework.transaction.support.DefaultTransactionStatus)
*/
protected void doCommit(DefaultTransactionStatus status)
      throws TransactionException
{
    ContextSourceAndJpaTransactionObject actualTransactionObject =
            (ContextSourceAndJpaTransactionObject) status.getTransaction();
    try
    {
      super.doCommit(new DefaultTransactionStatus(
                actualTransactionObject.getJpaTransactionObject(),
                status.isNewTransaction(),
                status.isNewSynchronization(),
                status.isReadOnly(),
                status.isDebug(),
                status.getSuspendedResources())
      );
    }
    catch (TransactionException ex)
    {
      if (isRollbackOnCommitFailure())
      {
            logger.debug("Failed to commit db resource, rethrowing", ex);
            // If we are to rollback on commit failure, just rethrow the
            // exception - this will cause a rollback to be performed on
            // both resources.
            throw ex;
      }
      else
      {
            logger.warn(
                  "Failed to commit and resource is rollbackOnCommit not set -"
                            + " proceeding to commit ldap resource.");
      }
    }
    ldapManagerDelegate.doCommit(new DefaultTransactionStatus(
            actualTransactionObject.getLdapTransactionObject(),
            status.isNewTransaction(),
            status.isNewSynchronization(),
            status.isReadOnly(),
            status.isDebug(),
            status.getSuspendedResources())
    );
}
/**
* @see org.springframework.orm.jpa.JpaTransactionManager#doRollback(org.springframework.transaction.support.DefaultTransactionStatus)
*/
protected void doRollback(DefaultTransactionStatus status) throws TransactionException
{
    ContextSourceAndJpaTransactionObject actualTransactionObject =
            (ContextSourceAndJpaTransactionObject) status.getTransaction();
    super.doRollback(new DefaultTransactionStatus(
            actualTransactionObject.getJpaTransactionObject(),
            status.isNewTransaction(),
            status.isNewSynchronization(),
            status.isReadOnly(),
            status.isDebug(),
            status.getSuspendedResources())
    );
    ldapManagerDelegate.doRollback(new DefaultTransactionStatus(
            actualTransactionObject.getLdapTransactionObject(),
            status.isNewTransaction(),
            status.isNewSynchronization(),
            status.isReadOnly(),
            status.isDebug(),
            status.getSuspendedResources())
    );
}
public ContextSource getContextSource()
{
    return ldapManagerDelegate.getContextSource();
}
public void setContextSource(ContextSource contextSource)
{
    ldapManagerDelegate.setContextSource(contextSource);
}
protected void setRenamingStrategy(TempEntryRenamingStrategy renamingStrategy)
{
    ldapManagerDelegate.setRenamingStrategy(renamingStrategy);
}
private final static class ContextSourceAndJpaTransactionObject
{
    private Object ldapTransactionObject;
    private Object jpaTransactionObject;
    public ContextSourceAndJpaTransactionObject(
            Object ldapTransactionObject, Object jpaTransactionObject)
    {
      this.ldapTransactionObject = ldapTransactionObject;
      this.jpaTransactionObject = jpaTransactionObject;
    }
    public Object getJpaTransactionObject()
    {
      return jpaTransactionObject;
    }
    public Object getLdapTransactionObject()
    {
      return ldapTransactionObject;
    }
}
/**
* @see org.springframework.orm.jpa.JpaTransactionManager#doSuspend(java.lang.Object)
*/
protected Object doSuspend(Object transaction) throws TransactionException
{
    throw new TransactionSuspensionNotSupportedException(
            "Transaction manager [" + getClass().getName()
                  + "] does not support transaction suspension");
}
/**
* @see org.springframework.orm.jpa.JpaTransactionManager#doResume(java.lang.Object, java.lang.Object)
*/
protected void doResume(Object transaction, Object suspendedResources)
      throws TransactionException
{
    throw new TransactionSuspensionNotSupportedException(
            "Transaction manager [" + getClass().getName()
                  + "] does not support transaction suspension");
}
/**
* @see org.springframework.orm.jpa.JpaTransactionManager#doSetRollbackOnly(org.springframework.transaction.support.DefaultTransactionStatus)
*/
@Override
protected void doSetRollbackOnly(DefaultTransactionStatus status)
{
    super.doSetRollbackOnly(
            new DefaultTransactionStatus(
                ((ContextSourceAndJpaTransactionObject)status.getTransaction())
                        .getJpaTransactionObject(),
                status.isNewTransaction(),
                status.isNewSynchronization(),
                status.isReadOnly(),
                status.isDebug(),
                status.getSuspendedResources())
    );
}
}  

  

  这事那人写的一直没时间翻译 等有时间 得好好研究下 并写好注解。。。之后你的tx.xml要支持它所以再看下我的tx.xml
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
                                          
    xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
          http://www.springframework.org/schema/context
          http://www.springframework.org/schema/context/spring-context-3.1.xsd
          http://www.springframework.org/schema/aop
          http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
          http://www.springframework.org/schema/tx   
          http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
          http://www.springframework.org/schema/cache
          http://www.springframework.org/schema/cache/spring-cache-3.1.xsd
          http://www.springframework.org/schema/data/jpa
          http://www.springframework.org/schema/data/jpa/spring-jpa.xsd"
    default-lazy-init="true"default-autowire="byName">
                                          
                                          
    <bean id="transactionManager" class="com.smarcloud.control.util.ContextSourceAndJpaTransactionManager">
      <!-- 第一个是LDAP的 -->
      <property name="contextSource" ref="contextSource"/>
      <!-- 第二个是Spring-Date-Jpa的 -->
       <property name="entityManagerFactory" ref="entityManagerFactory"/>
    </bean>
                                          
    <tx:annotation-driven transaction-manager="transactionManager"/>
                                          
</beans>  

  这样就可以了 ,非常好用的 ,对了 对于删除ldap的一个组织时,下面如果有分组,请不要家事物,否者你会发现 你并没删除掉并且还报错。

  
页: [1]
查看完整版本: LDAP 与 MySql 连用 的JPA事物问题