Это очень интересный вопрос, поэтому я решил превратить в статью .
Как описано в Руководстве пользователя yu может использовать функцию EXTRACT
:
List<Integer> days = entityManager
.createQuery(
"select extract( day from c.timestamp ) " +
"from Call c ", Integer.class )
.getResultList();
или функцию day
:
List<Integer> days = entityManager
.createQuery(
"select day( c.timestamp ) " +
"from Call c ", Integer.class )
.getResultList();
Регистрация функции DATE_TRUNC с использованием MetadataBuilderContributor
Если вам также нужно использовать AT TIMEZONE
, вам необходимо зарегистрировать функцию PostgreSQL следующим образом:
public class SqlFunctionsMetadataBuilderContributor
implements MetadataBuilderContributor {
@Override
public void contribute(MetadataBuilder metadataBuilder) {
metadataBuilder.applySqlFunction(
"date_trunc",
new SQLFunctionTemplate(
StandardBasicTypes.TIMESTAMP,
"date_trunc('day', (?1 AT TIME ZONE 'UTC'))"
)
);
}
}
Настройка MetadataBuilderContributor
с использованием JPA persistence.xml
Теперь,вам нужно предоставить SqlFunctionsMetadataBuilderContributor
для Hibernate через свойство конфигурации hibernate.metadata_builder_contributor
:
<property>
name="hibernate.metadata_builder_contributor"
value="com.vladmihalcea.book.hpjp.hibernate.query.function.SqlFunctionsMetadataBuilderContributor"
</property>
Настройка MetadataBuilderContributor
с использованием Spring Boot
Если вы используете Spring Boot, вынеобходимо добавить следующую конфигурацию в файл application.properties
:
spring.jpa.properties.hibernate.metadata_builder_contributor=com.vladmihalcea.book.hpjp.hibernate.query.function.SqlFunctionsMetadataBuilderContributor
Данные тестирования
Затем, при условии, что в базе данных имеется следующая сущность Post
:
Post post = new Post();
post.setId(1L);
post.setTitle(
"High-Performance Java Persistence"
);
post.setCreatedOn(
Timestamp.valueOf(
LocalDateTime.of(2018, 11, 23, 11, 22, 33)
)
);
entityManager.persist(post);
Использование DATE_TRUNC в JPQL
Вы можете вызвать функцию date_trunc
в JPQL следующим образом:
Tuple tuple = entityManager
.createQuery(
"select p.title as title, date_trunc(p.createdOn) as creation_date " +
"from Post p " +
"where p.id = :postId", Tuple.class)
.setParameter("postId", 1L)
.getSingleResult();
assertEquals(
"High-Performance Java Persistence",
tuple.get("title")
);
assertEquals(
Timestamp.valueOf(
LocalDateTime.of(2018, 11, 23, 0, 0, 0)
),
tuple.get("creation_date")
);
Для получения более подробной информации, ознакомьтесь с этой статьей .
Настройка часового пояса, переданного в DATE_TRUNC
Если вы хотите настроить часовой пояс, просто передайте часовой поясв качестве параметра, подобного этому:
public static class SqlFunctionsMetadataBuilderContributor
implements MetadataBuilderContributor {
@Override
public void contribute(MetadataBuilder metadataBuilder) {
metadataBuilder.applySqlFunction(
"date_trunc",
new SQLFunctionTemplate(
StandardBasicTypes.TIMESTAMP,
"date_trunc('day', (?1 AT TIME ZONE ?2))"
)
);
}
}
Теперь вы можете вызвать функцию date_trunc
следующим образом:
Tuple tuple = entityManager
.createQuery(
"select p.title as title, date_trunc(p.createdOn, :timezone) as creation_date " +
"from Post p " +
"where p.id = :postId", Tuple.class)
.setParameter("postId", 1L)
.setParameter("timezone", "UTC")
.getSingleResult();
Контрольные примеры
Я создал следующий тестслучаи в моем высокопроизводительном хранилище GitHub-java-persistence, и они работают нормально: