I have a two named native queries in my orm.xml
, one for retrieving the data, and one for doing the count for my pagination:
<named-native-query name="Person.findPeople.count">
<query>select count(*) from
from person
</query>
</named-native-query>
<named-native-query name="Person.findPeople">
<query>select first_name, last_name
from person
</query>
</named-native-query>
To load this data, I have a Spring Data Repository, which loads a projection of the data (my actual code is more complex than the provided example):
@Query(nativeQuery = true)
fun findPeople(pageable: Pageable): Page<PersonFirstName>
Now, when I execute the above code, I'm getting an error:
Caused by: java.lang.IllegalArgumentException: Named query exists but its result type is not compatible
at org.hibernate.internal.AbstractSharedSessionContract.resultClassChecking(AbstractSharedSessionContract.java:984) ~[hibernate-core-5.6.9.Final.jar:5.6.9.Final]
at org.hibernate.internal.AbstractSharedSessionContract.createNativeQuery(AbstractSharedSessionContract.java:942) ~[hibernate-core-5.6.9.Final.jar:5.6.9.Final]
at org.hibernate.internal.AbstractSharedSessionContract.buildQueryFromName(AbstractSharedSessionContract.java:920) ~[hibernate-core-5.6.9.Final.jar:5.6.9.Final]
This is caused by Hibernate, which doesn't want to map the native count query to a Long. I've changed the named-native-query
in my orm.xml
to a named-query
, and that does work, but I can't use that in my actual code.
The full code to reproduce the issue is this (and can also be found on Github):
@SpringBootApplication
class HibernateBugApplication : ApplicationRunner {
@Autowired
lateinit var personRepository: PersonRepository
override fun run(args: ApplicationArguments?) {
personRepository.saveAll(listOf(Person("a", "a1"), Person("b", "b1"), Person("c", "c1")))
personRepository.findPeople(Pageable.ofSize(2))
}
}
@Repository
interface PersonRepository : JpaRepository<Person, Long> {
@Query(nativeQuery = true)
fun findPeople(pageable: Pageable): Page<PersonFirstName>
}
interface PersonFirstName {
fun getName(): String
}
@Entity
class Person(
val firstName: String,
val lastName: String,
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
var id: Long? = null
)
And the orm.xml
:
<!-- This query works, but the named version does not.
<named-query name="Person.findPeople.count">
<query>select count(p) from Person p</query>
</named-query>
-->
<named-native-query name="Person.findPeople.count">
<query>select count(*) from
from person
</query>
</named-native-query>
<named-native-query name="Person.findPeople">
<query>select first_name, last_name
from person
</query>
</named-native-query>
I almost think this may be a bug in Hibernate, but before reporting it there I'd love to know if I'm not missing something in my configuration.
I'm using Spring 2.7.1, Hibernate 5.6.9, and Kotlin 1.7.0