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

java - spring jpa 连表重复 join 如何解决?

滑乐逸
2023-12-27
UserEntity
@Data@Accessors(chain = true)@Entity@Table(name = "user")public class UserEntity {    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    @Column(name = "id")    private Long id;    @OneToOne(mappedBy = "user", fetch = FetchType.LAZY)    @JsonManagedReference    private UserArchiveEntity userArchive;}
UserArchiveEntity
@Data@Accessors(chain = true)@Entity@Table(name = "user_archive")public class UserArchiveEntity {    @Id    @Column(name = "user_id")    private Long userId = 0L;    @OneToOne(fetch = FetchType.LAZY)    @JoinColumn(name = "user_id", insertable = false, updatable = false)    // 从属关系:从;一定要加这个,避免json序列化循环引用导致报错    @JsonBackReference    private UserEntity user;    @ManyToOne(fetch = FetchType.LAZY)    @JoinColumn(name = "nation_id", insertable = false, updatable = false)    private NationEntity nation;    @ManyToOne(fetch = FetchType.LAZY)    @JoinColumn(name = "industry_id", insertable = false, updatable = false)    private IndustryEntity industry;}
UserRepository
@Repositorypublic interface UserRepository extends JpaRepository<UserEntity, Long>, JpaSpecificationExecutor<UserEntity> {    @EntityGraph(attributePaths = {"userArchive", "userArchive.nation", "userArchive.industry"})    @NotNull    @Override    Page<UserEntity> findAll(@NotNull Specification<UserEntity> specification, @NotNull Pageable pageable);

我的查询如下:

public List<UserEntity> recommend(int size) throws Exception {        UserEntity userEntity = UserContext.get();        Optional<UserArchiveEntity> optionalUserArchiveEntity = this.userArchiveRepository.findByUserId(userEntity.getId());        if (optionalUserArchiveEntity.isEmpty()) {            throw new Exception("用户档案记录不存在");        }        UserArchiveEntity userArchiveEntity = optionalUserArchiveEntity.get();        Integer gender = userArchiveEntity.getGender();        Integer judgeGender = gender == UserArchiveEntity.GENDER_MALE ? UserArchiveEntity.GENDER_FEMALE : UserArchiveEntity.GENDER_MALE;        Specification<UserEntity> specification = (root, query, criteriaBuilder) -> {            Predicate predicate = criteriaBuilder.conjunction();            Join<UserEntity, UserArchiveEntity> userArchiveEntityJoin = root.join("userArchive", JoinType.LEFT);            return predicate;        };        Sort sort = Sort.by(Sort.Direction.DESC, "infoCompletedRatio");        Pageable pageable = PageRequest.of(0, size, sort);        return this.userRepository.findAll(specification, pageable).getContent();    }

出现的问题:

  1. 上述代码生成的sql针对 userArchiveleft join 两次!即 user left join userarchive on xxx left join userarchive on xxx left join nation on xx on left join industry on xx,该如何避免重复 join
  2. findAll 方法针对不同的业务场景关联的实体要求不一样;但是 spring jpa 没法声明方法签名一致的方法,也没法随意声明不同名称的方法(需要符合 spring jpa 的规范名称才会被正确解析),且由于要支持动态条件查询,必须要有 specification 这种 criterial 标准api 。该如何针对不同业务场景实现不同的模型关联?

共有1个答案

锺离韬
2023-12-27

使用QueryDSL查询框架来解决
链接:博客园上关于QueryDSL的介绍和使用说明:为 JPA 插上翅膀的 QueryDSL

或者在字段上添加注解

@JoinColumn(name = "column_name", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))

使得原来的外键链接变成逻辑链接,在查询时就会分开查

 类似资料:
  • 本文向大家介绍如何使用LEFT JOIN从MySQL表中删除重复值?,包括了如何使用LEFT JOIN从MySQL表中删除重复值?的使用技巧和注意事项,需要的朋友参考一下 让我们首先创建一个表- 使用插入命令在表中插入一些记录- 使用select语句显示表中的所有记录- 这将产生以下输出- 以下是从MySQL表中删除重复值的查询- 让我们再次检查表记录。 这将产生以下输出-

  • 前面小节介绍了表的设计三范式和单表的查询,本小节介绍如何将通过多个表进行关联查询数据,其中连表查询包括 LEFT JOIN、INNER JOIN、RIGHT JOIN。前面小节介绍过表的设计,其中有学生信息表 student、教师信息表 teacher、课程表 course、学生选课关联表 student_course。 1.插入表测试数据 为了演示方便,分别清空学生信息表 student、教师信

  • 我有一根这样的绳子。 如何在Java中将字符串解析成多行?

  • 我试图写这个来获取列表,我必须将ID列表作为参数传递: 我的实体是我用来查询的实体是: 但我在运行后遇到了以下异常: 有人能帮我用上面的方法获取列表吗?或者能告诉我我在这方面做错了什么。我不想使用本机,即(nativeQuery=true)使用这个。

  • 1、通过JavaScript屏蔽提交按钮(不推荐) 2、给数据库增加唯一键约束(简单粗暴) 3、利用Session防止表单重复提交(推荐) 4、使用AOP自定义切入实现

  • 我想写一个这样的链表: 这是我迄今为止尝试过的,但显然是错误的。我想知道如何用java正确地表达这一点? 谢谢