2016-04-08 61 views
1

Eclipse Link Multitenancy无法正常工作。Eclipse Link Multitenancy无法正常工作

例实体(正由liquibase创建的模式):

@Entity 
@Table(name = "ENTITIES") 
@Multitenant(MultitenantType.SINGLE_TABLE) 
@TenantDiscriminatorColumn(name = "TENANT_ID", contextProperty = "eclipselink.tenant-id") 
public class EntityClass 

要设置的实体管理我使用一个方面的多租户属性,如以下:

@Around("execution(* javax.persistence.EntityManagerFactory.*(..))") 
public Object invocate(ProceedingJoinPoint joinPoint) throws Throwable { 
    final Object result = joinPoint.proceed(); 

    if (result instanceof EntityManager) { 
     EntityManager em = (EntityManager) result; 

     final String tenantId = TenantContext.getCurrentTenantId(); 
     LOG.debug("Set EntityManager property for tenant {}.", tenantId); 
     em.setProperty(EntityManagerProperties.MULTITENANT_PROPERTY_DEFAULT, 
       tenantId); 

     return em; 
    } 

    return result; 
} 

当我启动Spring Boot应用程序完美地工作。有在集成测试提供租户信息,我定义的注释:

@Target({ElementType.TYPE, ElementType.METHOD}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface AsTenant { 
    String value(); 
} 

要绑定此值,我用一个TestExecutionListener

@Override 
public void beforeTestMethod(TestContext testContext) throws Exception { 
    final Method testMethod = testContext.getTestMethod(); 
    final AsTenant asTenantAnnotation = testMethod 
      .getAnnotation(AsTenant.class); 

    if (asTenantAnnotation != null) { 
     TenantContext.setCurrentTenantId(asTenantAnnotation.value()); 
    } 
} 

通过调试,我可以明确地说,TestExectionListener之前被调用任何EM都会创建并且该属性为EM设置正确。在将任何内容持久化到数据库时,Eclipse Link不会为该列设置值。

也许有人可以帮我解决这个问题,我不知道为什么EclipseLink Multitenancy不工作。

回答

0

好的,我得到了它的工作。如果有人遇到类似的问题,这是我的解决方案。

如果使用交易,则在交易开始后(http://www.eclipse.org/eclipselink/documentation/2.5/solutions/multitenancy002.htm),租户歧视的上下文属性必须设置为

EntityManager em = createEntityManager(MULTI_TENANT_PU); 
em.getTransaction().begin(); 
em.setProperty(EntityManagerProperties.MULTITENANT_PROPERTY_DEFAULT, "my_id"); 

要在春季启动/数据环境下实现这一目标,我定制Spring的JpaTransactionManager。此问题除了问题中的方面外,因为SELECT查询没有交易。

public class MultitenantJpaTransactionManager extends JpaTransactionManager { 

    /* (non-Javadoc) 
    * @see org.springframework.orm.jpa.JpaTransactionManager#doBegin(java.lang.Object, org.springframework.transaction.TransactionDefinition) 
    */ 
    @Override 
    protected void doBegin(Object transaction, TransactionDefinition definition) { 
     super.doBegin(transaction, definition); 

     final EntityManagerHolder emHolder = (EntityManagerHolder) TransactionSynchronizationManager.getResource(getEntityManagerFactory()); 
     final EntityManager em = emHolder.getEntityManager(); 
     final String tenantId = TenantContext.getCurrentTenantId(); 

     if (tenantId != null) { 
      em.setProperty(EntityManagerProperties.MULTITENANT_PROPERTY_DEFAULT, tenantId); 
     } 
    } 
} 

这是通过JpaConfiguration容易有线:

/** 
* Configures Eclipse Link as JPA Provider. 
*/ 
@Configuration 
@EnableTransactionManagement 
@AutoConfigureAfter({ DataSourceAutoConfiguration.class }) 
public class JpaConfiguration extends JpaBaseConfiguration { 

    @Bean 
    @Override 
    public PlatformTransactionManager transactionManager() { 
     return new MultitenantJpaTransactionManager(); 
    } 

    @Override 
    protected AbstractJpaVendorAdapter createJpaVendorAdapter() { 
     EclipseLinkJpaVendorAdapter adapter = new EclipseLinkJpaVendorAdapter(); 
     return adapter; 
    } 

    @Override 
    protected Map<String, Object> getVendorProperties() { 
     HashMap<String, Object> properties = new HashMap<String, Object>(); 

     properties.put(PersistenceUnitProperties.WEAVING, detectWeavingMode()); 

     return properties; 
    } 

    private String detectWeavingMode() { 
     return InstrumentationLoadTimeWeaver.isInstrumentationAvailable() 
      ? "true" : "static"; 
    } 
}