【问题标题】:JPA - SELECT entity FROM a subsetJPA - 从子集中选择实体
【发布时间】:2013-12-03 17:24:38
【问题描述】:

我有一个名为 Fee 的实体类。执行初始查询后,如果返回多个费用,我想仅在第一个查询返回的行上添加一些(WHERE)条件。既然一个码sn-p胜过千字,这里是:

// Results of initial query
List<Fee> fees = queryFindFees.getResultList();
if (fees == null || fees.size() <= 0)
    return null;
if (fees.size() == 1) {
    Fee f = fees.get(0);
    jpa.refresh(f);
    return f;
}

// More than one fee found
String sqlBase = "SELECT f FROM Fee f WHERE f IN :fees";
String sqlComplete = sqlBase/* + " AND f.isValid = ?1"*/;
queryFindFees = jpa.createQuery(sqlComplete);
queryFindFees.setParameter("fees", fees);
// Commented out for test
// queryFindFees.setParameter(1, "Y");
List<Fee> specFees = queryFindFees.getResultList();

现在,由于我实际上是要求 EntityManager 返回上一个查询中已返回的所有费用,因此我希望得到相同的结果集。相反,列表 specFees 始终为空。

我做错了什么?

提前致谢,

卢卡

编辑 1:实体类费用的详细信息

@Entity
public class Fee implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(unique = true, nullable = false)
    private long id;

    @Column(nullable = false, length = 1)
    private String isValid;

    ...

    @Override
    public boolean equals(Object arg0) {
        if (!(arg0 instanceof Fee))
            return false;
        Fee f0 = (Fee) arg0;
        return f0.getId() == this.getId();
    }
}

生成的 SQL(sqlComplete 变量)符合预期:

SELECT f FROM Fee f WHERE f IN :fees

编辑 2:正如 Deepak 所建议的,使用 ID 集合有效:

String sqlBase = "SELECT f FROM Fee f WHERE f.id IN :feesIds";
String sqlComplete = sqlBase/* + " AND f.isValid = ?1"*/;
List<Long> feesIds = new ArrayList<Long>();
for (Fee f : fees) {
    feesIds.add(f.getId());
}
queryFindFees = jpa.createQuery(sqlComplete);
queryFindFees.setParameter("feesIds", feesIds);

使用此代码可以查询(返回所有原始费用),但如果可能,我想避免使用 for 循环,因为费用实例的数量可能非常大...

【问题讨论】:

  • 我猜,in 子句应该带括号为“SELECT f FROM Fee f WHERE f IN (:fees)”;
  • @Gayathri 谢谢,但我相信这取决于 JPA 的实现和版本,在我的(EclipseLink 2.5)中,没有括号是正确的(我也尝试添加它们,但出现语法错误)。
  • 确实,在某些情况下需要括号。再次感谢。
  • 生成的SQL是什么?是您所期望的吗?最初返回的实体是否都将 isValid 标志设置为“Y”?
  • @luc 您使用了 createQuery,它采用 JPQL 并将其转换为 SQL。打开最精细的日志记录和参数日志记录,以查看 SQL 和参数是否与传入 ID 列表而不是实体时相同。如果您还没有发布 eclipselink 的版本并尝试最新版本 - 我似乎相信集合参数中的实体可能已经修复了这样的问题,但我不记得细节了。

标签: java jpa eclipselink jpql


【解决方案1】:

看起来您覆盖的 equals 方法正在产生问题。使您的 id 长对象并使用下面的覆盖方法。或者您也可以使用此查询

SELECT f FROM Fee f WHERE f.id IN :fees 

这一次你的费用参数将包含Fee objects的ID列表

@Entity
public class Fee implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(unique = true, nullable = false)
private Long id;

@Column(nullable = false, length = 1)
private String isValid;

...

 @Override
 public boolean equals(Object arg0) {
    if (!(arg0 instanceof Fee))
        return false;
    Fee f0 = (Fee) arg0;
    return f0.getId().equals(this.getId());
  }
}

【讨论】:

  • @Luc 也报告了另一个答案
  • 如前所述,将 id 字段从 long 转换为 Long 并使用 equals 不起作用。使用替代查询 SELECT f FROM Fee f WHERE f.id IN :feesIds 并将 List 作为参数传递的解决方案工作正常,但它不是原始问题的解决方案(它更像是一种解决方法)。
  • 然而被接受为答案,因为似乎没有其他解决方案有效。
  • @Luc 我正在安装 eclipse 链接和 JPA 以查看原始问题
  • 非常感谢您抽出宝贵时间 :)
猜你喜欢
  • 1970-01-01
  • 2015-06-24
  • 1970-01-01
  • 2014-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-10
  • 1970-01-01
相关资源
最近更新 更多