gpt4 book ai didi

eclipselink - 使用 spring data jpa 和 eclipselink 进行 Multi-Tenancy

转载 作者:行者123 更新时间:2023-12-04 20:40:51 32 4
gpt4 key购买 nike

我正在尝试向我的 Spring 数据 jpa 存储库添加 Multi-Tenancy 支持。我想为每个请求动态设置租户 ID,但它不适用于自定义查找器 查找* 存储库上的方法。
我已遵循此指南:http://codecrafters.blogspot.sk/2013/03/multi-tenant-cloud-applications-with.html

我的 存储库 看起来像这样:

public interface CountryRepository extends PagingAndSortingRepository<Country, Long> {

Country findByName(String name);
Country findByIsoCountryCode(String isoCountryCode);

}

当我调用任何自定义查找器时出现以下错误 查找* 存储库接口(interface)上的方法:
javax.persistence.PersistenceException: Exception [EclipseLink-6174] (Eclipse Persistence Services - 2.5.2.v20140319-9ad6abd): org.eclipse.persistence.exceptions.QueryException
Exception Description: No value was provided for the session property [eclipselink.tenant-id]. This exception is possible when using additional criteria or tenant discriminator columns without specifying the associated contextual property. These properties must be set through Entity Manager, Entity Manager Factory or persistence unit properties. If using native EclipseLink, these properties should be set directly on the session.
Query: ReadAllQuery(referenceClass=Country sql="SELECT ID, TENANT_ID, CONTINENT, CREATED_BY, CREATED_DATETIME, CURRENCY, INDEPENDENTFROM, ISOCOUNTRYCODE, LONGNAME, MODIFIED_BY, MODIFIED_DATETIME, NAME, POPULATION, REC_VERSION FROM COUNTRY WHERE ((NAME = ?) AND (TENANT_ID = ?))")
at org.eclipse.persistence.internal.jpa.QueryImpl.getSingleResult(QueryImpl.java:547)
at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getSingleResult(EJBQueryImpl.java:400)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:360)
at com.sun.proxy.$Proxy56.getSingleResult(Unknown Source)
at org.springframework.data.jpa.repository.query.JpaQueryExecution$SingleEntityExecution.doExecute(JpaQueryExecution.java:197)
at org.springframework.data.jpa.repository.query.JpaQueryExecution.execute(JpaQueryExecution.java:74)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.doExecute(AbstractJpaQuery.java:97)
at org.springframework.data.jpa.repository.query.AbstractJpaQuery.execute(AbstractJpaQuery.java:88)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:421)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:381)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:98)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:262)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:111)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy52.findByName(Unknown Source)

我假设 spring 数据生成那些自定义查找器的实现 查找* 初始化阶段的方法并将它们放入当前实体管理器的缓存中,而没有设置租户 ID,我无法在此缓存的实体管理器上设置/更改租户 ID。我正在尝试根据请求动态更改实体管理器上的租户 ID,所以问题是如何更改/设置该缓存实体管理器上的租户 ID,当我调用任何自定义查找器时会使用它 查找* 方法。

这是我的 Multi-Tenancy querydsl 存储库实现:
public class MultiTenantQueryDslJpaRepository<T, ID extends Serializable> extends QueryDslJpaRepository<T, ID> {
private final CurrentTenantResolver currentTenantResolver;
protected final EntityManager entityManager;

public MultiTenantQueryDslJpaRepository(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager, CurrentTenantResolver currentTenantResolver) {
this(entityInformation, entityManager, SimpleEntityPathResolver.INSTANCE, currentTenantResolver);
}

public MultiTenantQueryDslJpaRepository(JpaEntityInformation<T, ID> entityInformation, EntityManager entityManager, EntityPathResolver resolver, CurrentTenantResolver currentTenantResolver) {
super(entityInformation, entityManager, resolver);
this.currentTenantResolver = currentTenantResolver;
this.entityManager = entityManager;
}

protected void setCurrentTenant() {
entityManager.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT, currentTenantResolver.getCurrentTenantId());
}

@Override
protected JPQLQuery createQuery(final Predicate... predicate) {
setCurrentTenant();
return super.createQuery(predicate);
}

@Override
public void delete(final T entity) {
setCurrentTenant();
super.delete(entity);
}

@Override
public T findOne(final ID id) {
setCurrentTenant();
return super.findOne(id);
}

@Override
public void deleteInBatch(final Iterable<T> entities) {
setCurrentTenant();
super.deleteInBatch(entities);
}

@Override
public void deleteAllInBatch() {
setCurrentTenant();
super.deleteAllInBatch();
}

@Override
public T getOne(final ID id) {
setCurrentTenant();
return super.getOne(id);
}

@Override
public boolean exists(final ID id) {
setCurrentTenant();
return super.exists(id);
}

@Override
protected TypedQuery<T> getQuery(final Specification<T> spec, final Sort sort) {
setCurrentTenant();
return super.getQuery(spec, sort);
}

@Override
public long count() {
setCurrentTenant();
return super.count();
}

@Override
protected TypedQuery<Long> getCountQuery(final Specification<T> spec) {
setCurrentTenant();
return super.getCountQuery(spec);
}

@Override
public <S extends T> S save(final S entity) {
setCurrentTenant();
return super.save(entity);
}
}

最佳答案

该解决方案基于 Eclipse-link 对 BindCallCustomParameter 的特定处理,该处理作为租户持有者添加到 EM 属性映射中。

public class TenantHolder extends BindCallCustomParameter {

private final TenantResolver tenantResolver;

private String defaultTenant;

public TenantHolder(String defaultTenant, TenantResolver tenantResolver) {
this.defaultTenant = defaultTenant;
this.tenantResolver = tenantResolver;
}

public String getDefaultTenant() {
return defaultTenant;
}

@Override
public void set(DatabasePlatform platform, PreparedStatement statement, int index, AbstractSession session) throws SQLException {
String resolvedTenant = resolveTenant();
platform.setParameterValueInDatabaseCall(resolvedTenant, statement, index, session);
}

private String resolveTenant() {
return tenantResolver.resolveTenant(defaultTenant);
}

}

关于eclipselink - 使用 spring data jpa 和 eclipselink 进行 Multi-Tenancy ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26588525/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com