IllegalStateException 使用 CriteriaBuilder 在 Java 中获取列表
IllegalStateException using CriteriaBuilder for getting a List in Java
总结一下,我有 3 个实体,主要的是名为 "Rac" 的实体。它包含一个 "RacNatureza" 的列表,其中包含一个属性 "Natureza".
Rac
@Entity
@Table(name = "rac")
public class Rac {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idRac;
@OneToMany(mappedBy = "rac", cascade = {CascadeType.ALL}, orphanRemoval = true)
@JsonManagedReference //para evitar recursão infinita do JSON
private List<RacNatureza> racNaturezas;
//...getters and setters ok
}
RacNatureza
@Entity
@Table(name = "rac_natureza")
public class RacNatureza implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_rac_natureza")
private Long idRacNatureza;
@ManyToOne
@JsonBackReference //coloquei para evitar a recursao infinita de JSON
@JoinColumn(name="id_rac")
private Rac rac;
@ManyToOne
@JoinColumn(name="id_natureza")
private Natureza natureza;
@Column(name = "principal")
private Boolean principal;
}
大自然
@Entity
@Table(name = "natureza")
public class Natureza {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_natureza")
private Integer idNatureza;
private String descricao;
@OneToMany(mappedBy = "natureza", fetch = FetchType.EAGER, orphanRemoval = true)
@JsonIgnore
private List<RacNatureza> racNatureza;
}
我正在尝试使用过滤器开发搜索,在这种情况下,用户 select 一个 "Natureza" 的列表,然后系统必须显示 "Rac" 包含的内容用户 select 编辑的 Natureza。为此,我尝试使用 Entitymanager 和 Criteriabuilder 来实现。
我试过这样写表达式,但没有用(我没有使用元模型):
@PersistenceContext
private EntityManager entityManager;
@Override
public List<Rac> filtrar(RacFilter racFilter) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Rac> criteria = builder.createQuery(Rac.class);
Root<Rac> root = criteria.from(Rac.class);
Predicate[] predicates = criarRestricoes(racFilter, builder, root);
criteria.where(predicates);
TypedQuery<Rac> query = entityManager.createQuery(criteria);
return query.getResultList();
}
@Override
public Predicate[] criarRestricoes(RacFilter racFilter, CriteriaBuilder builder, Root<Rac> root) {
List<Predicate> predicates = new ArrayList<>();
if (racFilter.getNaturezas() != null) {
predicates.add(
builder.equal(root.<List<RacNatureza>>get("racNaturezas").<Natureza>get("natureza"), racFilter.getNaturezas()) );
}
return predicates.toArray(new Predicate[predicates.size()]);
}
因此,使用上面的代码我收到了以下错误:
原因:java.lang.IllegalStateException:非法尝试取消引用基本类型的路径源 [null.racNaturezas]
我认为错误出在这一行,但我真的不知道如何解决:
predicates.add(
builder.equal(root.<List<RacNatureza>>get("racNaturezas").<Natureza>get("natureza"), racFilter.getNaturezas()) );
}
替换root.get("racNaturezas")
root.join("racNaturezas")
请不要问我为什么我们不能使用get
FWIW 你不能使用 get
因为隐式连接只针对多对一和一对一关联。它们不能用于多对多或一对多关联。在后一种情况下,需要显式连接,即 root.join("racNaturezas")
.
总结一下,我有 3 个实体,主要的是名为 "Rac" 的实体。它包含一个 "RacNatureza" 的列表,其中包含一个属性 "Natureza".
Rac
@Entity
@Table(name = "rac")
public class Rac {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long idRac;
@OneToMany(mappedBy = "rac", cascade = {CascadeType.ALL}, orphanRemoval = true)
@JsonManagedReference //para evitar recursão infinita do JSON
private List<RacNatureza> racNaturezas;
//...getters and setters ok
}
RacNatureza
@Entity
@Table(name = "rac_natureza")
public class RacNatureza implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_rac_natureza")
private Long idRacNatureza;
@ManyToOne
@JsonBackReference //coloquei para evitar a recursao infinita de JSON
@JoinColumn(name="id_rac")
private Rac rac;
@ManyToOne
@JoinColumn(name="id_natureza")
private Natureza natureza;
@Column(name = "principal")
private Boolean principal;
}
大自然
@Entity
@Table(name = "natureza")
public class Natureza {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id_natureza")
private Integer idNatureza;
private String descricao;
@OneToMany(mappedBy = "natureza", fetch = FetchType.EAGER, orphanRemoval = true)
@JsonIgnore
private List<RacNatureza> racNatureza;
}
我正在尝试使用过滤器开发搜索,在这种情况下,用户 select 一个 "Natureza" 的列表,然后系统必须显示 "Rac" 包含的内容用户 select 编辑的 Natureza。为此,我尝试使用 Entitymanager 和 Criteriabuilder 来实现。
我试过这样写表达式,但没有用(我没有使用元模型):
@PersistenceContext
private EntityManager entityManager;
@Override
public List<Rac> filtrar(RacFilter racFilter) {
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Rac> criteria = builder.createQuery(Rac.class);
Root<Rac> root = criteria.from(Rac.class);
Predicate[] predicates = criarRestricoes(racFilter, builder, root);
criteria.where(predicates);
TypedQuery<Rac> query = entityManager.createQuery(criteria);
return query.getResultList();
}
@Override
public Predicate[] criarRestricoes(RacFilter racFilter, CriteriaBuilder builder, Root<Rac> root) {
List<Predicate> predicates = new ArrayList<>();
if (racFilter.getNaturezas() != null) {
predicates.add(
builder.equal(root.<List<RacNatureza>>get("racNaturezas").<Natureza>get("natureza"), racFilter.getNaturezas()) );
}
return predicates.toArray(new Predicate[predicates.size()]);
}
因此,使用上面的代码我收到了以下错误: 原因:java.lang.IllegalStateException:非法尝试取消引用基本类型的路径源 [null.racNaturezas]
我认为错误出在这一行,但我真的不知道如何解决:
predicates.add(
builder.equal(root.<List<RacNatureza>>get("racNaturezas").<Natureza>get("natureza"), racFilter.getNaturezas()) );
}
替换root.get("racNaturezas")
root.join("racNaturezas")
请不要问我为什么我们不能使用get
FWIW 你不能使用 get
因为隐式连接只针对多对一和一对一关联。它们不能用于多对多或一对多关联。在后一种情况下,需要显式连接,即 root.join("racNaturezas")
.