在多租户系统上将Spring Data Rest与EclipseLink结合使用时,会出现QueryException

时间:2019-02-13 13:40:53

标签: spring eclipselink multi-tenant spring-data-rest querydsl

我正在使用Spring数据仓库和EclipseLink创建一个多租户单表应用程序。

但是我无法创建可以调用自定义QueryParameters的存储库。

我的孩子班

@Entity
@Table(name="kid")
@Multitenant
public class Kid {

   @Id
   private Long id;

   @Column(name = "tenant_id")
   private String tenant_id;

   @Column(name = "mother_id")
   private Long motherId;

   //more attributes, constructor, getter and setter
}

我的孩子资料库

@RepositoryRestResource
public interface KidRepository extends PagingAndSortingRepository<Kid, Long>, QuerydslPredicateExecutor<Kid> {}

当我呼叫localhost / kids时,出现以下异常:

Exception [EclipseLink-6174] (Eclipse Persistence Services - 2.7.4.v20190115-ad5b7c6b2a): 
org.eclipse.persistence.exceptions.QueryException\r\nException 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 EntityManager, EntityManagerFactory or persistence unit properties. 
If using native EclipseLink, these properties should be set directly on the session.

当我删除实体上的@Multitenant批注时,一切正常。因此,它肯定与EclipseLink有关。

当我不从QuerydslPredicateExecutor扩展时,它也可以工作。但是然后我必须自己实现所有findBy *。即使这样做,它也会再次中断。将我的KidsRepository更改为:

@RepositoryRestResource
public interface KidRepository extends PagingAndSortingRepository<Kid, Long> {
    Collection<Kid> findByMotherId(@Param("motherId") Long motherId);
}

当我现在呼叫localhost / kids / search / findByMotherId?motherId = 1时,我得到了与上述相同的异常。

我使用本教程通过JPA https://blog.marcnuri.com/spring-data-jpa-eclipselink-configuring-spring-boot-to-use-eclipselink-as-the-jpa-provider/来设置EcpliseLink,这意味着PlatformTransactionManager,createJpaVendorAdapter和getVendorProperties被覆盖。 tenant-id带有一个jwt,只要我不使用QuerydslPredicateExecutor(对于用例是必需的),一切就可以正常工作。

结果是,我们依靠QuerydslPredicateExecutor使用了错误的JpaTransactionManager。我不知道创建了哪一个,但是在EclipseLink Framework代码中有多个断点,没有一个被命中。无论是使用QuerydslPredicateExecutor还是使用自定义的findby方法,都是如此。

我在Google上搜索了很多,并试图覆盖一些基本的EclipseLink方法,但是没有一个起作用。我没办法了。

有人知道如何解决或解决此问题吗?

2 个答案:

答案 0 :(得分:1)

我一直在寻找解决同一问题的方法;最终的帮助是将Spring的@Transactional批注添加到存储库或调用此自定义查询的任何位置。 (它甚至可以与javax.transactional一起使用。)我们在大多数服务上都使用了@Transactional批注,因此问题不明显,而且似乎很偶然。

有关在存储库上使用@Transactional的详细说明,请参见:How to use @Transactional with Spring Data?

答案 1 :(得分:0)

我能够通过使用JPAQuery和QueryDsl实现自定义findBy *方法来解决该错误:

@Repository
public class MyDao {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Kid findByMotherId(Long motherId) {
        final JPAQuery<Kid> query = new JPAQuery<>(this.entityManager);
        final QKid kid = QKid.kid;

        return  query.from(kid)
            .where(kid.motherId.eq(motherId))
            .fetchOne();
    }
}

这意味着我必须自己编写所有查询。但是多租户有效。