【问题标题】:Spring Boot: How to use multiple schemas and dynamically choose which one to use for every request at runtimeSpring Boot:如何使用多个模式并在运行时为每个请求动态选择使用哪一个
【发布时间】:2016-10-02 19:19:55
【问题描述】:

前提: 我选择这样做是因为我最终可能会拥有几千个模式,每个模式都有(以及其他)1 个包含几百万个条目的表。另一种方法是(除其他外)一个表,在一个模式中包含数十亿个条目。

详细说明这个问题的最佳方法是提供一个简单的示例。考虑以下几点:

用户.java

@Entity(name = "user")
public class User {
    @Id
    @GeneratedValue
    @Column(name = "id")
    private Long id;

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

    // getters and setters...
}

UserDao.java

@Repository
public interface UserDao extends CrudRepository<User, Long> {}

用户服务.java

public interface UserService {
    User getUser(Long id);
}

UserServiceBean.java

@Transactional
@Service
public class UserServiceBean implements UserService {
    @Autowired
    private UserDao dao;

    @Override
    public User getUser(Long id) {
        return dao.findOne(id);
    }
}

UserController.java

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @RequestMapping(
            value = "/api/users/{id}",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<User> getUser(
            @PathVariable("id") Long id) {

        User user = userService.getUser(id);
        return new ResponseEntity<User>(user, HttpStatus.OK);
    }
}

我想扩展以下功能:在 URL 中提供另一个 ID,以便从不同的表返回用户数据。

UserController.java

...
@RequestMapping(
            value = "/api/users/{id}",
            method = RequestMethod.GET,
            produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity<User> getUser(
            @PathVariable("id") Long id,
            @RequestParam(value = "tlbid") Long tblId) {

        User user = userService.getUser(id, tblId);
        return new ResponseEntity<User>(user, HttpStatus.OK);
    }

现在,UserService 会将该 ID 解码为对 spring 有用的东西,以便从不同的表中获取数据。

UserServiceBean.java

    ...
    public User getUser(Long id, Long tblId) {
        Object o = doMagic(tblId);
        // What should 'o' be and how could I use this?
    }

所有表的结构和名称都相同,但条目不同。这些表必须在不同的数据库中,或者在同一个数据库中但在不同的模式中。

我也想知道:

a) 我怎样才能拥有一个数据库连接并为每个请求指定不同的架构。

b) 如何在必要时创建新的数据库连接(我会为进一步的请求维护它们),并指定每次应该在哪个连接上发出请求。

c) 我的前提是错误的,表中有数十亿个条目,高并发不会显着降低查询速度。

【问题讨论】:

  • 我觉得是 c)。无论哪种情况,您都不应该将您对数据库分区的尝试泄漏到 api 中。 (paperplanes.de/2011/12/9/the-magic-of-consistent-hashing.html 左右可能适合你)
  • 我担心这样的表在增长时会自动重新组织多次(为了有效的散列)并且并发更改会使其变慢。
  • 10 亿行表优于 1000 万行表。
  • 嗨,Alin,你能解决你的问题吗?我正在寻找相同问题的解决方案。
  • 嗨@Irtaza。根据 Rick James 的回答,我选择不再走这条路。这是一个大学项目,凭借 4 年后获得的智慧,我很高兴我决定不再增加复杂性并使用单个表格。

标签: java database-design spring-boot


【解决方案1】:

如果您使用的是休眠实体类,那么您始终可以对同一数据源使用不同的架构,前提是其他架构可供映射到数据源中的特定用户访问。

您可以在实体类中使用Table 注释的schema 属性。使用以下语法来使用不同的架构

@Table(name="TABLE_NAME",schema="SCHEMA2")

【讨论】:

  • 这里的问题是如何“动态”更改/切换模式名称以访问具有相同结构的表。这个目的不能通过简单地硬编码实体中的模式名称来解决。
【解决方案2】:

听起来您在描述多租户解决方案。请参阅the Hibernate documentation 以获得更详细的说明和一些关于如何对数据进行分区的选项。

注意:我们目前正在尝试实现基于模式的多租户方法 :)

【讨论】:

  • 这个答案指向正确的方向,而不是仅仅展示解决方法。
猜你喜欢
  • 2017-06-29
  • 1970-01-01
  • 2021-02-17
  • 1970-01-01
  • 2023-03-22
  • 1970-01-01
  • 1970-01-01
  • 2017-05-26
  • 2017-03-14
相关资源
最近更新 更多