Jinq icon indicating copy to clipboard operation
Jinq copied to clipboard

WHERE clause not working well with ENUM types

Open kasimmm opened this issue 8 years ago • 13 comments

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

kasimmm avatar Apr 27 '17 02:04 kasimmm

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?

my2iu avatar Apr 27 '17 03:04 my2iu

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.

kasimmm avatar Apr 27 '17 03:04 kasimmm

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 avatar Apr 27 '17 05:04 my2iu

Maybe making the Status enum static would work too?

my2iu avatar Apr 27 '17 05:04 my2iu

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?

kasimmm avatar Apr 27 '17 06:04 kasimmm

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 avatar Apr 27 '17 13:04 my2iu

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?

my2iu avatar Apr 27 '17 14:04 my2iu

@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.

aVolpe avatar Apr 27 '17 14:04 aVolpe

@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 :)

kasimmm avatar Apr 28 '17 00:04 kasimmm

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.

my2iu avatar Apr 28 '17 03:04 my2iu

@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.

kasimmm avatar May 01 '17 06:05 kasimmm

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

OknoLombarda avatar May 19 '21 11:05 OknoLombarda

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

bodiam avatar May 17 '22 10:05 bodiam