0

我有一个带有存储库的 Springboot 应用程序,该存储库具有诸如 findOne、findAll 之类的 Spring Data JPA 查询以及诸如 findByID 或 findByName 等派生查询。

我想要实现的是多租户。所有实体都有一个包含租户的“account_id”列。

如何在不使用包含 findIdAndAccountid 等名称的派生查询(即 findone)的情况下向上面提到的所有查询添加类似“account_id”的过滤器

@Repository
public interface CategoryRepository extends JpaRepository<Category, Long> {

    Category findByName(String name);

}

这是对应的实体

@Entity
@Table(name = "unit")
@Data
public class Unit {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    private String name;

    @Column(name = "account_id")
    private Long account_id;
}

我知道大多数人使用模式作为租户分离,但这对我来说是不可能的。有没有办法(我没有找到)在这些查询上添加这样的租户过滤条件,而无需编写 NamedQueries 或使用 DerivedQueries。一个优雅的解决方案,比如注释存储库或实体,或者所有查询都应该添加额外的过滤器“account_id”的查询?

4

2 回答 2

1

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

@Entity
@Table(name = "unit")
@Data
@Where(clause = "account_id= :account_id")
public class Unit {
    @Id
    @GeneratedValue(strategy=GenerationType.AUTO)
    private Long id;

    private String name;

    @Column(name = "account_id")
    private Long account_id;
}

于 2019-10-31T17:22:17.273 回答
0

更新和解决方案 1.像这样在实体上创建一个过滤器和过滤器定义

@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;
}
  1. 通过自动装配entitymanager在控制器中启用过滤,编写一个方法来启用过滤器并在@ModelAttribute中为每个请求激活过滤器
@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

}
于 2019-11-03T13:22:43.793 回答