Ich versuche, meine Frühjahr Daten jpa Repositories Multi-Mandanten-Unterstützung hinzufügen. Ich möchte dynamisch die Mandanten-ID pro Anfrage festlegen, aber es funktioniert nicht für den benutzerdefinierten Finder findBy * Methoden auf Repository. Ich habe diese Anleitung gefolgt: http://codecrafters.blogspot.sk/2013/03/multi-tenant-cloud-applications-with.htmlMulti-Tenancy mit Frühjahr Daten jpa und Eclipselink
Mein Repository wie folgt aussieht:
public interface CountryRepository extends PagingAndSortingRepository<Country, Long> {
Country findByName(String name);
Country findByIsoCountryCode(String isoCountryCode);
}
Ich erhalte den Fehler unten, wenn ich eine der benutzerdefinierten finder nennen findBy * Methoden auf die Repository-Schnittstelle:
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)
ich gehe davon aus, dass Daten, die die Feder Durchführung dieser benutzerdefinierten finder erzeugt findBy * Methoden in der Initialisierungsphase und legen Sie sie in einen Cache mit dem aktuellen Entity Manager, ohne dass eine Mandanten-ID festgelegt wurde. Ich kann die Mandanten-ID für diesen zwischengespeicherten Entity Manager nicht festlegen/ändern. Ich versuche, die Tenant-ID im Entity Manager dynamisch pro Anfrage zu ändern, also lautet die Frage, wie kann ich die Tenant-ID in diesem zwischengespeicherten Entity-Manager ändern/setzen, der verwendet wird, wenn ich einen benutzerdefinierten Finder anrufe findBy * Methoden.
Hier ist meine Multi-Tenant-querydsl Repository Implementierung:
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);
}
}
haben Sie Lösung für dieses? –
Ja. Die Lösung basiert auf der Eclipse-Link-spezifischen Behandlung von BindCallCustomParameter, die als Tenant Holder der EM-Eigenschaftszuordnung hinzugefügt wird. – Ati