Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

duplicate result when using in-statement with bean cache #3441

Open
devDomM opened this issue Jul 8, 2024 · 3 comments
Open

duplicate result when using in-statement with bean cache #3441

devDomM opened this issue Jul 8, 2024 · 3 comments

Comments

@devDomM
Copy link

devDomM commented Jul 8, 2024

Expected behavior

When building an expressionList with an in-statement, like: .in("id", "1") for an entity that has bean caching enabled, by adding the @Cache Annotation, the actual object with the corresponding ID is returned when calling findList()

Actual behavior

The result of findList does contain objects with the same ID twice.

Steps to reproduce

It's important, that the in-statment has to retrieve a String value for a numerical field. This can be reproduced quite easily in the official play-java-ebean example.

The computer model has to have the @Cache Annotation added and the repository will execute the following query:

DB.find(Computer.class).where().in("id", "1").findList()

This will return the same object with ID 1 twice. When doing the reverse-test and acutally building the expression list with numerical values

DB.find(Computer.class).where().in("id", 1L).findList();

the object with ID 1 will only be returned once.

Also, just to be sure, the test by selecting the cached bean directly with a string value

DB.find(Computer.class).where().eq("id", "1").findList()

works as intended and returns the object with ID exactly once.

@MathiasSchoettle
Copy link

Refining the issue a bit further, after clearing the ebean cache, executing the following query returns a single entry.

DB.find(Computer.class).where().in("id", "1").findList()

Executing it again returns the two identical entries.

The issue seems to be that bean ids which are fetched from the cache are not removed correctly from the remaining ids which still need to be fetched from the datasource.

When converting the cached entry to a bean (class: BeanDescriptorCacheHelp#cacheIdLookup) the id is converted using the BeanDescriptor#convertId method, adding the bean to the query result.

The ids of cached beans should then be removed from the bindValues (class: InExpression#removeIds). But as the types of the ids don't match (bound values in Expression are of type String, the ids to remove are of type Long) no ids are removed and the subsequent query will fetch the duplicate entry from the data source.

I think either the bindValues list in the InExpression class needs to be of the actual type of the beans identifier or the removal of the ids in class: CacheIdLookupMany#removeHits has to convert the hitIds to the type of the inExpression.

@devDomM
Copy link
Author

devDomM commented Aug 26, 2024

is there any update on this topic, or further clarification required?

@rbygrave
Copy link
Member

.in("id", "1")

The workaround is to use the correct type in the predicate. In this case to not use String but instead the correct Long (or Integer?) type.

I'm expecting that is the workaround being used right? There isn't an issue using the workaround right? If there is an issue with that workaround then please state more clearly why we can't use the correct type.

This issue has lower priority based on the workaround being pretty good (so I'm really trying to look at other stuff according to priority).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants