标签已经是一种 ID,因此不需要专门的表格。您只需要questions 表:
create table questions (
id bigint not null constraint questions_pkey primary key,
user_id bigint constraint fk_questions_users references users,
question text not null;
)
和questions_hashtags关系表,索引由hashtag字段:
create table questions_hashtags (
question_id bigint not null fk_questions_hashtags_questions references questions,
hashtag text not null,
constraint uk_questions_hashtags unique (question_id, hashtag)
);
create index index_questions_hashtags_hashtag on questions_hashtags(hashtag);
(这里是 PostgreSQL 方言。)
这些表简单映射到单个(!)实体(不考虑 User 实体):
@Entity
@Table(name = "questions")
public class Question {
@Id
@GeneratedValue
private Long id;
@Column(nullable = false)
private String question;
@ManyToOne(optional = false)
private User user;
@CollectionTable(name = "questions_hashtags", joinColumns = @JoinColumn(name = "question_id"))
@Column(name = "hashtag")
@ElementCollection(fetch = FetchType.EAGER)
@BatchSize(size = 20)
private Set<String> hashtags = new HashSet<>();
public Question(User user, String question) {
this.user = user;
this.question = question;
}
private Set<String> extractHashtags() {
// extract hashtags from question to Set...
}
@PrePersist
@PreUpdate
private void populateHashtags() {
hashtags.clear();
hashtags.addAll(extractHashtags());
}
// other stuff
}
这是一个非常方便的模型。要使用主题标签创建和保存问题,您只需执行以下操作:
questionRepo.save(new Question(user, question));
要获取所有主题标签,您可以使用questionRepo 的这种查询方法:
@Query("select distinct h as hashtag from Question q join q.hashtags h")
List<String> getAllHashtags();
要查找与特定主题标签相关的所有问题,您可以使用以下查询方法:
@Query("select q from Question q join q.hashtags h where h = ?1")
List<Question> getQuestionsByHashtag(String hashtag);
要通过多个主题标签查找问题,您可以使用此方法:
@Query("select q from Question q join q.hashtags h where h in (?1)")
List<Question> getQuestionsByHashtag(Set<String> hashtags);
要查找与给定主题标签相关的用户,您可以使用此方法:
@Query("select distinct u from Question q join q.user u join q.hashtags h where h in (?1)")
List<User> getUsersByHashtag(Set<String> hashtags);
查看我的 REST 服务主题标签使用示例sb-hashtag-usage-example:
1) POST /users - 创建新用户
{
"name": "user1"
}
2) POST /questions - 创建新问题
{
"question": "How implement best JPA #entity #model for Hashtags?",
"user": "/user/1"
}
3) GET /hashtags - 获取所有主题标签
4) GET/questions/search/by_hashtag?hashtag=%23model - 通过一个标签获取问题
5) GET /questions/search/by_hashtags?hashtags=%23entity,%23model - 通过多个主题标签获取问题
6) GET /users/search/by_hashtags?hashtags=%23entity - 通过多个主题标签获取用户
(也可以使用其他方法,如 PATCH、DELETE。)