如何向Spring数据JPA Default和Dervied查询添加租户条件

如何向Spring数据JPA Default和Dervied查询添加租户条件,spring,spring-boot,spring-data-jpa,Spring,Spring Boot,Spring Data Jpa,我有一个Springboot应用程序,它的存储库中有Spring数据JPA查询,如findOne、findAll,还有派生的查询,如findByID或findByName等 我想要实现的是多租户。所有实体都有一个“account\u id”列,其中包含租户 如何向上述所有查询添加“account\u id”之类的筛选器,而不使用包含findid和accounted(即findone)等名称的派生查询 @存储库 公共接口类别repository扩展了JpaRepository{ 类别findByN

我有一个Springboot应用程序,它的存储库中有Spring数据JPA查询,如findOne、findAll,还有派生的查询,如findByID或findByName等

我想要实现的是多租户。所有实体都有一个“account\u id”列,其中包含租户

如何向上述所有查询添加“account\u id”之类的筛选器,而不使用包含findid和accounted(即findone)等名称的派生查询

@存储库
公共接口类别repository扩展了JpaRepository{
类别findByName(字符串名称);
}
这是对应的实体

@实体
@表(name=“unit”)
@资料
公营课组{
@身份证
@GeneratedValue(策略=GenerationType.AUTO)
私人长id;
私有字符串名称;
@列(name=“account\u id”)
私人长帐号;
}

我知道大多数人使用模式作为租户分离,但这对我来说是不可能的。有没有一种方法(我没有找到)可以在这些查询上添加这样的租户过滤条件,而不必编写NamedQuery或使用DerivedQuery。一个元素解决方案,比如注释存储库或实体,或者所有查询都应该添加额外过滤器“account\u id”的查询。

您可以在实体类上添加Where子句(没有时间测试)


更新和解决方案 1.在实体上创建一个过滤器&FilterDef,如下所示

@FilterDef(name="accountFilter", parameters=@ParamDef( name="accountId", type="long" ) )
@Filters( {
        @Filter(name="accountFilter", condition=":accountId = account_id")
} )
public class Category {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    private String name;

    @Column(name = "account_id")
    private Long account_id;
}
  • 通过自动连接entitymanager,在控制器中启用筛选,编写一个方法来启用筛选器并在@ModelAttribute中为每个请求激活筛选器

  • 你好,马克,请阅读这篇文章。也可以缩短您的问题,让其他人很容易帮助您!好的,我已经重读了《如何提问》并将问题缩短了很多。希望这有帮助。是的,您可以将
    @where
    子句添加到实体,但我还没有找到在使用派生qureise时设置参数的方法。我可以找到的所有带有
    @where
    的EAMPLE都使用EntityManager,然后使用createquery。
    @Where
    注释可以与Sprint数据JPA和dervied需求一起使用吗?你能举个例子吗?@where子句不支持变量。您必须使用“Filter”和“FilterDef”查看解决方案。附带说明-此方法仅适用于查询。当您尝试通过回购中的findById访问实体时,基础方法使用带有实体id的“find”来获取实体,而不是查询,并忽略过滤器,该过滤器将限制对未分配给租户的实体的访问。一种对我有效的方法是创建一个自定义存储库(接口+实现),它扩展了JPARepository,并在其中覆盖findById方法。在我的方法中,我创建了一个自定义查询,该查询创建了一个查询,因此应用了过滤器。当然,所有回购协议都必须使用此回购协议如果您需要定义自定义回购协议并在其中创建查询,您不能使用query开始并定义where子句并避免所有上述代码吗
    @Query(“从记录r中选择r,其中u.tenantId=?”)
    @FilterDef(name="accountFilter", parameters=@ParamDef( name="accountId", type="long" ) )
    @Filters( {
            @Filter(name="accountFilter", condition=":accountId = account_id")
    } )
    public class Category {
        @Id
        @GeneratedValue(strategy=GenerationType.AUTO)
        private Long id;
    
        private String name;
    
        @Column(name = "account_id")
        private Long account_id;
    }
    
    @RestController
    @RequestMapping(path = "/categories",produces = MediaType.APPLICATION_JSON_VALUE )
    public class CategoryController {
        private final CategoryRepository repository;
    
        @Autowired
        private EntityManager entityManager;
    
        CategoryController(CategoryRepository repository) {
            this.repository = repository;
        }
    
        private void activateFilter() {
            Session session = entityManager.unwrap(Session.class);
    
            Filter filter = session.enableFilter("accountFilter");
            filter.setParameter("accountId", Long.valueOf(TenantContext.getCurrentTenant()));
    
    
        }
        @ModelAttribute
        public void initFilter() {
            activateFilter();
        }
    
        ... your rest methods here
    
    }