【问题标题】:Spring MVC - get a single value from a List in the controllerSpring MVC - 从控制器中的列表中获取单个值
【发布时间】:2016-03-21 06:22:17
【问题描述】:

我有一个问题,我不知道如何处理......

在我的控制器中我有一个方法

@RequestMapping(value = {path+"/illuminazione"}, method = RequestMethod.GET)
public String lightsSituation(ModelMap model){
    String pageTitle ="Stato Luci";
    List <Illuminazione> illuminazione = illuminazioneService.showLightsSituation();
    model.addAttribute("illuminazione", illuminazione);
    model.addAttribute("pageTitle", pageTitle);
    model.addAttribute("cssActiveIll", cssActiveIll);
    return path+"/illuminazione";
}

此方法只是从数据库中创建一个对象列表。通过这种方式,我可以轻松地将所有模型传递给我的视图以显示对象。问题是在字段中我有两个时间戳值,我想在视图中显示它们之间的持续时间。 我对持续时间函数没有任何问题,我设法直接在 JSP 页面中进行计算,但我更愿意在控制器中执行此操作,并将计算结果简单地传递给模型(这是正确的方法吗? )。如何从列表中获取我需要的两个值以便将它们添加到模型中?

我想在服务实现类中添加一个新功能,但在我看来它是一个超级解决方案...

这是 Illuminazione.java

@Entity
@Table(name = "illuminazione", catalog = "SMARTPARK")
public class Illuminazione implements java.io.Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    private int idEvento;
    private Luce luce;
    private Date dateTime;
    private Date lastDateTime;
    private boolean isLit;

    public Illuminazione() {
    }

    public Illuminazione(int idEvento, Luce luce, Date dateTime, Date lastDateTime, boolean isLit) {
        this.idEvento = idEvento;
        this.luce = luce;
        this.dateTime = dateTime;
        this.lastDateTime = lastDateTime;
        this.isLit = isLit;
    }

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id_evento", unique = true, nullable = false)
    public Integer getIdEvento() {
        return this.idEvento;
    }

    public void setIdEvento(Integer idEvento) {
        this.idEvento = idEvento;
    }

    @ManyToOne
    @JoinColumn(name = "id_luce")
    public Luce getLuce() {
        return this.luce;
    }

    public void setLuce(Luce luce) {
        this.luce = luce;
    }

    @NotNull
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(pattern="dd/MM/yyyy - hh:mm")
    @Column(name = "date_time")
    public Date getDateTime() {
        return this.dateTime;
    }

    public void setDateTime(Date dateTime) {
        this.dateTime = dateTime;
    }

    @NotNull
    @Column(name = "isLit", nullable = false)
    public boolean isIsLit() {
        return this.isLit;
    }

    public void setIsLit(boolean isLit) {
        this.isLit = isLit;
    }

    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(pattern="dd/MM/yyyy - hh:mm")
    @Column(name = "last_date_time")
    public Date getLastDateTime() {
        return lastDateTime;
    }

    public void setLastDateTime(Date lastDateTime) {
        this.lastDateTime = lastDateTime;
    }

}

有什么想法吗?

按照@reos 的建议,我可以在我的 Illuminazione.java 中添加一个 duration 字段,该字段现在具有

public String getDuration(){    
        DateTime sd = new DateTime(getDateTime());
        DateTime ed = new DateTime(getLastDateTime());
        Period period = new Period(sd, ed);
        long days = period.getDays();
        long hours = period.getHours();
        long minutes = period.getMinutes();
        long seconds = period.getSeconds();

        this.duration=days+" giorni - "+hours+" ore - "+minutes+" minuti - "+seconds+" secondi";

        return duration;
    }

问题是我的illuminazioneService.showLightsSituation(); 来自一个 DaoImpl,它是一个普通的 SQL 查询(我不能用 Criteria 或 HQL 来做这个查询来处理对象)

public List<Illuminazione> showLightsSituations() {

        String query = "select i.id_evento, i.id_luce, i.last_date_time, l.numero_luce, l.nome_luce, ill.MaxDate, i.isLit ";

        query += "from illuminazione i inner join  luci l on i.id_luce= l.id_luce ";
        query += "inner join (SELECT `id_luce` as numeroLuce2, max(date_time) as MaxDate from illuminazione i2 group by `i2`.`id_luce`) ill ";
        query += "on i.id_luce = ill.`numeroLuce2` and i.`date_time` = ill.MaxDate order by i.`id_luce` asc";
        SQLQuery q = getSession().createSQLQuery(query);
        q.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
        List<Illuminazione> lista = q.list();
        return lista;
    }

这样,当我将模型发送到 JSP 视图时,我只有通过查询选择的字段,我无法以这种方式回忆持续时间${ill.duration},因为它是空的 这是JPS的摘录

<c:forEach items="${illuminazione}" var="ill">

        <tr>
            <td><div class="list-field">
            <fmt:formatDate value="${ill.MaxDate}"  pattern="dd/MM/yyyy - HH:mm" />
            </div></td>
       <td><div class="list-field">
            <fmt:formatDate value="${ill.last_date_time}"  pattern="dd/MM/yyyy - HH:mm" />
            </div></td>
        <td><div class="list-field">${ill.duration}</div></td>

    </tr>

</c:forEach>

【问题讨论】:

  • 您可以使用像 IlluminazioneDTO 这样具有类变量 durationBetweenDates 的包装器对象,并在每个语句中创建此对象并使用此值设置字段。但是如果你在这个列表中有超过 10K 的值,这会导致性能问题。如果是我建议您编写另一个查询并在 sql 中计算差异并直接在字段中返回。这样 sql 的性能会更好。
  • 我不太喜欢包装器的想法。直接在 SQL 中进行计算是一种选择,但我可以返回非格式化结果,例如使用 TIMESTAMPDIFF。我只得到一个数字,我应该用 JSP 格式化它吗?
  • Illuminazione的内容是什么?
  • 编辑了问题以添加它@reos
  • 我建议你在你的 Illuminazione 类中添加一个 getDuration() 方法

标签: spring spring-mvc


【解决方案1】:

可能有更有效的方法来做到这一点,但我只是向您展示这个概念。这应该可以让您快速完成。

控制器:

@RequestMapping(value = {path+"/illuminazione"}, method = RequestMethod.GET)
public String lightsSituation(Model model){
    String pageTitle ="Stato Luci";
    List <Illuminazione> illuminazione = illuminazioneService.showLightsSituation();

    //to be very clear with the example, we create a new list that will have
    //the updated duration.  
    List <Illuminazione> definitivo = new ArrayList<>(illuminazione.size());

    for (Illuminazione fagioloJava : illuminazione) {
         DateTime start = fagioloJava.getDateTime();
         DateTime end = fagioloJava.getLastDateTime();

         //let your controller just route requests  
         //and provide the model attributes; 
         //put the duration calculation in a service class

         String duration = IlluminazioneService.getDuration(start, end);
         fagioloJava.setDuration(duration);
         definitivo.add(fagioloJava);
    }

    model.addAttribute("definitivo", definitivo);
    model.addAttribute("pageTitle", pageTitle);
    model.addAttribute("cssActiveIll", cssActiveIll);
    return path+"/illuminazione";
}

服务:

public class IlluminazioneService {
    public static String getDuration(DateTime start, DateTime end) {
       Period period = new Period(start, end);
       long days = period.getDays();
       long hours = period.getHours();
       long minutes = period.getMinutes();
       long seconds = period.getSeconds();
       //if this needs to be internationalized, 
       //then I wouldn't return it this way.  
       //You could have a field for days, hours, minutes, etc. 
       //and get the rest from a Spring message (resource) bundle.
       return days+" giorni - "+hours+" ore - "+minutes+" minuti - "+seconds+" secondi"; 
    }
}

照明:

//add this.  
//transient because we don't need to persist this:
@Transient 
private String duration;

//getter and setter

现在显然,如果您有数万亿个 Illuminazione bean,那么迭代它们将需要时间。但在大多数情况下,这种解决方案会非常好。我们一直在项目中看到这种方法。

【讨论】:

  • 谢谢@bphilipnyc,这只是我正在寻找的方法,很清楚,“应该”做我需要的,我唯一的问题是我得到了一个java.lang.ClassCastException: java.util.HashMap cannot be cast to it.besmart.models.Illuminazione it.besmart.controller.IlluminazioneController.lightsSituation(IlluminazioneController.java:58),这就是这部分@987654327 @
  • 我在您的代码中没有看到 HashMap。你确定illuminazioneService.showLightsSituation() 返回一个List
  • 您将查询设置为返回 Mapq.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);。见:stackoverflow.com/questions/8909550/…
  • 如果你需要返回一个Map,那么这个过程应该是相似的——迭代一个Map而不是一个List。但无论如何,您的服务方法showLightsSituations() 需要更改以反映正确的类型。
  • 我可能会重命名你原来的服务类IlluminazioneDaoImpl而不是IlluminazioneService. 然后你可以创建一个名为IlluminazioneDao的接口,这样如果你以后需要添加另一个实现,它就很简单就像实现了 Dao 接口一样,你就不必接触其他任何东西了。
猜你喜欢
  • 2017-11-01
  • 1970-01-01
  • 2015-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多