我在JPA多对多单向关系方面遇到困难。问题是在DB中创建重复的Label实体,即使它们是相同的。出于性能原因,@ Id是生成的数字而不是Label.label。连接的问题是findByLabel()找不到这两个音符。
我阅读了很多文章和示例,我认为我有相似的代码,但它不起作用。任何帮助表示赞赏。
我使用Spring Boot,H2,Spring Data JPA。我正在寻找非XML,纯Java注释解决方案。
存储库:
public interface NoteRepository extends CrudRepository<Note, Long> {
@Query("SELECT a from Note a where ?1 member of a.labels")
List<Note> findByLabel(Label label); }
标签:
@Entity
public class Label {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "label_id")
private Long labelId;
private String label;
protected Label() {
}
public Label(String label) {
this.label = label;
}
public Long getLabelId() {
return labelId;
}
public void setLabelId(Long labelId) {
this.labelId = labelId;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Label)) return false;
Label label1 = (Label) o;
return getLabel().equals(label1.getLabel());
}
@Override
public int hashCode() {
return Objects.hash(getLabel());
}
@Override
public String toString() {
return "Label{" +
"labelId=" + labelId +
", label='" + label + '\'' +
'}';
}
}
注意:
@Entity
public class Note {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "note_id")
private Long noteId;
private String note;
@ManyToMany(
fetch = FetchType.EAGER,
cascade = CascadeType.ALL)
@JoinTable(
name = "Note_Label",
joinColumns = @JoinColumn(
name = "NoteId",
referencedColumnName = "note_id"),
inverseJoinColumns = @JoinColumn(
name = "LabelId",
referencedColumnName = "label_id"))
private Set<Label> labels;
protected Note() {
}
public Note(String note, Set<Label> labels) {
this.note = note;
this.labels = labels;
}
public Note(String note) {
this(note, null);
}
public String getNote() {
return note;
}
public void setNote(String note) {
this.note = note;
}
public Long getNoteId() {
return noteId;
}
public void setNoteId(Long noteId) {
this.noteId = noteId;
}
public Set<Label> getLabels() {
return labels;
}
public void setLabels(Set<Label> labels) {
this.labels = labels;
}
@Override
public String toString() {
return "Note{" +
"note='" + note + '\'' +
", labels='" + labels + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Note)) return false;
Note note1 = (Note) o;
if (!getNote().equals(note1.getNote())) return false;
return getLabels() != null ? getLabels().equals(note1.getLabels()) : note1.getLabels() == null;
}
@Override
public int hashCode() {
int result = getNote() != null ? getNote().hashCode() : 0;
result = 31 * result + (getLabels() != null ? getLabels().hashCode() : 0);
return result;
}
}
测试失败:
@SpringBootTest
@RunWith(SpringRunner.class)
public class NoteRepositoryTest {
@Autowired
private NoteRepository repository;
@Test
public void findByLabel() throws Exception {
String labelAString = "labelA";
Label labelA = new Label(labelAString);
Label labelA1 = new Label(labelAString);
Label labelB = new Label("labelB");
Label labelC = new Label("labelC");
Note note1 = new Note(
"note1", new HashSet<Label>(Arrays.asList(
labelA, labelB)));
Note note2 = new Note(
"note2", new HashSet<Label>(Arrays.asList(
labelA1, labelC)));
repository.deleteAll();
repository.save(note1);
repository.save(note2);
List<Note> actualNotes = repository.findByLabel(labelA);
System.out.println(actualNotes);
assertTrue(actualNotes.size() == 2);
assertTrue(actualNotes.containsAll(Arrays.asList(note1, note2)));
}
}
答案 0 :(得分:0)
正确的代码:
@Test
public void saveAndGet() throws Exception {
String labelAString = "labelA";
Label labelA = new Label(labelAString);
Label labelA1 = new Label(labelAString);
Label labelB = new Label("labelB");
Label labelC = new Label("labelC");
repository.save(labelA);
System.out.println(labelA.getLabelId());
repository.save(labelB);
Iterable<Label> all = repository.findAll();
all.forEach(p ->{
System.out.println(p.getLabel());
System.out.println(p.getLabelId());
});
}