HQLを使用してテーブルから期限切れのエンティティを取得したい。そんな感じ:
select id, name from entity_table where date_creation + 10_minutes < current_time()
HQLでそれを行う方法がわかりません。余分なクエリを作成したくない、Javaコードで日付を処理するなど。これは、HQLレベルで実行する必要があります。
手伝ってくれませんか?
データベースによっては、これは簡単なことです。HQLは、組み込みのベンダー固有の機能をサポートします。また、HQLでまだサポートされていない場合は、新しい関数を登録することで方言を拡張する機能もサポートします。
SQLServer(またはSybase)を使用しているとしましょう。SQLServerには、「DATEADD」と呼ばれる関数があり、好きなことを非常に簡単に実行できます。形式は次のとおりです。
DATEADD (datepart, number, date)
この関数は、最初に独自のHibernate方言に登録することで、HQLで直接使用できます。これを行うには、現在使用している方言を拡張する必要があります。これは非常に単純なプロセスです。
まず、独自の方言クラスを作成します(「SQLServer2008Dialect」を独自のDBベンダーに置き換えます)。
public class MySQLServerDialect extends SQLServer2008Dialect {
public MySQLServerDialect() {
registerFunction("addminutes", new VarArgsSQLFunction(TimestampType.INSTANCE, "dateadd(minute,", ",", ")"));
}
}
次に、この新しいクラスを使用するようにHibernate構成を変更します。
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
...
<property name="hibernate.dialect">com.mycompany.MySQLServerDialect</property>
...
</hibernate-configuration>
次に、関数を使用します。
select x from MyEntity x where addminutes(x.creationDate, 10) < current_time()
(これは、エンティティがMyEntityと呼ばれ、creation_dateフィールドがcreationDateというプロパティにマップされていることを前提としています)。
HQLは日付と時刻の算術演算をサポートしていないため、HQLを拡張しないと不可能です。最も簡単な方法は、おそらくそのような計算のためにデータベースベンダーのSQL方言関数を登録することです。プラス記号とマイナス記号を使用した構文が望ましい場合は、インターセプターを実装して登録することもできます(オーバーライドする方法は)。onPrepareStatement
ソリューションが純粋にHQLである必要がなく、JVMホストからの時間が十分である場合、最も簡単なソリューションは、過去10分である日付を計算し、それを引数として指定することです。データベース時間を優先する場合は、別のクエリでクエリを実行してから10分ずつデクリメントすることで実現できます。