Spring 启动 JPA 如何在 @Transient 属性上查询过滤器

Spring boot JPA how to query filter on @Transient attribute

我正在使用 spring boot 1.3.3 with starter-data-jpa + 我正在使用 specification-arg-resolver 在 JPA Repo

中组合多个过滤器

我在实体中有一个与数据库状态 ID 匹配的已归档调用状态属性,但是,我们想按状态名称搜索,我在实体的 hashMap 中定义了所有状态名称,如下代码

然而,当我尝试按状态名称过滤时,我得到了

 Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.dao.InvalidDataAccessApiUsageException: Unable to locate Attribute  with the the given name [statusName] on this ManagedType [api.domain.Inscription]; nested exception is java.lang.IllegalArgumentException: Unable to locate Attribute  with the the given name [statusName] on this ManagedType [api.domain.Inscription]] with root cause

java.lang.IllegalArgumentException: 无法在此 ManagedType [api.domain.Inscription]

上找到具有给定名称 [statusName] 的属性

实体 class:

@Entity
@Table(name="INSCRIPTIONS")
public class Inscription {
    private static final Map<Byte, String> STATUS = new HashMap<Byte, String>(){{
       put((byte) 1, "sale");
       put((byte) 3, "rent");
    }};

    private byte status;

    @Transient
    private String statusName;

    public byte getStatus() {
        return this.status;
    }

    public void setStatus(byte status) {
        this.status = status;
    }

    public String getStatusName() {
        return STATUS.get(this.status);
    }

    public void setStatusName(byte status) {
        this.statusName = STATUS.get(status);
    }
}

控制器Class:

 public class InscriptionController
 {
     @Autowired
     private InscriptionRepository inscriptionRepository;

     @RequestMapping(method = RequestMethod.GET)
     public Page<Inscription> findAll(
     final @RequestParam(defaultValue = "0", required = false) int offset,
     final @RequestParam(defaultValue = "20", required = false) int limit,
     @Spec(params = "status",  path = "statusName", spec = In.class) Specification<Inscription> spec
 )
 {
     Page<Inscription> inscriptions = inscriptionRepository.findAll(spec, new PageRequest(offset, limit));
     return inscriptions;
 }

回购 Class:

public interface InscriptionRepository extends PagingAndSortingRepository<Inscription, String>, JpaSpecificationExecutor<Inscription> { }

@Transient 注解用于表示一个字段不被持久化到数据库中,也就是说它在数据库中没有对应的,你不能查询它。

并且由于 statutNamestatus 相关,后者不是瞬态的,您可以使用 status 代替。

感谢@Rafik BELDI 我按照规范做了它,希望这可以帮助任何遇到同样问题的人。

规格class

public class InscriptionSpecification
{
     public static Specification<Inscription> statusNameIn(String[] statusNames) {
        if (statusNames == null || statusNames.length == 0) {
            return null;
        }
        return (root, query, cb) -> {
            Inscription inscription = new Inscription();
            List<Byte> statusIds = new ArrayList<Byte>();
            for (String oneStatusName : statusNames) {
                statusIds.add(inscription.getStatusIdByName(oneStatusName));
            }
            return cb.isTrue(root.<String>get("status").in(statusIds));
        };
    }
}

控制器class

   @RequestMapping(method = RequestMethod.GET)
   public Page<Inscription> findAll(
       final @RequestParam(defaultValue = "0", required = false) int offset,
       final @RequestParam(defaultValue = "20", required = false) int limit,
       final @RequestParam(required = false) String[] status
   )
   {
       Specification<Inscription> specStatusNameIn = InscriptionSpecification.statusNameIn(status);
       inscriptionRepository.findAll(specStatusNameIn, new PageRequest(offset, limit));
       return inscriptions;
   }
}