使用sharding-jdbc时实体自关联问题如何解决?

发布于 2022-09-13 01:27:40 字数 2766 浏览 14 评论 0

在使用JPA+sharding-jdbc时,遇到了实体自关联时查询错误问题,分析主要原因是sharding-jdbc做了查询优化,如果查询语句中使用分表列作为条件,就只会路由到1个分表中查询,不会查询所有分表,这对于自关联实体是不合理的。

User.java

@Entity
@Table("t_user")
@Data
@Builder
class User {

    @Id
    private Long id;

    private String name;

    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable(name = "t_parent_children",
        joinColumns = @JoinColumn(name = "parent", foreighKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT)),
        inverseJoinColumns = @JoinColumn(name = "children", foreignKey = @ForeignKey(name = "none", value = ConstraintMode.NO_CONSTRAINT)))
    @Builder.default
    private List<User> children = new ArrayList<>();

    @ManyToMany(fetch = FetchType.LAZY, mappedBy = "children")
    @org.hibernate.annotations.ForeignKey(name="none")
    @Builder.default
    private List<User> parents = new ArrayList<>();
}

application.yml

spring:
  ...
  shardingsphere:
    datasource:
      ...
    sharding:
      tables:
        t_user:
          actual-data-nodes: dbname.t_user_$->{0..9}
          key-generator:
            type: SNOWFLAKE
            column: id
          table-strategy:
            inline:
              sharding-column: id
              algorithm-expression: t_user_$->{id % 10}
    props:
      sql:
        show: true
  ...

测试数据

User father = User.builder().id(1).name("father").build();
userRepository.save(father);

User son = User.builder().id(2).name("son").build();
son.getParents().add(father);
father.getChildren().add(son);
userRepository.save(son);

User daughter = User.builder().id(3).name("daughter").build();
daughter.getParents().add(father);
father.getChildren().add(daughter);
userRepository.save(daughter);

UserRepository.java

@Repository
public interface UserRepository extends JpaRepository<User,Long> {
    
    @Query("select c from User p join p.children c where p.id = ?1")
    public List<User> findByParent(Long id);
}

测试用例

@Test
public void test() {
    List<User> children = userRepository.findByParent(1L);
    assertEquals(2, children.size()); // expect 2, but is 0
}

sharding日志

Actual SQL: slave ::: 
select user1.id as user1_id,user1.name as user1_name 
from t_user_1 user0 
inner join t_parent_children parent_children1 on arent_chidlren.parent = user0.id 
inner join t_user_1 user1 on parent_children1.children = user1.id 
where user0.id=? 
::: [1]

用户表中3条数据,根据分表规则分别在t_user_1,t_user_2,t_user_3表中,查询时根据father id=1查询,sharding只查询了t_user_1, 因此查不到son和daughter两条数据,如何解决呢?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

海螺姑娘 2022-09-20 01:27:40

这个问题后续如何解决的呢

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文