EclipseLink+SpringDataJPA: Single Table MultiTenan

2019-07-21 06:36发布

问题:

I am using EclipseLink And Spring Data JPA for Single Table Multi-Tenancy.(DISCRIMINATOR based model).

I have customized Spring Data JPA SimpleJPAReposity to add below mentioned and required property on EntityManager.

em.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT,"TENANT_1");

Every Spring Data JPA operations are now handled by CustomizedSimpleJpaRepository. I have configured it successfully and below all Spring DATA JPA operations are working fine, they are automatically adding TENANT_ID to WHERE clause and also set that property to TENANT_1.

  • userRepository.findOne(userName);
  • userRepository.save(user) - FOR CREATE OPERATION
  • userRepository.findAll()
  • userRepository.findByFirstName(userName) - This is custom method defined in

But TENANT_ID is not automatically added for below mentioned operations

  • userRepository.deleteAll()
  • userRepository.delete(userName)
  • userRepository.save(user) - FOR UPDATE OPERATION

I am not able to find any solution for this problem, and worried that for few operations, it is working fine and few not.

Below is my UserRepository and custom SimpleJPARepository which I extends in order to use EclipseLink as stated above.

UserRepository

public interface UserRepository extends CustomizedSimpleJpaRepository<User, String>, JpaSpecificationExecutor<User>{

    User findUserByUserName(String userName);

    User findUserByFirstName(String firstName);
}

CustomizedSimpleJpaRepository

public interface CustomizedSimpleJpaRepository<T, ID extends Serializable> extends JpaRepository<T, ID> {

}

CustomizedSimpleJpaRepositoryImpl

public class CustomizedSimpleJpaRepositoryImpl<T, ID extends Serializable> extends
        SimpleJpaRepository<T, ID> implements
        CustomizedSimpleJpaRepository<T, ID> {

    private final CurrentTenantResolver tenantResolver;
    private final EntityManager em;

    public CustomizedSimpleJpaRepositoryImpl(
            JpaEntityInformation<T, ?> entityInformation, EntityManager em,
            CurrentTenantResolver tenantResolver) {
        super(entityInformation, em);
        em.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT,tenantResolver.getCurrentTenantId());
        this.tenantResolver = tenantResolver;
        this.em = em;
    }

    public CustomizedSimpleJpaRepositoryImpl(Class<T> domainClass,
            EntityManager em, CurrentTenantResolver tenantResolver) {
        super(domainClass, em);
        this.tenantResolver = tenantResolver;
        this.em = em;
    }

    protected void setCurrentTenant() {
        em.setProperty(PersistenceUnitProperties.MULTITENANT_PROPERTY_DEFAULT,
                tenantResolver.getCurrentTenantId());
    }

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

    @Override
    public void delete(ID id) {
        setCurrentTenant();
        super.delete(id);
    };

    /*@Override
    public void delete(T entity) {
        setCurrentTenant();
        super.delete(entity);
    };
*/
    @Override
    public T findOne(ID id) {
        setCurrentTenant();
        return super.findOne(id);
    };

    @Override
    public List<T> findAll() {
        setCurrentTenant();
        return super.findAll();
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.springframework.data.repository.PagingAndSortingRepository#findAll
     * (org.springframework.data.domain.Sort)
     */
    @Override
    public List<T> findAll(Sort sort) {
        setCurrentTenant();
        return super.findAll(sort);
    }

    @Override
    public List<T> findAll(Iterable<ID> ids) {
        setCurrentTenant();
        return super.findAll(ids);
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.springframework.data.repository.CrudRepository#save(java.lang.Iterable
     * )
     */
    @Override
    public <S extends T> List<S> save(Iterable<S> entities) {
        setCurrentTenant();
        return super.save(entities);
    }

    /**
     * Flushes all pending changes to the database.
     */
    @Override
    public void flush() {
        setCurrentTenant();
        super.flush();
    }

    /**
     * Saves an entity and flushes changes instantly.
     * 
     * @param entity
     * @return the saved entity
     */
    @Override
    public T saveAndFlush(T entity) {
        setCurrentTenant();
        return super.saveAndFlush(entity);
    }

    /**
     * Deletes the given entities in a batch which means it will create a single
     * {@link Query}. Assume that we will clear the
     * {@link javax.persistence.EntityManager} after the call.
     * 
     * @param entities
     */
    @Override
    public void deleteInBatch(Iterable<T> entities) {
        setCurrentTenant();
        super.deleteInBatch(entities);
    }

    /**
     * Deletes all entites in a batch call.
     */
    @Override
    public void deleteAllInBatch() {
        setCurrentTenant();
        super.deleteAllInBatch();
    }

    // override the other methods
}

Two more classes are there- CustomizedSimpleJpaRepositoryFactory and CustomizedSimpleJpaRepositoryFactoryBean , but I am not adding code for those as it is not needed.

Why it is not adding TENANT_ID to WHERE clause for above stated operation for DELETE and UPDATE.?