我不确定这是否可能,这就是我如何使用@ElementCollection 将值列表存储在实体类中您可以在此处阅读更多信息https://thorben-janssen.com/hibernate-tips-query-elementcollection/
可以在这里找到很好的讨论How to persist a property of type List<String> in JPA?。我的建议是避免基于分隔符在 db 中存储任何值。
理想情况下,在存储此类标签时,最好使用 OneToMany 关系映射它们。另请注意,在这种情况下,这将创建一个额外的表 animal_labels。
回答 1
存储库
@Repository
public interface AnimalRepository extends JpaRepository<Animal, UUID> {
List<Animal> findDistinctAnimalsByLabelsIsIn(List<String> cute);
}
实体类
@Entity
@Table(name = "animal")
public class Animal {
@Id
@GeneratedValue
@Type(type = "uuid-char")
private UUID id;
private String name;
@ElementCollection(targetClass = String.class)
private List<String> labels;
public Animal() {
}
public Animal(String name, List<String> labels) {
this.name = name;
this.labels = labels;
}
public UUID getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getLabels() {
return labels;
}
public void setLabels(List<String> labels) {
this.labels = labels;
}
}
测试:
@ExtendWith(SpringExtension.class)
@Transactional
@SpringBootTest(classes = TestApplication.class)
class CustomConverterTest {
@Autowired
private EntityManager entityManager;
@Autowired
private AnimalRepository animalRepository;
@Test
void customLabelConverter() {
Animal puppy = new Animal("Puppy", Arrays.asList("cute", "intelligent", "spy"));
Animal meow = new Animal("Cat", Arrays.asList("cute", "intelligent"));
entityManager.persist(puppy);
entityManager.persist(meow);
List<Animal> animalWithCutelabels = animalRepository.findDistinctAnimalsByLabelsIsIn(Arrays.asList("cute"));
List<Animal> animalWithSpylabels = animalRepository.findDistinctAnimalsByLabelsIsIn(Arrays.asList("spy"));
List<Animal> animalWithCuteAndSpylabels = animalRepository.findDistinctAnimalsByLabelsIsIn(Arrays.asList("cute", "spy"));
Assertions.assertEquals(2, animalWithCutelabels.size());
Assertions.assertEquals(1, animalWithSpylabels.size());
Assertions.assertEquals(2, animalWithCuteAndSpylabels.size());
}
}
答案 2
如果您有任何选择,只能使用逗号分隔值,那么请在下面找到此方法的答案:
Repository(因为这是一个字符串,我们不能使用像in这样的列表)
@Repository
public interface AnimalRepository extends JpaRepository<Animal, UUID> {
// Also note that the query goes as string and not list
List<Animal> findAllByLabelsContaining(String labels);
}
测试:
@Test
void customLabelConverter() {
Animal puppy = new Animal("Puppy", String.join(",", Arrays.asList("cute", "intelligent", "spy")));
Animal meow = new Animal("Cat", String.join(",", Arrays.asList("cute", "intelligent")));
entityManager.persist(puppy);
entityManager.persist(meow);
List<Animal> animalWithCutelabels = animalRepository.findAllByLabelsContaining(String.join(",", Arrays.asList("cute")));
List<Animal> animalWithSpylabels = animalRepository.findAllByLabelsContaining(String.join(",", Arrays.asList("spy")));
Assertions.assertEquals(2, animalWithCutelabels.size());
Assertions.assertEquals(1, animalWithSpylabels.size());
}
实体:
@Entity
@Table(name = "animal")
public class Animal {
@Id
@GeneratedValue
@Type(type = "uuid-char")
private UUID id;
@Column
private String name;
@Column
private String labels;
public Animal() {
}
public Animal(String name, String labels) {
this.name = name;
this.labels = labels;
}
public UUID getId() {
return id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getLabels() {
if (StringUtils.isEmpty(labels)) return Collections.emptyList();
return new ArrayList<>(Arrays.asList(labels.split(AnimalLabelsConverter.DELIMITER_COMMA)));
}
public void setLabels(List<String> labels) {
if (CollectionUtils.isEmpty(labels)) {
this.labels = "";
} else {
this.labels = String.join(AnimalLabelsConverter.DELIMITER_COMMA, labels);
}
}
@Converter
public static class AnimalLabelsConverter implements AttributeConverter<List<String>, String> {
private static final String DELIMITER_COMMA = ",";
@Override
public String convertToDatabaseColumn(List<String> labels) {
if (CollectionUtils.isEmpty(labels)) return "";
return String.join(DELIMITER_COMMA, labels);
}
@Override
public List<String> convertToEntityAttribute(String dbData) {
if (StringUtils.isEmpty(dbData)) return Collections.emptyList();
return new ArrayList<>(Arrays.asList(dbData.split(DELIMITER_COMMA)));
}
}
}