【问题标题】:Many to Many relation with embedded key is inserting null in primary key与嵌入键的多对多关系在主键中插入空值
【发布时间】:2020-10-27 02:16:25
【问题描述】:

在中间表中插入记录时遇到问题。 Post 和 Tag 表使用中间表 post_tag 共享多对多关系;

发布表:id (pk)、发布、created_by、created_on、modified_by、modified_on

标签表:id (pk)、tag、created_by、created_on、modified_by、modified_on

Post_Tag 表:post_id、tag_id(pk post_id 和 tag_id)、created_by、created_on、modified_by、modified_on

实体:

// ID class
@Embeddable @Data @NoArgsConstructor @AllArgsConstructor
public class PostTagId
    implements Serializable {
 
    @Column(name = "post_id")
    private Long postId;
 
    @Column(name = "tag_id")
    private Long tagId;
}

@Entity
@Table(name = "post_tag")
@EntityListeners(AuditingEntityListener.class)
@Data
@EqualsAndHashCode(callSuper = false)
public class PostTag extends Auditable<String> {
 
    @EmbeddedId
    private PostTagId id;
 
    @ManyToOne
    @MapsId("postId")
    @JoinColumn(name="post_id")
    private Post post;
 
    @ManyToOne
    @MapsId("tagId")
    @JoinColumn(name="tag_id")
    private Tag tag;
 
    public PostTag(Post post, Tag tag) {
     this.post = post;
     this.tag = tag;
     this.id = new PostTagId(post.getId(), tag.getId());
    }

  }

使用 springboot(AuditingEntityListener) 添加审计列。 Post 和 Tag 实体有点像 -

///////////Tag
    @Data
    @EqualsAndHashCode(callSuper = false, exclude = {"postTags"})
    @ToString( exclude = {"postTags"})
    @Entity
    @Table(name = "tag")
    @EntityListeners(AuditingEntityListener.class)
    public class Tag extends Auditable<String> {
      @Id  
      private Long id;
      
      @Column(name = "tag")
      private String tag;
      
      @OneToMany(mappedBy = "tag", cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
      private Set<PostTag> postTags;
    }

//////////////POST

    @Data
    @EqualsAndHashCode(callSuper = false, exclude = {"postTags"})
    @ToString( exclude = {"postTags"})
    @Entity
    @Table(name = "post")
    @EntityListeners(AuditingEntityListener.class)
    public class Post extends Auditable<String> {
      @Id  
      private Long id;
      
      @Column(name = "post")
      private String post;
      
      @OneToMany(mappedBy = "post", cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
      private Set<PostTag> postTags;
    
      public void addTag(Tag tag) {
        PostTag postTag = new PostTag(this, tag);
        if (postTags == null) {
          postTags = new HashSet<>();
        }
        postTags.add(postTag);
        tag.getPostTags().add(postTag);
      }
    }

使用 addTag() 方法插入标签的代码 sn-p -

public Post create(Post post) {
    // DefaultTag is some default tag getting from repository   
    post.addTag(DefaultTag)
    return postRepo.save(post);
  }

Insert in post_tag 正在尝试插入 null post_id。

 Hibernate: 
     insert 
     into
         post_tag
         (created_by, created_on, modified_by, modified_on, post_id, tag_id) 
     values
         (?, ?, ?, ?, ?, ?) [0;39m [36mo.h.engine.jdbc.spi.SqlExceptionHelper SQL Error: 0, SQLState:
 23502 [0;39m [36mo.h.engine.jdbc.spi.SqlExceptionHelper  ERROR: null
 value in column "post_id" violates not-null constraint   Detail:
 Failing row contains (null, 100, anonymousUser, anonymousUser,
 2020-07-06 15:22:19.227-06, 2020-07-06 15:22:19.227-06).

【问题讨论】:

    标签: spring-boot hibernate spring-data-jpa many-to-many


    【解决方案1】:

    删除@EmbededId 并在 PostTag 类中使用 @Id。这种方式不需要在构造函数中创建 embededId,由 hibernate 处理 id 创建。变化看起来像这样 -

    @Entity
    @Table(name = "post_tag")
    @EntityListeners(AuditingEntityListener.class)
    @Data
    @EqualsAndHashCode(callSuper = false)
    public class PostTag extends Auditable<String> implements Serializable {
     
        @ManyToOne
        @Id
        @JoinColumn(name="post_id")
        private Post post;
     
        @ManyToOne
        @Id
        @JoinColumn(name="tag_id")
        private Tag tag;    
      }
    

    由于 PostTag(Post, Tag) 构造函数被移除,因此需要在 Post 实体中重构 addTag(Tag tag) 方法。

        public void addTag(Tag tag) {
          PostTag postTag = new PostTag();
          postTag.setPost(this);
          postTag.setTag(tag);
          if (postTags == null) {
            postTags = new HashSet<>();
          }
          postTags.add(postTag);
          tag.getPostTags().add(postTag);
       }
        
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-01
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    • 2015-01-11
    • 2015-08-19
    • 1970-01-01
    • 2020-02-04
    相关资源
    最近更新 更多