Spring Boot 使用@OneToManyMap的列上的JPA countBy

wqsoz72f  于 2023-08-04  发布在  Spring
关注(0)|答案(5)|浏览(109)

bounty将在4天后过期。回答此问题可获得+50声望奖励。MaX希望引起更多关注此问题。

我正在尝试对@OneToMany Set列中包含特定字符串的项进行计数。
要做到这一点,在我的JpaRepository<User, String>中,我可以在List<User> findByCompanyIds(String companyId);的结果上使用.size(),它的工作原理就像一个魅力。
但我希望使用long countByCompanyIds(String companyId);,但它不工作,我得到一个queryException。
我必须做一个自定义查询,还是我做错了计数querydsl?

@Entity
@Table(name = "user")
public class User {
    @Id
    @Column(name = "id", nullable = false)
    private String id;

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "companyId",
            joinColumns = @JoinColumn(name = "id"),
            indexes = {
                    @Index(name = "company_ids_index", columnList = "company_ids")
            }
    )
    @Column(name = "company_ids")
    private Set<String> companyIds;

    public User() {
        companyIds = new HashSet<>();
    }
}

个字符
异常跟踪:

org.springframework.dao.InvalidDataAccessApiUsageException: 
 org.hibernate.QueryException: query specified join fetching, but the owner of the fetched association was not present in the select list 
 [FromElement{explicit,collection join,fetch join,fetch non-lazy properties,classAlias=generatedAlias1,role=com.test.User.companyIds,
 tableName={none},tableAlias=companyids1_,origin=user user0_,columns={,className=null}}] [select count(generatedAlias0) 
 from com.test.User as generatedAlias0 left join generatedAlias0.companyIds as generatedAlias1 where generatedAlias1=:param0]

yvfmudvl

yvfmudvl1#

试试这个:
第一个月
我在一个本地项目中测试了这个,它对你的情况很好,很可能语法不完全正确,因为你正在寻找包含某个字符串的东西。

t9eec4r0

t9eec4r02#

如果我理解正确,您在Repository中的查询应该是这样的:

@Query("SELECT COUNT(user) FROM User user LEFT JOIN u.companyIds cP WHERE cP IN :companyId")
Long findBySpecialtiesIn(Set<String> companyId);

字符串
在这个方法的append中,你将传递如下内容

Collections.singleton(companyIds);

vu8f3i0k

vu8f3i0k3#

我认为这不能用countBy查询来实现。您需要使用自定义查询来获取数据。一定要读这个。**https://github.com/spring-projects/spring-data-jpa/issues/2348**第一个字符
使用本机查询,您可以实现这一点

@Query(value = "Select count(*) from User u join company_id c on u.id = c.id AND c.company_ids = :companyId",nativeQuery = true)
int totalCountUserByCompanyId(@Param("companyId") String companyId);

字符串

ldfqzlk8

ldfqzlk84#

我认为您可能需要使用自定义查询,因为它似乎无法正确解释您想要的内容。试试用

@Query("SELECT COUNT(u) FROM User u WHERE :companyId IN u.companyIds")
int totalCountUserByCompanyId(String companyId);

字符串

00jrzges

00jrzges5#

countByCompanyIdsContaining方法的问题在于,它将companyIds集视为单个字符串,这不能按预期工作。为了实现你想要的,你可以使用JPQL查询:

@Query("SELECT COUNT(u) FROM User u WHERE :companyId MEMBER OF u.companyIds")

字符串
但是,如果不想使用自定义查询,另一种解决方案是为公司ID引入@Embeddable值对象。通过这样做,您还可以与最佳实践保持一致,并确保更有组织地表示数据。
下面是公司ID的值对象可能的样子:

@Embeddable
public class CompanyId implements Serializable {

    private String value;

    public CompanyId() {
        // Hibernate requires default constructor
    }

    public CompanyId(String value) {
        this.value = value;
    }

    // Getter, equals and hashCode methods
}


接下来,更新User实体以使用CompanyId类型,并指定应如何使用@AttributeOverride注解Map列:

@Entity
@Table(name = "user")
public class User {
    @Id
    @Column(name = "id", nullable = false)
    private String id;

    @ElementCollection(fetch = FetchType.EAGER)
    @CollectionTable(name = "companyId",
            joinColumns = @JoinColumn(name = "id"),
            indexes = {
                    @Index(name = "company_ids_index", columnList = "company_ids")
            }
    )
    @AttributeOverride(name = "value", column = @Column(name = "company_ids"))
    private Set<CompanyId> companyIds;

    public User() {
        companyIds = new HashSet<>();
    }
}


现在您应该能够使用类似long countByCompanyIdsContaining(CompanyId companyId)的查询

相关问题