When running a particular unit-test, I am getting the exception:
Caused by: org.hibernate.HibernateException: Errors in named queries: UPDATE_NEXT_FIRE_TIME
at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:437)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1385)
at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954)
at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:891)
... 44 more
for the named query defined here:
@Entity(name="fireTime")
@Table(name="qrtz_triggers")
@NamedQueries({
@NamedQuery(
name="UPDATE_NEXT_FIRE_TIME",
query= "update fireTime t set t.next_fire_time = :epochTime where t.trigger_name = 'CalculationTrigger'")
})
public class JpaFireTimeUpdaterImpl implements FireTimeUpdater {
@Id
@Column(name="next_fire_time", insertable=true, updatable=true)
private long epochTime;
public JpaFireTimeUpdaterImpl() {}
public JpaFireTimeUpdaterImpl(final long epochTime) {
this.epochTime = epochTime;
}
@Override
public long getEpochTime() {
return this.epochTime;
}
public void setEpochTime(final long epochTime) {
this.epochTime = epochTime;
}
}
After debugging as deep as I could, I've found that the exception occurs in w.statement(hqlAst) in QueryTranslatorImpl:
private HqlSqlWalker analyze(HqlParser parser, String collectionRole) throws QueryException, RecognitionException {
HqlSqlWalker w = new HqlSqlWalker( this, factory, parser, tokenReplacements, collectionRole );
AST hqlAst = parser.getAST();
// Transform the tree.
w.statement( hqlAst );
if ( AST_LOG.isDebugEnabled() ) {
ASTPrinter printer = new ASTPrinter( SqlTokenTypes.class );
AST_LOG.debug( printer.showAsString( w.getAST(), "--- SQL AST ---" ) );
}
w.getParseErrorHandler().throwQueryException();
return w;
}
Is there something wrong with my query or annotations?
NamedQuery should be written with JPQL, but query seems to mix both names of persistent attributes and names of database columns. Names of database columns cannot be used in JPQL.
In this case instead of next_fire_time
name of the persistent attribute epochTime
should be used. Also trigger_name
looks more like name of the database column than name of the persistent attribute, but it seems not to be mapped in your current class at all. After it is mapped, query is as follows:
update fireTime t set t.epochTime = :epochTime
where t.triggerName = 'CalculationTrigger'
If SQL query is preferred, then @NamedNativeQuery should be used instead.
As a side note, JPA 2.0 specification doesn't encourage changing primary key:
The application must not change the value of the primary key[10]. The behavior is undefined if this occurs.[11]
In general entities are not aware of changed made via JPQL queries. That gets especially interesting when trying to refresh entity that does not exist anymore (because primary key was changed).
Additionally naming is little bit confusing: