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

查询多对多连接表时的Jpa hibernate问题

轩辕啸
2023-03-14

我想管理与映射到联接表的实体的关系。因此我有3个实体类:posttagposttagPostTag具有@ManyToOne注释的PostTag成员。

PostTag及其嵌入的密钥:

@Entity
@Table(name = "post_tag")
public class PostTag {
        
  @EmbeddedId
  private PostTagId id;
    
  @ManyToOne(fetch = FetchType.LAZY)
  @MapsId("postId")
  private Post post;
        
  @ManyToOne(fetch = FetchType.LAZY)
  @MapsId("tagId")
  private Tag tag;
    
  private PostTag() {}
        
  public PostTag(Post post, Tag tag) {
    this.post = post;
    this.tag = tag;
    this.id = new PostTagId(post.getId(), tag.getId());
  }
    
  public PostTagId getId() { return id; }
  public void setId(PostTagId id) { this.id = id; }
  public Post getPost() { return post; }
  public void setPost(Post post) { this.post = post; }
  public Tag getTag() { return tag; }
  public void setTag(Tag tag) { this.tag = tag; }
}

@Embeddable
public class PostTagId implements Serializable {
     
  @Column(name = "post_id")
  private Long postId;
     
  @Column(name = "tag_id")
  private Long tagId;
     
  public PostTagId() {}
     
  public PostTagId(Long postId, Long tagId) {
    this.postId = postId;
    this.tagId = tagId;
  }
     
  public Long getPostId() { return postId; }
  public void setPostId(Long postId) { this.postId = postId; }
  public Long getTagId() { return tagId; }
  public void setTagId(Long tagId) { this.tagId = tagId; }
}

当我需要带有给定标记的帖子时,我希望使用以下查询:

@Query(value = "select pt from PostTag pt join fetch pt.post where pt.id.tagId = :tagId")
Set<PostTag> findByTagIdAndFetchPosts(@Param("tagId") Long tagId);
    2020-08-25 10:21:57.486 DEBUG 16791 --- [           main] org.hibernate.SQL                        : 
        select
            posttag0_.post_id as post_id1_1_0_,
            posttag0_.tag_tag_id as tag_tag_2_1_0_ 
        from
            post_tag posttag0_ 
        where
            posttag0_.post_id=? 
            and posttag0_.tag_tag_id=?
    2020-08-25 10:21:57.487  WARN 16791 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 42122, SQLState: 42S22
    2020-08-25 10:21:57.487 ERROR 16791 --- [           main] o.h.engine.jdbc.spi.SqlExceptionHelper   : Column "POSTTAG0_.TAG_TAG_ID" not found; SQL statement:
    select posttag0_.post_id as post_id1_1_0_, posttag0_.tag_tag_id as tag_tag_2_1_0_ from post_tag posttag0_ where posttag0_.post_id=? and posttag0_.tag_tag_id=? [42122-200]

整件事都在这里:

https://github.com/riskop/jpa_hibernate_spring_boot_many_to_many_managed_on_join_table_problem

共有1个答案

阴高刚
2023-03-14

使用@mapsid时,hibernate实际上会忽略@embeddable类适当字段的@column注释中提供的列名,并开始使用@joincolumn中的名称。如果@joincolumn不存在,则应用默认约定(引用关系属性的名称的串联;“_”;引用的主键列的名称)。

您有:

@Entity
public class Tag {

    @Id
    @Column(name="TAG_ID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    // ...
}

@Entity
@Table(name = "post_tag")
public class PostTag {
    
    @EmbeddedId
    private PostTagId id;

    // There is no @JoinColumn annotation !!!
    // So, the default naming convention is used 
    // "tag" + "_" + "tag_id"
    // "tag_id" is the Tag's entity PK column name
    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("tagId")
    private Tag tag;
    
    // ...
}

因此,您可以通过以下方式修复映射:

@Entity
@Table(name = "post_tag")
public class PostTag {
    
    @EmbeddedId
    private PostTagId id;

    // by chance the default naming convention 
    // lead to the same column name for this case
    @MapsId("postId")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "post_id") 
    private Post post;
    
    @MapsId("tagId")
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "tag_id")
    private Tag tag;

    // ...
}
@Embeddable
public class PostTagId implements Serializable {
 
    private Long postId;
 
    private Long tagId;
    // ...
}
 类似资料:
  • 我有2个具有多对多关系的实体User和AcCountBase。我需要从连接表中选择所有具有选定用户ID的AcCountBase对象。我尝试了一些连接查询,但不起作用。

  • 给定两个具有一对多关系的表(SQLServer的脚本): 一个人只有一个地址,但同一地址可以链接到多个不同的人。 还有一个Spring JPA存储库,其中包含一个显式查询: 使用Hibernate作为JPA提供程序,会为该查找方法生成类似的SQL: 因为我对表中的任何数据都不感兴趣,而且我已经知道了,所以似乎没有真正需要连接: 这个查询给出了相同的结果。 我是否可以让JPA/Hibernate在没

  • 我的实体是用户和角色。它们之间存在着多对多的关系。角色的获取在用户中是惰性的。 我想在一个查询中得到用户和规则数据。所以我试着用JPQL得到这些数据。我的用户库是 我记录我的查询与数据源代理,我有两个查询,但我没有离开加入一个查询。为什么不做一个查询? 我的日志是

  • 问题内容: 我遇到了麻烦。 有一个实体发行人与与实体镇的ManyToMany关系有关: 那么实体镇也与地区有关 现在,我必须过滤(使用jpql)一个区域中的所有分发服务器。我能怎么做? 问题答案: 请参阅:https://en.wikibooks.org/wiki/Java_Persistence/JPQL

  • 问题内容: 我想在以下(简化的)数据库中应用JPA: 因此,一个节点可以具有多个权限,并且一个权限可以被多个节点引用。 我希望我的班级看起来像这样: 但是注释“ @ManyToMany”似乎仅可用于“ @JoinTable”,在这种情况下,它不可用(据我所知)。有人知道修改数据库之外是否还有其他方法吗? 问题答案: JPA不允许这样做,因为它需要外键来引用完整的主键以用于标识目的,并且它可能不适用

  • 我的数据模型中有以下实体关系。 ERD Hibernate实体: 要求:我想用实体B的连接获取查询实体C,同时也急切地获取实体D。查询完成后,我希望如果我执行,它不应导致hibernate中的N 1查询问题。 我正在尝试以下JPQL查询: 这导致结果重复,因为与实体D交叉连接。我得到的不是一个结果,而是n个结果,其中n是实体D列表的大小。 我该如何避免这种情况?有没有办法在JPQL中不交叉连接地获