Skip to content
New issue

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

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

Already on GitHub? # to your account

WHERE clause not working well with ENUM types #56

Open
kasimmm opened this issue Apr 27, 2017 · 13 comments
Open

WHERE clause not working well with ENUM types #56

kasimmm opened this issue Apr 27, 2017 · 13 comments

Comments

@kasimmm
Copy link

kasimmm commented Apr 27, 2017

Hi,
I have a model with an enum property like this:

public class AuthKey {
private static final long serialVersionUID = 1L;

	public enum Status {
	    PENDING,
	    AUTHORIZED
	}

        @Enumerated(EnumType.STRING)
	private Status status;
        ......
}

The enum field is persisted in MySQL as varchar.

When I do a search like
streamAll(em, AuthKey.class).where(k->k.getStatus() == Status.PENDING)
it works just fine.

But when I do a search using a parameter

Status s = Status.PENDING;
streamAll(em, AuthKey.class).where(k->k.getStatus() == s)

it complains that 'Parameter value did not match expected type'

Any idea why? Thanks

@my2iu
Copy link
Owner

my2iu commented Apr 27, 2017

This seems to be a Hibernate error. Usually enums passed through Jinq work fine with Hibernate, so I'm not sure what the issue might be. Do you have more detailed error information from Hibernate? What did Hibernate say was the expected type and what did it think it received?

@kasimmm
Copy link
Author

kasimmm commented Apr 27, 2017

It said something like this

java.lang.IllegalArgumentException: Parameter value [PENDING] did not match expected type [com.abc.model.AuthKey$Status (n/a)]
        at org.jinq.jpa.JPAQueryComposer.fillQueryParameters(JPAQueryComposer.java:127)
	at org.jinq.jpa.JPAQueryComposer.executeAndReturnResultIterator(JPAQueryComposer.java:167)
	at org.jinq.orm.stream.QueryJinqStream.createWrappedStream(QueryJinqStream.java:37)
	at org.jinq.orm.stream.LazyWrappedStream.realizeStream(LazyWrappedStream.java:41)
	at org.jinq.orm.stream.LazyWrappedStream.collect(LazyWrappedStream.java:227)
	at org.jinq.orm.stream.NonQueryJinqStream.toList(NonQueryJinqStream.java:492)

I checked in the lambda expression, both the k.getStatus() and s are with Enum type.

I also tried fetching a record without the where clause then compared it with the parameter like
result(0).getStatus() == s
and it actually returned true.

@my2iu
Copy link
Owner

my2iu commented Apr 27, 2017

That seems strange. What happens when you move the Status enum to be its own top-level class instead of an inner-class? That's the only difference that I can see from my own test cases.

@my2iu
Copy link
Owner

my2iu commented Apr 27, 2017

Maybe making the Status enum static would work too?

@kasimmm
Copy link
Author

kasimmm commented Apr 27, 2017

Hmmmm still no luck with making it the top-level enum class.
Ahhh just realised I forgot to mention that the parameter was actually passed from another service like this:

authKeyService.getAuthKey(Status.PENDING);

then in this AuthKeyService:

public AuthKey getAuthKey(Provider provider) throws AuthKeyServiceException {
		List<AuthKey> authKeys = streamAll(em, AuthKey.class).where(k -> k.getProvider() == provider).toList();
               ........
}

Maybe it is the reason?

@my2iu
Copy link
Owner

my2iu commented Apr 27, 2017

That should be fine. But there might be a classloader issue. Have you looked at this Stack Overflow about Hibernate and enums?

http://stackoverflow.com/questions/27622045/parameter-value-did-not-match-expected-type

@my2iu
Copy link
Owner

my2iu commented Apr 27, 2017

If that still doesn't work, you could try just dropping down to raw JPA/Hibernate there and seeing if the problem still comes up.

em.createQuery("SELECT * FROM AuthKey a WHERE a.status = :param")
   .setParameter("param", s)
   .getResultList()

It's seems like a strange Hibernate issue, so I'm just suggesting random ideas. What happens if you move the @Enumerated(EnumType.STRING) annotation onto the getter instead of the field? What happens if you make the status field public instead of private?

@aVolpe
Copy link

aVolpe commented Apr 27, 2017

@my2iu all the enums are static!, even if they are nested.

I am using code like the one you provided @kasimmm with hibernate 5.2 with no issue.

@kasimmm
Copy link
Author

kasimmm commented Apr 28, 2017

@my2iu

  • Yes using raw JPA solves the problem.
  • I also tried the other two suggestions you mentioned, and the other one from Stack Overflow (mapping unique ID with enum). Unfortunately none of them does the trick :(

@aVolpe I'm having some trouble switching to 5.2 (we are using 4.3) at the moment. Will definitely give it a try later.

Anyway, thank you both for your time and help :)

@my2iu
Copy link
Owner

my2iu commented Apr 28, 2017

If the raw JPA seems to work, then I don't know what the issue could be because that should be exactly the same code that Jinq is running.

The Stack Overflow solution is actually at the end of the page (it's not the first one listed). The accepted solution says there might be a classloader problem because of the way things are packaged up (it's possible to have two classes with the same name which Java thinks are different because they were loaded in different class loaders). But if the raw JPA worked for you, then that shouldn't be an issue.

I don't think I'll be able to help you further with this without some sample code that exhibits the problem that I can run and debug.

@kasimmm
Copy link
Author

kasimmm commented May 1, 2017

@my2iu
Sorry for the late reply.
I tried to replicate it with some sample code using same libs (hibernate-4.3.11, hibernate-jpa-2.0.1, etc.) but it worked just fine. The only difference is that our application runs as a spring boot application, which shouldn't really matter in this case.
I'm using the raw JPA as a solution for now and will try to setup another env (spring boot/mysql) if I have some time.

@aVolpe
Turns out that hibernate version isn't the issue as I was using the same version with some sample code and it worked fine.

Cheers.

@OknoLombarda
Copy link

I don't know if this was the case for kasimmm, but I have encountered similar issue. The problem was that we had spring devtools in dependencies of our project, so what it does is it loads all third-party libraries with default ClassLoader, but all project classes with a separate ClassLoader. Removing devtools from dependencies solved the issue

@bodiam
Copy link

bodiam commented May 17, 2022

@OknoLombarda you saved me. I spent 3+ hours debugging this, and your comment fixed it!

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

No branches or pull requests

5 participants