在Hibernate中共享具有唯一值的公用表

时间:2018-02-02 10:31:20

标签: java hibernate

我一直试图了解如何使用hibernate创建一个通用的标签资产库,但我无法让它工作。

我希望它看起来像这样:

Unique tag library

我希望订阅和通知共享相同的唯一标记库。

我尝试了@ManyToMany注释。但我不认为这是做到这一点的方法。在我最好的情况下,我希望Hibernate自动查看标签是否已经存在,然后只使用该ID。但我也可以先创建标签,然后再链接它们。用Hibernate来解决这个问题的最佳方法是什么?

这是我目前的代码:

Subscription.class

@Data
@Entity
public class Subscription {

  @Id
  @GeneratedValue
  @Column(name = "subscription_id")
  private Long id;

  @ManyToMany(cascade = CascadeType.ALL)
  @JoinTable(name = "subscription_tag",
        joinColumns = { @JoinColumn(name = "subscription_id") },
        inverseJoinColumns = { @JoinColumn(name = "tag_id") })
  private List<Tags> tags = new ArrayList<>();

  private String subscriberString;

}

Tags.class

@Data
@Entity
@Table(
    name = "notification_tags",
    uniqueConstraints = @UniqueConstraint(columnNames = "tag")
)
public class Tags {

  @Id
  @GeneratedValue
  @Column(name = "tag_id")
  private Long id;

  private String tag;

}

Notification.class

@Data
@Entity(name = "Notification")
@Table(name = "notification")
@TypeDef(
    name = "jsonb-node",
    typeClass = JsonNodeStringType.class
)
public class Notification extends NotificationBase {

    @Id
    @GeneratedValue
    @Column(name = "notification_id")
    private Long id;

    // This is when the object was created
    private Date updatedTime = new Date();

    private Date timestamp;

    private String name;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "notification_tag",
        joinColumns = { @JoinColumn(name = "notification_id") },
        inverseJoinColumns = { @JoinColumn(name = "tag_id") })
    private List<Tags> tags = new ArrayList<>();

    @Type(type = "jsonb-node")
    @Column(columnDefinition = "NVARCHAR(4000)")
    private JsonNode customJson;

}

1 个答案:

答案 0 :(得分:0)

我有一些关系错了。您应该只有一个类拥有该关系,但另一个类应该引用该关系。

我还使用@JsonManagedReference@JsonBackReference来避免在序列化为json时进行循环引用。

当我想搜索带有标记的所有订阅时,我不需要搜索所有订阅中的标记,反之亦然,所有包含特定标记的订阅。请参阅下面的代码。

SubscriptionRepository.class (查找具有特定标记的所有订阅)

public interface SubscriptionRepository extends CrudRepository<Subscription, Long>{

    List<Subscription> findAllByTag(Tag tag);

}

<强> Subscription.class

@Data
@Entity
public class Subscription {

    @Id
    @GeneratedValue
    @Column(name = "subscription_id")
    private Long id;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "subscription_tag",
        joinColumns = { @JoinColumn(name = "subscription_id") },
        inverseJoinColumns = { @JoinColumn(name = "tag_id") })
    private Set<Tags> tags = new HashSet<>();

    private String subscriberString;

}

<强> Tag.class

@Data
@Entity
@Table(
    name = "notification_tags",
    uniqueConstraints = @UniqueConstraint(columnNames = "tag")
)
public class Tag {

    @Id
    @GeneratedValue
    @Column(name = "tag_id")
    private Long id;

    private String tag;

    @ManyToMany(mappedBy = "tags", cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    @JsonBackReference
    private Set<Subscription> subscriptions = new HashSet<>();

    @ManyToMany(mappedBy = "tags", cascade = { CascadeType.PERSIST, CascadeType.MERGE })
    @JsonBackReference
    private Set<Notification> notifications = new HashSet<>();

    public Tag() {
    }

    @Builder
    public Tag(String tag) {
        this.tag = tag;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        if (!super.equals(o)) return false;
        Tag tag1 = (Tag) o;
        return Objects.equals(tag, tag1.tag);
    }

    @Override
    public int hashCode() {
        return Objects.hash(super.hashCode(), tag);
    }
}

<强> Notification.class

@Data
@Entity(name = "Notification")
@Table(name = "notification")
@TypeDef(
    name = "jsonb-node",
    typeClass = JsonNodeStringType.class
)
public class Notification extends NotificationBase {

    @Id
    @GeneratedValue
    @Column(name = "notification_id")
    private Long id;

    // This is when the object was created
    private Date updatedTime = new Date();

    private Date timestamp;

    private String name;

    @ManyToMany(cascade = CascadeType.ALL)
    @JoinTable(name = "notification_tag",
        joinColumns = { @JoinColumn(name = "notification_id") },
        inverseJoinColumns = { @JoinColumn(name = "tag_id") })
    private Set<Tags> tags = new HashSet<>();

    @Type(type = "jsonb-node")
    @Column(columnDefinition = "NVARCHAR(4000)")
    private JsonNode customJson;

}