0
JPA 다 대다 단방향 관계에 어려움이 있습니다. 문제는 동일한 레이블 엔티티가 DB에 작성된다는 것입니다. 성능상의 이유로 @Id는 Label.label이 아닌 생성 된 번호입니다. 연결된 문제는 findByLabel()이 두 개의 노트를 찾지 못한다는 것입니다.JPA 다 대다 저장 중복 엔티티
많은 기사와 예제를 읽었으며 비슷한 코드가 있다고 생각하지만 작동하지 않습니다. 어떤 도움을 주셔서 감사합니다.
스프링 부트, H2, 스프링 데이터 JPA를 사용하고 있습니다. 나는 비 XML, 순수 자바 주석 솔루션을 찾고있다.
저장소 :
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)));
}
}
두 개의 별도 Label 인스턴스를 만들고 동일한 "labelA"문자열 값을 제공합니다. 그것들이 동일하게되기를 원한다면 동일한 인스턴스를 전달하거나 save 메소드를 변경하여 새로운 노트가 생기면 먼저 레이블 문자열을 사용하여 참조 된 모든 레이블을 찾습니다. 그렇지 않으면 전달 된 인스턴스에 ID가없는 경우 삽입이 발생합니다. 이 경우에 예외가 필요하면 레이블 문자열을 고유 한 것으로 표시하십시오 - @Column (name = "LABEL", unique = true). 중복이 삽입되면 데이터베이스에서 예외가 발생합니다. – Chris
힌트를 보내 주셔서 감사합니다. 그러나 나는 어떻게이 솔루션을 달성 할 수 있는지 이해하지 못한다. 저장 방법을 변경하여 지속 된 라벨을 찾는다. noterepository.merge를 호출하거나 다른 계단식 설정을 추가하여 자동으로 수행 할 수 있습니까? 나는 스프링 데이터 jpa에 익숙하지 않다. 그러나 B를 가진 데이터 모델은 매우 공통적 일 것이기 때문에, Hibernate는 기성 템플릿을 가지고 있어야한다고 생각한다. ...? – KrystofP
@ 크리스 당신이 도와 드릴까요? – KrystofP