【问题标题】:JPA query not returning expected result setJPA 查询未返回预期结果集
【发布时间】:2016-10-11 10:19:21
【问题描述】:

在我正在工作的一个项目中,我们有一个带有多个实体的持久性单元的 ejb,但最近我们必须更新一些具有复杂 id 的实体(2 个字段形成该 id),并且通过此更改,查询不会在我们期望的方式。 我们有这个实体,它对应于一个中间表,其中一个实体发生了多对一的关系。

publicic class BapeConvCateZonas implements Serializable {

private static final long serialVersionUID = 1L;
@Size(max = 1)
@Column(name = "B_INTERINIDAD")
private String bInterinidad;
@Size(max = 1)
@Column(name = "B_SUSTIT_LARGA")
private String bSustitLarga;
@Size(max = 1)
@Column(name = "B_SUSTIT_CORTA")
private String bSustitCorta;
@Id
@Basic(optional = false)
@NotNull
@Column(name = "C_CODIGO")
private Long cCodigo;
@JoinColumns({
    @JoinColumn(name = "C_COD_GSA", referencedColumnName = "C_COD_GSA", updatable=false,insertable=false),
    @JoinColumn(name = "C_COD_CENTRO", referencedColumnName = "C_CODIGO", updatable=false,insertable=false)})

@ManyToOne
private BapeCentrossanitarios bapeCentrossanitarios;
@JoinColumns({
    @JoinColumn(name = "C_COD_CONV", referencedColumnName = "C_COD_CONV"),
    @JoinColumn(name = "C_COD_CATE", referencedColumnName = "C_COD_CATE")})
@ManyToOne(optional = false)
private BapeConvCateTopes bapeConvCateTopes;
@JoinColumns({
    @JoinColumn(name = "C_COD_GSA", referencedColumnName = "C_COD_GSA", updatable=false,insertable=false),
    @JoinColumn(name = "C_COD_CENTRO", referencedColumnName = "C_COD_CENTRO", updatable=false,insertable=false),
    @JoinColumn(name = "C_COD_DEPTO", referencedColumnName = "C_CODIGO", updatable=false,insertable=false)})

@ManyToOne
private BapeDeptSanitarios bapeDeptSanitarios;
@JoinColumn(name = "C_COD_GSA", referencedColumnName = "C_CODIGO", updatable=false,insertable=false)
@ManyToOne
private BapeGerenciasaludarea cCodGsa;

实体发生了变化:

public class BapeCentrossanitarios implements Serializable {

@OneToMany(mappedBy = "bapeCentrossanitarios")
private List<BapeConvCateZonas> bapeConvCateZonasList;

private static final long serialVersionUID = 1L;
@EmbeddedId
protected BapeCentrossanitariosPK bapeCentrossanitariosPK;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 150)
@Column(name = "A_DESCRIPCION")
private String aDescripcion;
@JoinColumn(name = "C_COD_GSA", referencedColumnName = "C_CODIGO", insertable = false, updatable = false)
@ManyToOne(optional = false)
private BapeGerenciasaludarea bapeGerenciasaludarea;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "bapeCentrossanitarios")
private List<BapeDeptSanitarios> bapeDeptSanitariosList;

此实体中的 id 更改为:

@Id
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 4)
@Column(name = "C_CODIGO")
private String cCodigo;

收件人:

@EmbeddedId
protected BapeCentrossanitariosPK bapeCentrossanitariosPK;

还有:

@Embeddable

公共类 BapeCentrossanitariosPK 实现可序列化 {

@Basic(optional = false)
@NotNull
@Size(min = 1, max = 4)
@Column(name = "C_CODIGO")
private String cCodigo;
@Basic(optional = false)
@NotNull
@Size(min = 1, max = 4)
@Column(name = "C_COD_GSA")
private String cCodGsa;

当我执行这个查询时,不会返回任何东西:

SQL: select u from BapeConvCateZonas u where u.bapeConvCateTopes.bapeConvCateTopesPK.cCodConv=:convocatoria and u.bapeConvCateTopes.bapeConvCateTopesPK.cCodCate=:categoria and u.bapeCentrossanitarios is null and u.bInterinidad='S' order by u.cCodGsa.cCodigo ASC;

BapeConvCateTopes 实体: 公共类 BapeConvCateTopes 实现 Serializable {

    @Column(name = "N_ANIO_FINALIZACION")
    private Short nAnioFinalizacion;
    @JoinTable(name = "BAPE_CONV_CATE_MERI_SUB", joinColumns = {
        @JoinColumn(name = "C_COD_CONV", referencedColumnName = "C_COD_CONV"),
        @JoinColumn(name = "C_COD_CATE", referencedColumnName = "C_COD_CATE")}, inverseJoinColumns = {
        @JoinColumn(name = "C_COD_AREA", referencedColumnName = "C_COD_AREA"),
        @JoinColumn(name = "C_COD_TIPO", referencedColumnName = "C_COD_TIPO"),
        @JoinColumn(name = "C_COD_SUBTIPO", referencedColumnName = "C_CODIGO")})
    @ManyToMany
    @OrderBy("bapeMeritosSubtiposPK.cCodArea ASC")
    private List<BapeMeritosSubtipos> bapeMeritosSubtiposList;

    @JoinTable(name = "BAPE_CONV_CATE_TITU_EXPE", joinColumns = {
        @JoinColumn(name = "C_COD_CONV", referencedColumnName = "C_COD_CONV"),
        @JoinColumn(name = "C_COD_CATE", referencedColumnName = "C_COD_CATE")}, inverseJoinColumns = {
        @JoinColumn(name = "C_COD_TITU", referencedColumnName = "C_CODIGO")})
    @ManyToMany
    private List<BapeTitulaExper> bapeTitulaExperCollection;
    @JoinColumn(name = "C_COD_CONV", referencedColumnName = "C_CODIGO", insertable = false, updatable = false)
    @ManyToOne(optional = false)
    private BapeConvocatorias bapeConvocatorias;
    @JoinColumn(name = "C_COD_CATE", referencedColumnName = "C_CODIGO", insertable = false, updatable = false)
    @ManyToOne(optional = false)
    private BapeCategorias bapeCategorias;

    private static final long serialVersionUID = 1L;
    @EmbeddedId
    protected BapeConvCateTopesPK bapeConvCateTopesPK;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 1)
    @Column(name = "B_ACTIVO")
    private String bActivo;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 1)
    @Column(name = "B_NOTIF_AUTOMATICA")
    private String bNotifAutomatica;
    // @Max(value=?)  @Min(value=?)//if you know range of your decimal fields consider using these annotations to enforce field validation
    @Column(name = "TOPE")
    private BigDecimal tope;
    @OneToMany(cascade = CascadeType.REFRESH, mappedBy = "bapeConvCateTopes")
    @OrderColumn(name="C_COD_GSA")
    private List<BapeConvCateZonas> bapeConvCateZonasList;

还有 BapeConvCateTopesPK:

@Embeddable
public class BapeConvCateTopesPK implements Serializable {

    @Basic(optional = false)
    @NotNull
    @Column(name = "C_COD_CONV")
    private long cCodConv;
    @Basic(optional = false)
    @NotNull
    @Column(name = "C_COD_CATE")
    private long cCodCate;

该表具有符合条件的值。 根据最后的变化,它必须与关系和复杂的 id 相关,但我不放弃掌握可能是什么。编辑:添加了有关 ID 更改的更多信息。

【问题讨论】:

  • 你检查生成的SQL了吗?
  • ... it has to be something related to the relationship and the complex id ... - 对于初学者,您可以考虑设置该复杂 id 的定义。
  • 我检查了 sql 字符串,但没有检查 jpa 最终执行的内容,我该如何检查 sql?编辑了更多信息。
  • spring.jpa.show-sql=true in application.properties 将有助于查看 JPA 正在执行什么
  • 请修正你的格式,那些代码墙和半格式块读起来很痛苦。除此之外,请发布您正在使用的实体和 id-class,即看起来我们需要 BapeConvCateTopesBapeConvCateTopesPK 而不是 BapeCentrossanitariosBapeCentrossanitariosPK

标签: java jpa eclipselink jpql


【解决方案1】:

虽然您的 ID 更改混淆了问题,但使用的 JPQL 不正确。具体来说,“u.bapeCentrossanitarios 为空”正在强制对表进行内部连接。由于内连接过滤掉了空值,因此该子句永远不会为真,因此不会返回任何结果。

查询应在此关系上使用左外连接。比如:

"select u from BapeConvCateZonas u left outer join u.bapeCentrossanitarios bapeCentrossanitarios where u.bapeConvCateTopes.bapeConvCateTopesPK.cCodConv=:convocatoria and u.bapeConvCateTopes.bapeConvCateTopesPK.cCodCate=:categoria and bapeCentrossanitarios is null and u.bInterinidad='S' order by u.cCodGsa.cCodigo ASC"

会起作用,尽管可能有很多方法可以形成类似的查询。

它可能首先起作用的原因是,您对复合 PK 的更改可能会绕过 EclipseLink 优化,该优化允许它在不执行连接的情况下评估“u.bapeCentrossanitarios is Null”——它可以只检查 pk 值,如果它是空的。随着更改,一个或多个外键可能为空,也可能不为空(它们不受映射控制),因此必须加入表才能确定。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-31
    • 2016-04-12
    相关资源
    最近更新 更多