Je suis un débutant dans Spring Framework.
J'utilise les types hibernate pour convertir un intervalle PostgreSQL en un objet de durée Java.
Pour sélectionner toutes les lignes, cela fonctionne très bien. J'ai créé un modèle de données pour la table spécifique et utilisé l'annotation TypeDef pour le mappage:
org.postgresql.util.PSQLException: ERROR: cannot cast type bigint to interval
Mais maintenant, je souhaite créer une requête native personnalisée. Je souhaite sélectionner toutes les lignes de la table Test, où flightDuration est un RequestParam d'un webservice. Comme ceci comme exemple de base (la vraie requête est beaucoup plus complexe et nécessite des fonctions postgres spéciales):
public interface TestRepository extends JpaRepository<Test, int> {
@Query( value = SELECT * FROM test t WHERE flight_duration = ?1 , nativeQuery = true )
List<Test> findByFlightDuration(Duration flightDuration);
}
Mais voici mon problème. Je ne sais pas comment utiliser le PostgreSQLIntervalType pour convertir la durée en un intervalle PostgreSQL.
Si j'exécute la requête comme ci-dessus, j'obtiendrai l'erreur suivante:
@Entity
@Table(name = "test")
@Typedef(
typeClass = PostgreSQLIntervalType.class,
defaultForType = Duration.class
)
@Getter @Setter
public class Test {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int id;
private Duration flightDuration;
}
Alors là où je dois définir une annotation (ou peu importe) comme le TypeCast dans la classe de test, que la durée sera transtypée en un PostgreSQLIntervalType?
3 Réponses :
Il n'y a aucune raison d'utiliser une requête native. Vous pouvez simplement JPQL.
@Query( value = "FROM test t WHERE flight_duration = ?1") List<Test> findByFlightDuration(Duration flightDuration);
cela ne fonctionne pas non plus: org.postgresql.util.PSQLException: ERREUR: l'opérateur n'existe pas: intervalle = bigint. Et comme mentionné, j'ai besoin de certaines méthodes spécifiques postgres dans la requête réelle. Ceci n'est qu'un exemple.
@ user2622344 vous ne devez pas utiliser db specifica si l'utilisation de jpa.jpa consiste à abstraire la base de données sous-jacente.
Si vous avez VRAIMENT besoin de la requête native, parce que vous en avez besoin, vous devez convertir l'entier de votre requête en un intervalle de PostgreSQL.
Je suppose que vous fournissez des secondes dans votre requête, et le ? 1 est le nombre de secondes que prendra votre vol.
Essayez ce qui suit:
@Query(value = SELECT * FROM test t WHERE flight_duration = (?1 || ' secs') , nativeQuery = true ) List<Test> findByFlightDuration(int flightDurationInSec);
Plus d'informations ici: https://www.postgresql.org/message-id/Pine.LNX.4.44.0410051443550.13144-100000@matrix.gatewaynet.com p>
Mais je vous suggère de vérifier si vous en avez vraiment besoin ou non. Peut-être que vous pouvez essayer avec JPQL. Faites-nous savoir.
Alternativement: make_interval (secs =>? 1)
Pour les requêtes SQL natives, vous devez utiliser la méthode setParameter Query spécifique à Hibernate pour fournir le type Hibernate nécessaire pour gérer les types de colonnes personnalisés:
List<Test> tests = entityManager.createNativeQuery("""
SELECT *
FROM test t
WHERE flight_duration = :duration
""", Test.class)
.unwrap(org.hibernate.query.Query.class)
.setParameter("duration", flightDuration, PostgreSQLIntervalType.INSTANCE)
.getResultList();
De cette façon, Hibernate saura comment gérer le paramètre de requête duration .
Pourquoi utiliser une requête native?