我尝试从表中删除超过给定时间的行数。行的start
是时间戳。
EntityManager em = ...
long interval = ... // long value read from a properties file
String template = "DELETE FROM %s WHERE current_timestamp() - start > :interval";
String jpql = String.format(template , MyClass.class.getCanonicalName());
Query q = em.createQuery(jpql);
q.setParameter("interval", TimeUnit.DAYS.toMillis(interval));
q.executeUpdate();
MyClass.java
@Entity
@Table(name = "ROWS")
public class MyClass implements Serializable {
private static final long serialVersionUID = 6070604872038740340L;
puyblic MyClass() {
}
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Column(name = "start", columnDefinition="TIMESTAMP WITH TIME ZONE")
@Temporal(TemporalType.TIMESTAMP)
private Date start;
// getters ans setters...
}
但是,我得到以下例外:
引起:java.lang.IllegalArgumentException:参数值[604800000]不匹配类型[java.lang.Double] 在org.hibernate.ejb.AbstractQueryImpl.registerParameterBinding(AbstractQueryImpl.java:360) 在org.hibernate.ejb.QueryImpl.setParameter(QueryImpl.java:364) 在org.hibernate.ejb.QueryImpl.setParameter(QueryImpl.java:72)
我做错了什么?
答案 0 :(得分:2)
这是我如何解决我的问题:
我没有在JPQL中进行计算和比较,而是在Java代码中进行所有计算。最后的比较留给了JPQL。
String template = "DELETE FROM %s WHERE start < :calculatedStop";
String jpql = String.format(template , MyClass.class.getCanonicalName());
long calculatedStop = new java.util.Date().getTime() - INTERVAL;// INTERVAL is a constant
Query q = em.createQuery(jpql);
q.setParameter("calculatedStop", calculatedStop);
q.executeUpdate();
答案 1 :(得分:1)
答案很简单。
String template = "DELETE FROM %s WHERE current_timestamp() - start > :interval";
构建此查询Hibernate期望此间隔值为Double类型。
这样做可以解决您的问题:
q.setParameter("interval", (double)TimeUnit.DAYS.toMillis(interval));
如果需要,我们都希望Java能够从long转换为double。但是由于长值是盒装的,Hibernate只是试图强制转换 Long to Double,这实际上并不富有成效。
因此,如果您将其转换为double,则将其设置为Double,Double显然可以转换为Double。
那么Double来自哪里?
我检查了SqlDate和Date类型的实现,并且都映射到日期,并且能够转换为long值和long值。时间戳也映射到日期。
所以我尝试了这个:
String template = "DELETE FROM %s WHERE current_timestamp() > :interval";
它失败了,因为Hibernate抱怨Long与java.util.Date不兼容。因此,仅使用current_timestamp()映射到Date值。
对此也是如此:
String template = "DELETE FROM %s WHERE start > :interval";
当一个人试图从另一个日期减去一个日期时,双重发挥作用。所以使用任何:
String template = "DELETE FROM %s WHERE current_timestamp() - current_timestamp() > :interval";
要么
String template = "DELETE FROM %s WHERE start - start > :interval";
间隔预计为双倍。这就是Hibernate抱怨的原因。
有点奇怪,但这就是它的方式,这是对正在发生的事情的确切解释。
答案 2 :(得分:0)
请查看HSQL。问题可能与currentTimestamp和start有关。我想不出它是HSQL关键字或有效属性。
您是否尝试使用未命名的参数并使用其索引设置参数?
<强>更新强>:
您的设置似乎不正确。您希望使用String(start)进行算术运算。
我最近做了类似的事情。我只有一个任务,我设置时间和之后,我检查任务是否超时(没有完成,但时间戳比之前更小)。
以下是一些代码:
1 /制图
long timestamp = 0; //default is 0
2 /设置时间戳
task.setTimestamp(System.currentTimeMillis()); session.getTransaction().commit()
3 /查询超时方法
session.beginTransaction();
long currentTime = System.currentTimeMillis();
Criteria criteria = session.createCriteria(Task.class);
criteria.add(Restrictions.eq("done", false));
criteria.add(Restrictions.le("timestamp", currentTime - Task.TASK_TIMEOUT));
Task task = (Task)criteria.uniqueResult();
if(task != null) {
task.setTimestamp(currentTime);
}
session.getTransaction().commit();
你可以看到我只是在这里使用标准搜索,因为它更简单。另请注意,我使用uniqueResult但您可以轻松更改它以检索列表。