使用HibernateTemplate将具体选择映射到对象

时间:2014-05-16 00:43:41

标签: java spring hibernate

我正在使用HibernateTemplate3 + Spring,我发现自己需要按日期列出ProfilingReport对象,按平均时间分组。 问题是显然Hibernate无法将我的选择映射到我的模型中的ProfilingReport对象。 我想知道是否有办法做到这一点,因为它只是返回一个目标数组列表。

这是我的ProfilingReport类的开始(减去getter和setter):

import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.persistence.Temporal;

@Entity
@Table(name = "ProfilingReport")
public class ProfilingReport extends Persistent {

private String serviceName;
private long runTime;
@Temporal(javax.persistence.TemporalType.DATE)
private Date date;

所有持久化类扩展的My Persistent类:

import java.io.Serializable;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.MappedSuperclass;
import javax.persistence.Version;

@MappedSuperclass
public class Persistent implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Version
private Long version;

public Long getId() {
    return id;
}

public void setId(Long id) {
    this.id = id;
}

public long getVersion() {
    return version;
}

public void setVersion(Long version) {
    this.version = version;
}
}

这是我试图在我的DAO中执行的方法:

@Override
@Transactional(readOnly = true)
public List<ProfilingReport> getProfilingReports(final Date fecha) {
    String query = "select  p.id, p.version, p.serviceName, AVG(p.runTime), date "
            + "from Profiling p "
            + "where p.date = :fecha "
            + "group by p.serviceName";

    return this.hibernateTemplate.findByNamedParam(query, "fecha", fecha);
}

2 个答案:

答案 0 :(得分:0)

尝试这个hql更改,

@Override
@Transactional(readOnly = true)
public List<ProfilingReport> getProfilingReports(final Date fecha) {
String query = "from ProfilingReport p "
        + "where p.date = :fecha "
        + "group by p.serviceName";

return this.hibernateTemplate.findByNamedParam(query, "fecha", fecha);
}

然后你需要通过java业务逻辑本身找到runTime的平均值。

否则,使用现有的数组对象列表,您可以迭代并创建ProfilingReport对象,并将这些数组值分配给ProfilingReport中的相关属性。最后将每个ProfilingReport对象添加到列表(List)中。

答案 1 :(得分:0)

解决方法是使用Hibernate org.hibernate.annotations.Formula注释:

@Entity
@Table(name = "ProfilingReport")
public class ProfilingReport extends Persistent {

private String serviceName;
private long runTime;
@Temporal(javax.persistence.TemporalType.DATE)
private Date date;
@org.hibernate.annotations.Formula("select AVG(p.runTime) from Profiling p group by p.serviceName") private Number averageRunTime;

然后按日期运行查询:

    @Override
@Transactional(readOnly = true)
public List<ProfilingReport> getProfilingReports(final Date fecha) {
String query = "from ProfilingReport p "
    + "where p.date = :fecha ";
    return this.hibernateTemplate.findByNamedParam(query, "fecha", fecha);
}

另一种解决方案是使用SQL窗口函数,如果您的数据库支持它们(Oracle,PostgreSQL),那么您只需要一个本机查询,窗口函数允许您在嵌入聚合结果时保留所选行,就像您想要的那样首先。