当前位置: 首页 > 知识库问答 >
问题:

在SpringJPA中应用多坚韧的通用标准的最佳实践?

颜实
2023-03-14

我正在构建一个具有多个租户(即客户)的企业应用程序(SaaS)。同一函数的不同客户之间的数据存储在同一个表中,我使用一个名为“site_id”的列来定义数据的所有权。它看起来像这样:

PurchaseOrder:
- int id
- int site_id
- String product_name
- int quantity

在每个请求中,过滤器处理会话信息,以确定该用户可以访问哪个站点。这些数据存储在一个静态线程局部变量中,该变量可以从名为< code>Set的静态方法中检索

现在,对于自动创建的存储库的“findAll”查询,它们还将返回其他客户的数据

例如,现在我有了这样的接口

public interface PurchaseOrderRepository implements CrudRepository<PurchaseOrder, int> {
  List<PurchaseOrder> findAll();
}

我正在处理一个用户的请求,我知道该用户只能访问3,4中的site_id。我想让findAll仅使用(3,4)site_ id返回数据。SQL应该看起来像<code>select*from purchase_order,其中site_id在(?,)中

当然,我可以手工创建每个查询以始终添加一个,其中site_id = ? 子句,但这不仅繁琐而且很容易被我未来的队友忘记。我查看了@Query注释,但没有帮助,因为我无法将动态变量(site_id)放入其中。

有没有一种方法可以改变Spring负责神奇地实现那些存储库方法的逻辑,这样我就可以用一条动态信息(来自线程本地类静态变量)以编程方式注入我的< code>where子句?

这个概念有点像RubyonRails的ActiveRecord<code>scope<code>概念,带有lamda风格。理想情况下,所有涉及具有“site_id”的表的查询都将自动包含此条件,除非涉及某些特殊过程(功能块注释禁用此条件)。

到目前为止,我一直在研究这些选择,但还没有决定结果:

  • 规范执行器(Spring Boot

更新:本文提供了Spring中多租户的所有三种解决方案:https://medium.com/swlh/multi-tenancy-implementation-using-spring-boot-hibernate-6a8e3ecb251a

共有2个答案

壤驷旭
2023-03-14

Spring为此类需求提供了两种解决方案,您可以在存储库中本地使用Query,并像这样向其发送绑定列表

java prettyprint-override">public interface PurchaseOrderRepository implements CrudRepository<PurchaseOrder, int> {
    @Query(value = "select * from purchase_order where site_id in (?)", nativeQuery = true)
    List<PurchaseOrder> findAll(List<Integer> in);
}

或者,如果您正在寻找一种更动态的方式来构建自己的可定制查询,您可以使用Spring JDBC模板,它具有强大的API,可以完美地处理您的情况。使用它定义您自己的DAO,并实现一些要调用的helpers方法。

检查这个很好的参考Spring JDBC模板示例

因此,您可以制作查询构建器,它将表名和 where 条件作为参数(如果列的名称不同,则为此设置);为了避免将来的混淆,请为该方法选择一个好名称,例如findAllByTableIn(String tableName,List in)

另请注意,您必须在目标数据源上配置 JDBCTemplate,该数据源将是访问正确数据库上的表的租户之一。

花玄裳
2023-03-14

JPA的Spring数据在这里无能为力。通常,您正在寻找Hibernate多租户。具体来说,您正在寻找鉴别器列多租户。但我认为即使是在最新的Hibernate版本中,它也尚未实现。

或者,您可以使用@Filter注释推出自己的解决方案:

@FilterDef(
    name = "tenantFilter", 
    parameters = @ParamDef(name = "tenant", type = "int")
)
@Filter(
    name = "tenantFilter", 
    condition = "tenant_id = :tenant"
)
public class BaseEntity implements Serializable {
 类似资料:
  • 问题内容: 我们在项目中使用SLF4J + Logback组合已经有一段时间了,并且对此感到满意,但是我们的日志记录策略非常简单,使用基于类的简单记录器,没有像MDC或Markers这样的奇特的东西。 我想知道的是,社区中是否有人真的使用了这些功能,以及它们如何用于改善日志记录/过滤功能。 我对在哪里,为什么以及如何使用[1]标记进行记录特别感兴趣。它们为我添加了一个很好的功能,将语义上下文添加到

  • 问题内容: 在python中,您通常使用PEP 8-Python代码样式指南 作为您的编码标准/准则吗?您还有其他更喜欢的正式标准吗? 问题答案: “在python中,您通常使用PEP 8-Python代码样式指南作为您的编码标准/准则吗?您是否还需要其他正式的标准?” 如您所提到的,请遵循PEP 8作为主要文本,并遵循PEP 257 作为文档字符串约定 与Python样式指南一起,建议您参考以下

  • 问题内容: 我们有一个大型Angularjs 1.6应用程序,该应用程序的$ rootscope分散在整个应用程序的过滤器,服务,路由等200多个位置中。因此需要对其进行重构,但是我不确定如何知道何时将其删除。什么时候在应用程序中使用$ rootscope是最佳实践? 我已经阅读了所有内容,从没读过,到用它来存储变量,我都以为是在控制器之间共享数据。从那以后,我读到最好在这种用例中使用工厂/服务,

  • 问题内容: 我想知道是否存在某种“标准”用于在数据库中存储美国地址?看来这是一项常见的任务,应该有某种标准。 我正在寻找的是数据库表应如何工作和交互的 特定 模式,已经是第三种标准形式,包括数据类型(MySQL)。一个好的UML文档将起作用。 也许我只是在偷懒,但这是一个非常常见的任务,而且我确信有人发布了在某处进行此操作的有效方法。我只是不知道在哪里寻找,而Google并没有帮助。请指出我的资源

  • 当多次调用保存时,它可以工作,但需要几分钟。 在我的理解中,保存执行。 因此,如果我可以将放在一起,则需要更短的时间。 有没有这方面的做法?

  • 我有一个存储库层,有许多方法组合,以匹配搜索标准…重用这个标准的最佳方法是什么?我认为像FindByNameAndidandBirthdayandAccouncAnumber这样的方法名称不是一个好主意!谢了! }