Get "Invalid derived query" error all over the place in our Spring Data JpaRepository interfaces in STS 3.1 - spring

We have implemented our repositories exactly as demonstrated in the Spring Data documentation. Everything was fine until we upgraded from STS 2.9 to STS 3.1. All attempts to get these errors to disappear have failed, and in some cases they don't even make sense! They don't match any properties in either the interface or the entities used!
Here is an example:
public interface CreditNotesRepository extends JpaRepository<CreditNotes, Long> {
CreditNotes findCurrentCreditNotes(Long shipmentDetailId);
}
The findCurrentCreditNotes is a named query in our entity. This code executes perfectly fine.
#NamedQueries({
#NamedQuery(name = "CreditNotes.getCount", query = "SELECT COUNT(f) FROM CreditNotes f"),
#NamedQuery(name = "CreditNotes.findCurrentCreditNotes", query =
"SELECT creditNotes FROM CreditNotes creditNotes"
+ " WHERE creditNotes.shipmentDetail.shipmentDetailId = ?1 "
+ " AND creditNotes.notesSeqNumber = (SELECT max(creditNotes2.notesSeqNumber) FROM CreditNotes creditNotes2"
+ " WHERE creditNotes.shipmentDetail.shipmentDetailId = creditNotes2.shipmentDetail.shipmentDetailId)")
})
And the error we get:
Invalid derived query! No property find found for type ca.cole.freight.model.CreditNotes
Although this is just a flag (doesn't affect compilation), it is annoying and confusing. Can anyone shed some light on this? And explain it to me like I'm 6 years old! ;)

At the post on the Spring Forum, Spring Team announced that
It is already fixed for STS 3.3.0
I didn't check this version yet. But I'm using 3.5.0.RELEASE and the problem comes back! My fix is to uncheck Invalid Derived Query

It's an IDE error explained in the following post:
http://forum.springsource.org/showthread.php?138585-Invalid-derived-query!-No-property-delete-found-for-type-java-lang-Object
In the meantime, you can turn off the validation in preferences/spring/project validators/Data validator uncheck invalid derived query and STS wont throw the marker anymore.

There is also workaround for this. Add #Query annotation on your method definition in Your repository without JPQL/SQL query defined.
Here is example :
#Query
List<OwnerModel> findByFirstNameAndAgeNotZero(#Param(value = "firstName") String firstName);
In this case named query OrderModel.findByFirstNameAndAgeNotZero will be used. Your Eclipse error Invalid derived query should also disappear without need of disabling validation as described by #Tuan Dang
Checked on Eclipse 4.5.1 with Spring plugin installed for #NamedQuery and #NamedNativeQuery.

I've just been going through this myself. Unfortunately, the implementation of Spring Data changed between 1.1 and 1.2. It no longer supports the <repository> XML declaration. You can set up a custom postfix, but by default, it expects a bean of class name <InterfaceName>Impl. If it can't find the custom repository implementation, you start getting errors like the one you're encountering. It's trying to create methods to query for objects based on names of methods in your interface.
An alternative is to back your Spring Data version down to 1.1 and specify a schemalocation of http://www.springframework.org/schema/data/jpa/spring-jpa-1.1.xsd in your XML.

Related

Neo4j Dynamic cql switching

I want to switch database based on a request header, which I have managed to do but in a rather clunky way.
I had to change my jdbc driver to neo native driver to get the "USE database" prefix to work.
I had to prefix my cql query with "USE database "
What I really want is to do this via AOP, such that I can annotate the method with my custom java annotation and this aspect will just call "USE DATABASE" in isolation before going on to the joinpoint and calling the actual query.
When I try this though I get this error
Query cannot conclude with USE GRAPH (must be RETURN or an update clause)
Is it possible ?
You can change the database on the session object.
try (Session session = driver.session(SessionConfig.forDatabase( "databaseName" ))) {
session.executeWrite((tx) -> tx.run(stmt, params));
}
You shouldn't use JDBC for apps, that's rather for tools.
https://neo4j.com/docs/java-manual/current/cypher-workflow/#java-database-selection

#DataJpaTest breaks after upgrade from Spring Boot 2.6.6 to 2.7.0

After upgrading to the latest Spring Boot Version, several tests in classes that have the annotation "#DataJpaTest" were no longer working. Many things broke, but what was specifically weird was that "findBy" methods do not seem to query data correctly (when I run integration tests or do manual tests, they work fine). Here is a basic test I ran:
#Test
fun `When findByActivationTokenId then return Account`() {
val firstName = "John"
val lastName = "Doe"
val phone = "1234"
val email = "test#gmail.com"
val providerId = "google"
val providerUserId = "123"
val activationToken = UUID.randomUUID()
val account = Account(
firstName = firstName,
lastName = lastName,
email = email,
phoneNumber = phone,
providerId = providerId,
providerUserId = providerUserId,
title = "Herr",
activationTokenId = activationToken
)
entityManager.persist(account)
entityManager.flush()
val allAccounts = accountRepository.findAll()
val found = accountRepository.findByActivationTokenId(activationToken)
found.get() shouldNotBe null
found.get().providerId shouldBe providerId
found.get().providerUserId shouldBe providerUserId
}
I called "findAll()" so I can look at the result with the debugger. What I noticed was that the repository does in fact return the account exactly the way I persisted it, with the right activation token ID. The "findByActivationTokenId", however, returns an empty optional. Is this a bug or an oversight on my part? I looked into the deprecation information and found nothing specific to Spring Data JPA that could effect tests only.
The problem is related to the embedded h2 database. With the latest upgrade, a lot of features will no longer work with JPA. Here is the changelog:
http://www.h2database.com/html/migration-to-v2.html
This is a more specific comment on the implications for migration to Spring Boot 2.7 and using the new Version:
https://twitter.com/odrotbohm/status/1526594686932160515
There are various things that might go wrong here, and just as mpbeaujean I suspect the new version of H2 to be the culprit.
There are various things you can try. Which one is the right one for you depends on your specific reason to use H2.
Don't use H2. Often H2 is used in tests while something else is used in production. This is a crutch at best and I recommend to switch to Testcontainers and a docker image of the exact database version you have in production.
You could revert to H2 1.4. Just note that there is a CVE for it. If I remember correctly you can mitigate it when you make sure that the JDBC URL used is trusted. But you should research the CVE in order to decide if it is a problem for you.
If you have to use the current version of H2, or if not using it doesn't resolve the problem, you need to find out what is going on.
I'd try the answers given here first.
If it doesn't help, please post the class definition of your entity, the DDL for your table and the SQL including parameters that gets executed.

Exception:rg.springframework.cloud.gcp.data.datastore.core.mapping.DatastoreDataException: Unable to convert class PageRequest to Datastore

I have issue with Spring data. When I use #Query annotation with Pageable, for example:
#Query("SELECT * FROM myTable WHERE myTable.t_blob_name > NULL")
Slice<MyTable> findAllWithPageable(Pageable pageable);
I will have next exception (That application runs on Google cloud platform):
org.springframework.cloud.gcp.data.datastore.core.mapping.DatastoreDataException: Unable to convert class org.springframework.data.domain.PageRequest to Datastore supported type.
at org.springframework.cloud.gcp.data.datastore.core.convert.DatastoreNativeTypes.wrapValue (DatastoreNativeTypes.java:166)
at org.springframework.cloud.gcp.data.datastore.core.convert.TwoStepsConversions.convertOnWriteSingle (TwoStepsConversions.java:320)
at org.springframework.cloud.gcp.data.datastore.repository.query.GqlDatastoreQuery.bindArgsToGqlQuery (GqlDatastoreQuery.java:233)
at org.springframework.cloud.gcp.data.datastore.repository.query.GqlDatastoreQuery.execute (GqlDatastoreQuery.java:118)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke (RepositoryFactorySupport.java:605)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.lambda$invoke$3 (RepositoryFactorySupport.java:595)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke (RepositoryFactorySupport.java:595)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:186)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke (DefaultMethodInvokingMethodInterceptor.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:186)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke (ExposeInvocationInterceptor.java:93)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:186)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke (SurroundingTransactionDetectorMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed (ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke (JdkDynamicAopProxy.java:212)
It's a google cloud DataStore syntax and the main question - how to resolve that problem?
There is a list of supported classes that can be used within GQL. You can find it in reference point 158.5.2 and directly in code on GitHub if you prefer. Actually the Pageable class is not among them.
I noticed that you are not using this paramater in the query so I suggest to use Slice<MyTable> findAllWithPageable() Similar query you may find in here.
I hope it will help!

Spring Data MongoDB failed with "in" query

I'm using spring-data-mongodb 1.8.0; MongoDB 3.0.6; mongo-java-driver 3.1.0;spring-framework.version 4.0.3.
What I want is to query a list of user with certain phone numbers.
example for user: { "_id" : ObjectId("5625e5c32e1ca013a03f0d1b"), "phone" : "12345535"}
In Mongo Shell db.user.find({phone: { $in: [ "12345535", "123535"]}}) works fine. But in Spring I failed. Java Class User(with getters/setters omitted):
#Document(collection = "user")
public class User {
#Id
String id;
String phone;
}
What I tried is:
Query q = new Query(Criteria.where("phone").in("12345535","123535"));
mongoTemplate.find(q, User.class);
It comes to error:
Exception in thread "main" java.lang.IllegalAccessError: tried to access class org.springframework.beans.PropertyMatches from class org.springframework.data.mapping.PropertyReferenceException
at org.springframework.data.mapping.PropertyReferenceException.detectPotentialMatches(PropertyReferenceException.java:134)
at org.springframework.data.mapping.PropertyReferenceException.<init>(PropertyReferenceException.java:59)
at org.springframework.data.mapping.PropertyPath.<init>(PropertyPath.java:75)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:327)
at org.springframework.data.mapping.PropertyPath.create(PropertyPath.java:307)
at org.springframework.data.mapping.PropertyPath.from(PropertyPath.java:270)
at org.springframework.data.mongodb.core.convert.QueryMapper$MetadataBackedField.getPath(QueryMapper.java:837)
at org.springframework.data.mongodb.core.convert.QueryMapper$MetadataBackedField.<init>(QueryMapper.java:729)
at org.springframework.data.mongodb.core.convert.QueryMapper$MetadataBackedField.with(QueryMapper.java:740)
at org.springframework.data.mongodb.core.convert.QueryMapper$MetadataBackedField.with(QueryMapper.java:686)
at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedKeyword(QueryMapper.java:258)
at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedObjectForField(QueryMapper.java:200)
at org.springframework.data.mongodb.core.convert.QueryMapper.getMappedObject(QueryMapper.java:123)
at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1700)
at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1690)
at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:602)
at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:593)
at com.example.TestMongo.main(TestMongo.java:30)
But with changing field phone to id, same code works fine.
Query q = new Query(Criteria.where("id").in("5625e5c32e1ca013a03f0d1b","f0d1e"));
mongoTemplate.find(q, User.class);
With debugging, I find that it even didn't go to the request phase, error occurred in the query-building phase. It seems $in cannot be processed by PropertyPath.create, while in the id case, it can.
How can I fix this? I am a newbie and searched a lot but got no luck.Can you please help me out. Every answer is appreciated. Thanks guys.
As indicated in the announcement blog and the release train wiki, Spring Data MongoDB 1.8 requires Spring 4.1, ideally 4.1.8 which includes an important security fix.
The issue have appeared on me while using Spring 4.2.3.RELEASE and Spring MongoDB 1.6.1
Switching to Spring mongoDB 1.8.1 solves the issue.
(Meant as a comment to #OliverGierke's answer, but couldn't do it, due to low reputation level.)

EF6.1 Upgrade Issues: To SQL Server CE file Location and [NotMapped] Properties

I really appreciate any insight anyone can provide.
I've come back to a project that was using the EF6.0 rc preview. After updating the projects EF to 6.1 and updating the SQL Server CE I have two problems.
[UPDATE]
Problems 1 & 2 solved Problem 3 is not.
PROBLEM 3 -
Now with the path set via a connection string as explained above, migrations called via the package manager are not working as its an invalid path. Any ideas anyone?
When I start up the debug process, I get problem 1 and the exceptions crash; but it does create a .sdf file although in the wrong location as explained in problem 2.
1. NOT MAPPED PROPERTY AND UNSUPPORTED BY LINQ ERROR
During the initial creation process I get an exception
List<Equipment> duplicateTags = db.EquipmentReg
.GroupBy(e => e.TagAndLocation)
.Where(g => g.Count() > 1)
.SelectMany(g => g).ToList<Equipment>();
The exception is related to the TagAndLocation. TagAndLocation is defined in the model by
/// <summary>
/// Creates concatenation object that will not be mapped in the database but will be in the
/// Object Relational Mapping (ORM) of the EF model.
/// </summary>
[NotMapped]
public string TagAndLocation { get { return Tag + " (" + Location.Name + ")"; } }
A first chance exception of type 'System.NotSupportedException' occurred in EntityFramework.dll
Additional information: The specified type member 'TagAndLocation' is
not supported in LINQ to Entities. Only initializers, entity members,
and entity navigation properties are supported.
Why is this happening now?
2. CONNECTION STRING NOT APPLYING LOCATION
My connection isn't applying the path properly anymore.
I have it being done by a DbConfiguration class which auto runs, I guess due to its inherited class type. As shown below
class HAIDbJob_EFConfiguration : DbConfiguration
{
public HAIDbJob_EFConfiguration()
{
SetProviderServices(SqlCeProviderServices.ProviderInvariantName, SqlCeProviderServices.Instance);
// Create the connection string programmatically - Setting the filename and path.
SetDefaultConnectionFactory(new System.Data.Entity.Infrastructure.SqlCeConnectionFactory(
"System.Data.SqlServerCe.4.0",
System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Databases"),
#"Data Source=" + System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Databases") +
#"\Hazardous_Area_Database_Job.sdf"));
}
}
Instead of creating a file in the runtime location ...\bin\Debug\Databases\Hazardous_Area_Database_Job.sdf, it creates it at
..\bin\Debug\HA_Inspector.HAI_Database.HAI_Job_EF_Model.Hazardous_Area_Database_Job.sdf
Which is the full namespace of the database model... I have tried a few solutions found for other people problems of a slightly different nature, but none of it works. Any ideas would be extremely appreciate.
1: The EF provider attempt to translate TagAndLocation to SQL and fails. You must use LINQ to Objects for this grouping.
2: Why not have a named connectionstring in your app.config, or pass it in the DbContext constructor.
SOLUTION 1
I did a string compare in the group by statement since location has a string member Location.Name.
SOLUTION 2
When I originally wrote this I wanted to dynamically name the database all the time and this is why I wrote the initialiser class.
To get around the problem, I just followed Erik's advice and put a XAML connection string in app.config using "Source=./Databases"..... to get the subfolder.

Resources