【问题标题】:Spring boot JPA how to query filter on @Transient attributeSpring Boot JPA如何在@Transient属性上查询过滤器
【发布时间】:2016-07-26 02:40:50
【问题描述】:

我正在使用带有 starter-data-jpa 的 spring boot 1.3.3 + 我正在使用 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] 的属性

实体类:

@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);
    }
}

控制器类:

 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;
 }

回购类:

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

【问题讨论】:

  • 不想要的时候为什么还要加上@Transient呢?
  • @mh-dev 因为statusName在表中不存在,status存在但它是status的id,我想通过status name过滤。

标签: java hibernate spring-boot spring-data spring-data-jpa


【解决方案1】:

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

规范类

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));
        };
    }
}

控制器类

   @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;
   }
}

【讨论】:

    【解决方案2】:

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

    由于statutNamestatus 相关,而status 不是瞬态的,因此您可以改用status

    【讨论】:

    • 但正如我在问题 statusName is not in database status 中解释的那样。但是 status 是数据库中的 id。我希望他们传递字符串(例如租金)而不是 id。我该怎么做?
    • @zt1983811 你不能将字符串传递给数据库,它没有任何意义,将其转换为状态并查询状态是你唯一的方法
    • @zt1983811 无论您使用哪种方法,您最终都会查询 STATUS。我同时使用 querydsl 和规范,您所能做的就是传递 statusName 并从 STATUS 中检索其等效项并查询数据库状态。
    • 是的@Rafik BELDI,这就是我要做的事情,你建议哪一个更多规格或查询dsl?
    • @zt1983811 如果你在没有通过类主键的情况下这样做,请让我更新:)
    猜你喜欢
    • 2014-04-18
    • 2020-01-25
    • 2022-07-01
    • 2020-10-30
    • 2018-08-29
    • 1970-01-01
    • 1970-01-01
    • 2021-10-13
    • 2015-03-26
    相关资源
    最近更新 更多