在多租户系统上使用 Spring Data Rest with EclipseLink 时出现 QueryException

QueryException when using Spring Data Rest with EclipseLink on Multi-Tenant System

我正在使用 Spring 数据剩余和 EclipseLink 创建多租户单一 table 应用程序。

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

我的Kid.class

@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
}

我的 KidRepository

@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 设置 EcpliseLink:https://blog.marcnuri.com/spring-data-jpa-eclipselink-configuring-spring-boot-to-use-eclipselink-as-the-jpa-provider/,意味着 PlatformTransactionManager、createJpaVendorAdapter 和 getVendorProperties 被覆盖。 tenant-id 带有一个 jwt,只要我不使用 QuerydslPredicateExecutor,一切正常,这对于用例是强制性的。

事实证明,我们使用了错误的 JpaTransactionManager,我们依赖于 QuerydslPredicateExecutor。我找不到创建的是哪一个,但在 EclipseLink 框架代码中有多个断点,但没有一个被击中。无论是使用 QuerydslPredicateExecutor 还是使用自定义的 findby 方法,都是如此。

我在谷歌上搜索了很多,并试图覆盖一些基本的 EclipseLink 方法,但没有一个有效。我 运行 没有选择。

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

我正在寻找相同问题的解决方案;最终有帮助的是将 Spring 的 @Transactional 注释添加到存储库或调用此自定义查询的任何地方。 (它甚至适用于 javax.transactional。)我们的大部分服务都有 @Transactional 注释,因此问题并不明显,它的发生似乎是偶然的。

关于在存储库上使用 @Transactional 的更多详细说明在这里:How to use @Transactional with Spring Data?