查询多对多jpa

Query Many-to-many jpa

我需要在 @QUERY 中实现具有多对多关系的 SELECT。也许我误解了文档中写的信息。 我的查询如下所示:

@Query("select massages.id from massages join string_massage on massages.id = string_massage.massage_id where string_massage.string_id = ?1")
List<MasageEntity>  findMassagesIdByStringId(@Param("strings_id") long strings_id);

在我的示例中,我使用 table 个名称。名称下划线表示错误(未经编译)。也许我应该使用实体。那么如何处理多对多关系呢?

我将展示我的实体的一部分。

我有两个实体。 MasageEntityRstringEntity.

//MasageEntity
@Entity
@Table(name = "massages")
public class MasageEntity {
    @Id
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "string_text")
    private String string_text;
    @Column(name = "string_speed")
    private Long string_speed;
    @Column(name = "string_color_type")
    private Long string_color_type;
    @Column(name = "string_color")
    private String string_color;
    @Column(name = "string_timing_type")
    private String string_timing_type;
    @Column(name = "string_timing")
    private String string_timing;
    @Column(name = "showed")
    private Long showed;

    

    @ManyToMany(fetch = FetchType.LAZY,
            cascade = {
                    CascadeType.PERSIST,
                    CascadeType.MERGE
            })
    @JoinTable(name = "string_massage",
            joinColumns = { @JoinColumn(name = "massage_id") },
            inverseJoinColumns = { @JoinColumn(name = "string_id") })
//RstringEntity
@Entity
@Table(name = "string")
public class RstringsEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "name")
    private String name;
    @Column(name="code")
    private String code;


    @ManyToMany(fetch = FetchType.LAZY,
            cascade = {
                    CascadeType.PERSIST,
                    CascadeType.MERGE
            }, mappedBy = "strings")
    @JsonIgnore
    private Set<MasageEntity> masagess = new HashSet<>();
    public  RstringsEntity() {}

在 Spring Boot: native SQL 和 JPQL 中执行查询有多种方法。
在本机查询的情况下,我们使用纯 SQL 语言,在数据库级别定义查询。
在 Java 持久性查询语言 (JPQL) 的情况下,我们通过实体对象定义查询。


方案一,原生查询
您在存储库中创建了本机查询,但要使用它,我们需要将其标记为 SQL nativeQuery = true。框架需要了解您使用的是什么查询语言。 @Query 注解默认使用 JPQL,所以这就是你出错的原因。

@Repository
public interface MessageRepository extends JpaRepository<MassageEntity, Long> {
    //find MessageEntities by String ID via native query 
    @Query(value = "select massages.* from massages join string_massage on massages.id = string_massage.massage_id where string_massage.string_id = ?1", nativeQuery = true)
    List<MassageEntity>  findMassagesByStringIdNativeSQL(@Param("strings_id") long strings_id);

    //find Message IDs by String ID via native query
    @Query(value = "select massages.id from massages join string_massage on massages.id = string_massage.massage_id where string_massage.string_id = ?1", nativeQuery = true)
    List<Long>  findMassagesIdByStringIdNativeSQL(@Param("strings_id") long strings_id);
}


方案二、JPQL查询
示例如何为您的案例定义 JPQL 查询。 JPQL 将在执行期间转换为 SQL。

@Repository
public interface MessageRepository extends JpaRepository<MassageEntity, Long> {

    //find MessageEntities by String ID via JPQL
    @Query("select message from MassageEntity message join message.strings string where string.id = :strings_id")
    List<MassageEntity>  findMassagesByStringIdJPQL(@Param("strings_id") long strings_id);

    //find Message IDs by String ID via JPQL
    @Query("select message.id from MassageEntity message join message.strings string where string.id = :strings_id")
    List<Long>  findMassagesIDByStringIdJPQL(@Param("strings_id") long strings_id);
}

Hibernate 生成的本机查询:

    select
        massageent0_.id as id1_3_,
        massageent0_.string_text as string_t2_3_ 
    from
        massages massageent0_ 
    inner join
        string_massage strings1_ 
            on massageent0_.id=strings1_.massage_id 
    inner join
        string rstringsen2_ 
            on strings1_.string_id=rstringsen2_.id 
    where
        rstringsen2_.id=?

方案三,Spring auto-generated queries
Spring 可以 auto-generate 通过存储库方法定义进行查询。
您的案例示例:

@Repository
public interface MessageRepository extends JpaRepository<MassageEntity, Long> {

    //find MessageEntities by String ID
    List<MassageEntity> findByStrings_Id(@Param("id") long strings_id);
}

我在解决方案中使用的条目:

@Entity
@Table(name = "massages")
public class MassageEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

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

    @ManyToMany(fetch = FetchType.LAZY,
            cascade = {
                    CascadeType.PERSIST,
                    CascadeType.MERGE
            })
    @JoinTable(name = "string_massage",
            joinColumns = { @JoinColumn(name = "massage_id") },
            inverseJoinColumns = { @JoinColumn(name = "string_id") })
    private Set<RstringsEntity> strings = new HashSet<>();
}

@Entity
@Table(name = "string")
public class RstringsEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(name = "name")
    private String name;
    @Column(name = "code")
    private String code;


    @ManyToMany(fetch = FetchType.LAZY,
            cascade = {
                    CascadeType.PERSIST,
                    CascadeType.MERGE
            }, mappedBy = "strings")
    @JsonIgnore
    private Set<MassageEntity> massages = new HashSet<>();
}