From 64dd15eaf44bd859f2e2b1ae5834ec09696f4dab Mon Sep 17 00:00:00 2001 From: Chris Franklin Date: Fri, 23 Feb 2018 17:01:23 -0500 Subject: [PATCH] [BAEL-1575] Advanced tagging implementation with JPA --- .../dao/ManyStudentRepository.java | 10 ++++ .../persistence/dao/ManyTagRepository.java | 7 +++ .../persistence/dao/StudentRepository.java | 6 +++ .../inmemory/persistence/model/KVTag.java | 33 ++++++++++++ .../persistence/model/LocationTag.java | 39 ++++++++++++++ .../persistence/model/ManyStudent.java | 34 ++++++++++++ .../inmemory/persistence/model/ManyTag.java | 39 ++++++++++++++ .../inmemory/persistence/model/SkillTag.java | 29 ++++++++++ .../inmemory/persistence/model/Student.java | 29 ++++++++-- .../repository/InMemoryDBIntegrationTest.java | 54 ++++++++++++++++++- 10 files changed, 276 insertions(+), 4 deletions(-) create mode 100644 persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyStudentRepository.java create mode 100644 persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyTagRepository.java create mode 100644 persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/KVTag.java create mode 100644 persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/LocationTag.java create mode 100644 persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyStudent.java create mode 100644 persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyTag.java create mode 100644 persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/SkillTag.java diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyStudentRepository.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyStudentRepository.java new file mode 100644 index 0000000000..a03b2950a0 --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyStudentRepository.java @@ -0,0 +1,10 @@ +package org.baeldung.inmemory.persistence.dao; + +import org.baeldung.inmemory.persistence.model.ManyStudent; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface ManyStudentRepository extends JpaRepository { + List findByManyTags_Name(String name); +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyTagRepository.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyTagRepository.java new file mode 100644 index 0000000000..b7d991de32 --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/ManyTagRepository.java @@ -0,0 +1,7 @@ +package org.baeldung.inmemory.persistence.dao; + +import org.baeldung.inmemory.persistence.model.ManyTag; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ManyTagRepository extends JpaRepository { +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/StudentRepository.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/StudentRepository.java index f856b78c52..ffe1a68558 100644 --- a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/StudentRepository.java +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/dao/StudentRepository.java @@ -15,4 +15,10 @@ public interface StudentRepository extends JpaRepository { @Query("SELECT s FROM Student s JOIN s.tags t WHERE s.name = LOWER(:name) AND t = LOWER(:tag)") List retrieveByNameFilterByTag(@Param("name") String name, @Param("tag") String tag); + @Query("SELECT s FROM Student s JOIN s.skillTags t WHERE t.name = LOWER(:tagName) AND t.value > :tagValue") + List retrieveByNameFilterByMinimumSkillTag(@Param("tagName") String tagName, @Param("tagValue") int tagValue); + + @Query("SELECT s FROM Student s JOIN s.kvTags t WHERE t.key = LOWER(:key)") + List retrieveByKeyTag(@Param("key") String key); + } diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/KVTag.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/KVTag.java new file mode 100644 index 0000000000..ba0071e37b --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/KVTag.java @@ -0,0 +1,33 @@ +package org.baeldung.inmemory.persistence.model; + +import javax.persistence.Embeddable; + +@Embeddable +public class KVTag { + private String key; + private String value; + + public KVTag(){} + + public KVTag(String key, String value) { + super(); + this.key = key; + this.value = value; + } + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/LocationTag.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/LocationTag.java new file mode 100644 index 0000000000..071dc24806 --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/LocationTag.java @@ -0,0 +1,39 @@ +package org.baeldung.inmemory.persistence.model; + +import javax.persistence.Embeddable; + +@Embeddable +public class LocationTag { + private String name; + private int xPos; + private int yPos; + + public LocationTag(){} + + public LocationTag(String name, int xPos, int yPos) { + super(); + this.name = name; + this.xPos = xPos; + this.yPos = yPos; + } + + public String getName() { + return name; + } + + public int getxPos() { + return xPos; + } + + public void setxPos(int xPos) { + this.xPos = xPos; + } + + public int getyPos() { + return yPos; + } + + public void setyPos(int yPos) { + this.yPos = yPos; + } +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyStudent.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyStudent.java new file mode 100644 index 0000000000..98778b8f75 --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyStudent.java @@ -0,0 +1,34 @@ +package org.baeldung.inmemory.persistence.model; + +import javax.persistence.*; +import java.util.HashSet; +import java.util.Set; + +@Entity +public class ManyStudent { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + private String name; + + @ManyToMany(cascade = CascadeType.ALL) + @JoinTable(name = "manystudent_manytags", + joinColumns = @JoinColumn(name = "manystudent_id", referencedColumnName = "id"), + inverseJoinColumns = @JoinColumn(name = "manytag_id", referencedColumnName = "id")) + private Set manyTags = new HashSet<>(); + + public ManyStudent() {} + + public ManyStudent(String name) { + this.name = name; + } + + public Set getManyTags() { + return manyTags; + } + + public void setManyTags(Set manyTags) { + this.manyTags.addAll(manyTags); + } +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyTag.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyTag.java new file mode 100644 index 0000000000..96f9534d43 --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/ManyTag.java @@ -0,0 +1,39 @@ +package org.baeldung.inmemory.persistence.model; + +import javax.persistence.*; +import java.util.HashSet; +import java.util.Set; + +@Entity +public class ManyTag { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private int id; + private String name; + + @ManyToMany(mappedBy = "manyTags") + private Set students = new HashSet<>(); + + public ManyTag() {} + + public ManyTag(String name) { + this.name = name; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Set getStudents() { + return students; + } + + public void setStudents(Set students) { + this.students.addAll(students); + } +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/SkillTag.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/SkillTag.java new file mode 100644 index 0000000000..0300d83d50 --- /dev/null +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/SkillTag.java @@ -0,0 +1,29 @@ +package org.baeldung.inmemory.persistence.model; + +import javax.persistence.Embeddable; + +@Embeddable +public class SkillTag { + private String name; + private int value; + + public SkillTag(){} + + public SkillTag(String name, int value) { + super(); + this.name = name; + this.value = value; + } + + public int getValue() { + return value; + } + + public void setValue(int value) { + this.value = value; + } + + public String getName() { + return name; + } +} diff --git a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/Student.java b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/Student.java index 2e4e3ea2cb..4751a999a0 100644 --- a/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/Student.java +++ b/persistence-modules/spring-jpa/src/main/java/org/baeldung/inmemory/persistence/model/Student.java @@ -1,10 +1,10 @@ package org.baeldung.inmemory.persistence.model; -import javax.persistence.ElementCollection; -import javax.persistence.Entity; -import javax.persistence.Id; +import javax.persistence.*; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Set; @Entity public class Student { @@ -16,6 +16,12 @@ public class Student { @ElementCollection private List tags = new ArrayList<>(); + @ElementCollection + private List skillTags = new ArrayList<>(); + + @ElementCollection + private List kvTags = new ArrayList<>(); + public Student() { } @@ -48,4 +54,21 @@ public class Student { public void setTags(List tags) { this.tags.addAll(tags); } + + public List getSkillTags() { + return skillTags; + } + + public void setSkillTags(List skillTags) { + this.skillTags.addAll(skillTags); + } + + public List getKVTags() { + return this.kvTags; + } + + public void setKVTags(List kvTags) { + this.kvTags.addAll(kvTags); + } + } diff --git a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/InMemoryDBIntegrationTest.java b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/InMemoryDBIntegrationTest.java index 28d7e3772c..fa957cc9d0 100644 --- a/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/InMemoryDBIntegrationTest.java +++ b/persistence-modules/spring-jpa/src/test/java/org/baeldung/persistence/repository/InMemoryDBIntegrationTest.java @@ -1,8 +1,10 @@ package org.baeldung.persistence.repository; import org.baeldung.config.StudentJpaConfig; +import org.baeldung.inmemory.persistence.dao.ManyStudentRepository; +import org.baeldung.inmemory.persistence.dao.ManyTagRepository; import org.baeldung.inmemory.persistence.dao.StudentRepository; -import org.baeldung.inmemory.persistence.model.Student; +import org.baeldung.inmemory.persistence.model.*; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; @@ -13,6 +15,7 @@ import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.Arrays; +import java.util.Collections; import java.util.List; import static org.junit.Assert.assertEquals; @@ -24,6 +27,12 @@ public class InMemoryDBIntegrationTest { @Resource private StudentRepository studentRepository; + + @Resource + private ManyStudentRepository manyStudentRepository; + + @Resource + private ManyTagRepository manyTagRepository; private static final long ID = 1; private static final String NAME="john"; @@ -79,4 +88,47 @@ public class InMemoryDBIntegrationTest { assertEquals("name incorrect", NAME, student2.getName()); } + @Test + public void givenStudenWithSkillTags_whenSave_thenGetByNameAndSkillTag() { + Student student = new Student(1, "Will"); + SkillTag skill1 = new SkillTag("java", 5); + student.setSkillTags(Arrays.asList(skill1)); + studentRepository.save(student); + + Student student2 = new Student(2, "Joe"); + SkillTag skill2 = new SkillTag("java", 1); + student2.setSkillTags(Arrays.asList(skill2)); + studentRepository.save(student2); + + List students = studentRepository.retrieveByNameFilterByMinimumSkillTag("java", 3); + assertEquals("size incorrect", 1, students.size()); + } + + @Test + public void givenStudentWithKVTags_whenSave_thenGetByTagOk(){ + Student student = new Student(0, "John"); + student.setKVTags(Arrays.asList(new KVTag("department", "computer science"))); + studentRepository.save(student); + + Student student2 = new Student(1, "James"); + student2.setKVTags(Arrays.asList(new KVTag("department", "humanities"))); + studentRepository.save(student2); + + List students = studentRepository.retrieveByKeyTag("department"); + assertEquals("size incorrect", 2, students.size()); + } + + @Test + public void givenStudentWithManyTags_whenSave_theyGetByTagOk() { + ManyTag tag = new ManyTag("full time"); + manyTagRepository.save(tag); + + ManyStudent student = new ManyStudent("John"); + student.setManyTags(Collections.singleton(tag)); + manyStudentRepository.save(student); + + List students = manyStudentRepository.findByManyTags_Name("full time"); + assertEquals("size incorrect", 1, students.size()); + } + }