Spring boot Data JDBC + Querydsl error " Reason: No property count found for type" - spring-boot

I'm trying to use Spring data JDBC with Query DSL in Kotlin.
This is my repository
#Repository
interface UserRepository : PagingAndSortingRepository<User, Int>, QuerydslPredicateExecutor<User> {}
My entity is a simple data object
#Entity
#Table(name = "user")
data class User(
#Id
#GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_id_seq")
#SequenceGenerator(name = "user_id_seq", sequenceName = "user_id_seq", allocationSize = 1)
val id: Int? = null,
val name: String,
val surname: String)
I've added these lines to my build.gradle
implementation("com.querydsl:querydsl-sql-spring:4.4.0") {
exclude group: 'joda-time', module: 'joda-time'
}
kapt "com.querydsl:querydsl-apt:4.4.0:jpa"
I've added the #EnableJdbcrepositories annotation in my Spring application
But when I try to start my application I get this error:
Unsatisfied dependency expressed through constructor parameter 1; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userRepository' defined in my.tests.querydsl.repositories.UserRepository defined in #EnableJdbcRepositories declared on
JdbcRepositoriesRegistrar.EnableJdbcRepositoriesConfiguration: Invocation of init method failed; nested exception is org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract long org.springframework.data.querydsl.QuerydslPredicateExecutor.count(com.querydsl.core.types.Predicate)! Reason: No property count found for type User!
I tried also to remove #EnableJdbcrepositories annotation but the error persists.
What I'm doing wrong? I'm missing some dependency?
Thanks

Infobip Spring Data Querydsl provides QuerydslPredicateExecutor fragment support for Spring Data JDBC (among other things).
With it, UserRepository definition should work as is defined, check out the module README.md JDBC section for details.
If you need SQLQuery, SQLUpdateClause or delete with Predicate support don't miss the QuerydslJdbcFragment.

The Spring-Data book says that only Spring Data JPA and MongoDB support QuerydslPredicateExecutor

Related

Hibernate Upgrade to v6 (Spring Boot 3) - "Named type [interface java.util.List] did not implement BasicType nor UserType"

After upgrading to Spring Boot 3 / Hibernate 6, I am getting exceptions during Spring application / test startup.
java.lang.IllegalStateException: Failed to load ApplicationContext for [WebMergedContextConfiguration#15ec3c0c testClass = ....
Caused by: jakarta.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is java.lang.IllegalArgumentException: Named type [interface java.util.List] did not implement BasicType nor UserType
Problem can be traced / debugged down to a List<String> entity property, which is using an AttributeConverter for storing it as a comma-separated string in the (MySQL) DB (TEXT field).
The converter:
#Converter
class StringListToStringConverter : AttributeConverter<List<String>, String> {
....
}
The entity:
#MappedSuperclass
abstract class MyInstance<T>(
...
#Column(name = "iface_ids", columnDefinition = "TEXT")
#Convert(converter = StringListToStringConverter::class)
var interfaceIds: List<String> = emptyList()
...
)
This has been working nicely before with Spring Boot 2.7.x / Hibernate 5.x.
Do you think there is another solution than writing a custom type (and thus removing/replacing the AttributeConverter) in this case?
Kind Regards,
dom
Expecting it to actually work OOTB, the AttributeConverter solution looks so clean&simple for this purpose compared to a custom type implementation that I don't really want to change that.

Spring Boot and Kotlin - Cannot find my ID

I'm unable to get documents by Id (using Spring Boot and Mongo) - I've tried the following lines with no luck:
sRepository.findById(songId)
and
query.addCriteria(Criteria.where("_id").is(songId))
I've added the #Id annotation in my model to specify the id field:
#Document(collection = "songs")
data class Song(
#Id
val id: String,
and in my mongo the document I've added looks like:
{
"_id": "532132assad4a0",
"code": "956743458",
...
The Mongo repository class:
#Repository
interface SongRepository : MongoRepository<Song, String>
Any help would be appreciated - rather confused by it.
FOUND THE ANSWER:
I had to add the annotation #MongoId instead of #Id as I was saving it as a string, didn't want any other conversion happening on it.
Found at the documentation here: https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mapping.conventions.id-field

quarkus and hibernate mapping (field access)

I moved an entity which worked in JEE wildfly to quarkus:
#Entity
#Getter
#Setter
public class Item {
#Column(name = "archived")
private OffsetDateTime archived;
public boolean isArchived() {
return archived != null;
}
}
After running in dev-mode, I get this error:
Caused by: org.hibernate.MappingException:
In trying to locate getter for property [archived],
Class [com.Item]
defined both a `get` [public java.time.OffsetDateTime com.Item.getArchived()]
and `is` [public boolean com.Item.isArchived()] variant
at org.hibernate.internal.util.ReflectHelper.checkGetAndIsVariants(ReflectHelper.java:538)
at org.hibernate.internal.util.ReflectHelper.verifyNoGetVariantExists(ReflectHelper.java:562)
at org.hibernate.internal.util.ReflectHelper.getGetterOrNull(ReflectHelper.java:502)
at org.hibernate.internal.util.ReflectHelper.findGetterMethod(ReflectHelper.java:424)
at org.hibernate.internal.util.ReflectHelper.getterMethodOrNull(ReflectHelper.java:571)
at org.hibernate.property.access.internal.PropertyAccessMixedImpl.getAccessType(PropertyAccessMixedImpl.java:97)
at org.hibernate.property.access.internal.PropertyAccessMixedImpl.<init>(PropertyAccessMixedImpl.java:47)
at org.hibernate.property.access.internal.PropertyAccessEnhancedImpl.<init>(PropertyAccessEnhancedImpl.java:28)
at org.hibernate.property.access.internal.PropertyAccessStrategyEnhancedImpl.buildPropertyAccess(PropertyAccessStrategyEnhancedImpl.java:27)
at org.hibernate.mapping.Property.getGetter(Property.java:311)
at org.hibernate.tuple.entity.PojoEntityTuplizer.buildPropertyGetter(PojoEntityTuplizer.java:255)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.<init>(AbstractEntityTuplizer.java:142)
at org.hibernate.tuple.entity.PojoEntityTuplizer.<init>(PojoEntityTuplizer.java:59)
... 35 more
I understand the error but I dont know why does this hibernate mapping work in wildfly and not in quarkus? As I declared jpa field access instead of jpa property access, hibernate should see the isArchived() automatically as transient.
Or does quarkus compiles all these field-injections to property-injections?
Quarkus generates a getter for the archived field.
Here Hibernate complains that you have two accessors for the archived field: isArchived() and getArchived().
This is an Hibernate issue/limitation, nothing specific to Quarkus.
I think the best is to rename your isArchived() method as Hibernate don't know which method to use to retrieve the value of the archivedfield. And if you add #Transient to your isArchived() method it could (depending on wich method it get first) handle your field as transient.

Spring Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)

I can't understand, what's wrong with my Service. I receive org.hibernate.StaleObjectStateException trying to run this method:
fun updateNameForPhone(phone: String, name: String): Client {
val res = clientRepository.findByPhone(phone) ?: throw ClientNotFoundException(phone)
res.name = name
return clientRepository.save(res)
}
ClientRepository:
#Repository
interface ClientRepository : JpaRepository<Client, UUID> {
fun findByPhone(phone: String): Client?
}
Client entity:
#Entity
data class Client(
var name: String = "",
var phone: String = "",
#Id #GeneratedValue(strategy = GenerationType.AUTO)
val uuid: UUID = defaultUuid()
)
Exception:
Object of class [com.app.modules.client.domain.Client] with identifier
[12647903-7773-4f07-87a8-e9f86e99aab3]: optimistic locking failed;
nested exception is org.hibernate.StaleObjectStateException: Row was
updated or deleted by another transaction (or unsaved-value mapping
was incorrect) :
[com.app.modules.client.domain.Client#12647903-7773-4f07-87a8-e9f86e99aab3]"
What is the reason?
I'm using Kotlin 1.3.11, Spring Boot 2.1.1, MySql. I don't run it in different threads, just trying with single request.
Well, finally I've found a solution. Better say workaround.
The problem is in the way spring uses UUID as entity identifier.
So there are two workarounds, solving this issue:
first, you can change your id field type to other one, such as Long, for example, if it's possible to you;
or you can add this annotation to your uuid field: #Column(columnDefinition = "BINARY(16)").
The last solution I've found from this question.

Method signature not resolving for kotlin in Java

IN my project I am using graphql-spring-java to implement a graphql endpoint. I have the graphql schema defined and all the entities put together in kotlin. The problem is that one of my method signatures in my kotlin is not resolving correctly while all the other ones do. Here's the error verbatim:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.coxautodev.graphql.tools.SchemaParser]: Factory method 'schemaParser' threw exception; nested exception is com.coxautodev.graphql.tools.FieldResolverError: No method or field found with any of the following signatures (with or without one of [interface graphql.schema.DataFetchingEnvironment] as the last argument), in priority order:
ninja.familyhomestay.domain.Host.reservations()
ninja.familyhomestay.domain.Host.getReservations()
ninja.familyhomestay.domain.Host.reservations
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:582)
... 105 common frames omitted
Caused by: com.coxautodev.graphql.tools.FieldResolverError: No method or field found with any of the following signatures (with or without one of [interface graphql.schema.DataFetchingEnvironment] as the last argument), in priority order:
ninja.familyhomestay.domain.Host.reservations()
ninja.familyhomestay.domain.Host.getReservations()
ninja.familyhomestay.domain.Host.reservations
at com.coxautodev.graphql.tools.FieldResolverScanner.missingFieldResolver(FieldResolverScanner.kt:51)
at com.coxautodev.graphql.tools.FieldResolverScanner.findFieldResolver(FieldResolverScanner.kt:42)
and here is the code in question:
#Entity
#Table(name = "host")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#Document(indexName = "host")
class Host(
...
#OneToMany(mappedBy = "host")
var reservations: MutableSet<Reservation> = HashSet()
) : Serializable
#Entity
#Table(name = "reservation")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
#Document(indexName = "reservation")
data class Reservation(
....
#ManyToOne
#JoinColumn(name = "host_id")
var host: Host? = null,
...) : Serializable {
companion object {
private const val serialVersionUID = 1L
}
}
Obviously there's nothing wrong with code so I am thinking that it's an issue with kotlin. What do you think? I am using kotlin version 1.2.51 and idea 2018.2.eap.

Resources