spring-data-jpa 有没有办法为JPA存储库添加一个抽象方法:findByEnumContaining(字符串枚举)[枚举是可能的ENUM值的子字符串]

drkbr07n  于 2022-11-10  发布在  Spring
关注(0)|答案(1)|浏览(121)

这是我的JPA @Repository,在这里我们可以通过findByFullNameContaining(String query)获得list<Person>-通过在查询中只提供fullName的子字符串

@Repository
public interface PersonRepository extends CrudRepository<Person,String> {
    Optional<Person> findByFullName(String fullName);
    List<Person> findByDepartment(Department department);
    List<Person> findByFullNameContaining(String query);

}

类似地,我们是否可以通过提供ENUM的子字符串值来对ENUM值执行一些操作?如何执行?
例如:

public enum Department {
    NORTH,
    SOUTH,
    EAST,
    WEST
}

List<Person> findByDepartmentContaining(String query);
JPA @实体人员:

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

@Entity
@Table(name = "Person")
public class Person {

    @Id 
    @NotNull(message = "Mobile number is required")
    @Size(min = 10, max = 10, message = "Mobile no. must be 10 digits")
    @Column(name = "person_id", unique = true, length = 10)
    private String mobileNum;

    @Transient
    @NotNull(message = "Password is required")
    @Size(min = 1, message = "Password cannot be empty")
    private String password="****";

    @NotNull(message = "Name cannot be empty")
    @Size(min = 1, max = 255, message = "fullName must be 1-255 characters long")
    @Column(name = "full_name")
    private String fullName;

    @Column(name = "department")
    @Enumerated(EnumType.STRING)
    @NotNull(message = "Department must be specified")
    private Department department = Department.UNKNOWN;

    public Person() {
    }

    public Person(String mobileNum, String fullName, String password, Department department) {
        this.mobileNum = mobileNum;
        this.password = password;
        this.fullName = fullName;
        this.department = department;
    }

    public String getMobileNum() {
        return mobileNum;
    }

    public void setMobileNum(String mobileNum) {
        this.mobileNum = mobileNum;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getFullName() {
        return fullName;
    }

    public void setFullName(String fullName) {
        this.fullName = fullName;
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    @Override
    public String toString() {
        return "Person [fullName=" + fullName + ", mobileNum=" + mobileNum + ", password=" + password + ", department=" + department + "]";
    }

}
5ktev3wc

5ktev3wc1#

这个问题并没有说明在声明这样的方法时到底有什么问题。
但是,在尝试使用PostgreSql数据库的spring boot 2.7后,应用程序引发以下运行时错误:

java.lang.IllegalArgumentException: Parameter value [%some value%] did not match expected type [com.Department (n/a)]
    at org.hibernate.query.spi.QueryParameterBindingValidator.validate(QueryParameterBindingValidator.java:54) ~[hibernate-core-5.6.5.Final.jar:5.6.5.Final]

至少Hibernate的问题是,它希望实体中的Department字段总是作为它自己的对象类型(Department)中的参数传递。
我认为没有办法避免这种情况,因为这是Hibernate的一个现成功能。
然而,我认为正确的方法不是定义这种类型的方法,而是下面的. Department已经存在于应用程序代码中,所以在需要调用查询时就知道了。因此,我认为下面的解决方案是一种更好的做法:

//Repository method to be used in PersonRepository
List<Person> findByDepartmentIn(List<Department> departments);

然后可以从服务层以下面的方式调用存储库。

//Service method to be used
public List<Person> findByDepartmentIn(String searchBy) {

    List<Department> departments = Arrays.stream(Department.values()).filter(dep -> dep.getName().contains(searchBy)).collect(Collectors.toList());

    return personRepository.findDepartmentIn(departments);
}

相关问题