my2iu / Jinq

LINQ-style queries for Java 8
Other
660 stars 71 forks source link

A Stream that returns a list of UUIDs is not serializable #104

Closed OssNass closed 2 years ago

OssNass commented 2 years ago

I have 2 entities:

ProxyEntity: Id(UUID), IssueDate, IssueNumber, RegistrationNumberId, WriterId among others.
ClientPerProxyEntity: ProxyId, ClientID, Both UUID

Now when I apply the following code:

var proxies = clientPerProxyRepository.createStream().where(item -> item.getClientId().equals(id))
                            .select(ClientPerProxyEntity::getProxyId);
proxyStream.where(proxy->JPQL.isIn(proxy.getId(),proxies)

It says

java.lang.IllegalArgumentException: Could not extract code from lambda. This error sometimes occurs because your lambda references objects that aren't Serializable

But when I apply the following code:

var tmp = proxyStream1.join((c, source) -> source.stream(ProxyEntity.class))
                            .where(pair -> pair.getOne().getIssueDate().equals(pair.getTwo().getIssueDate())
                                    && pair.getOne().getIssueNumber().equals(pair.getTwo().getIssueNumber())
                                    && pair.getOne().getRegistrationNumberId()
                                            .equals(pair.getTwo().getRegistrationNumberId())
                                    && pair.getOne().getWriterId().equals(pair.getTwo().getWriterId())
                                    && !pair.getOne().getId().equals(pair.getTwo().getId()))
                            .select(Pair::getOne).select(ProxyEntity::getId);
proxyStream.where(item->JPQL.isIn(item.getId(),tmp);

It works perfectly?

my2iu commented 2 years ago

Is the problem with UUID? I don't remember adding any specific code for handling UUID objects, so I'm not sure if that works. Where does the exception occur?

Also, I don't think Jinq can handle JPQL.isIn() with streams passed in from outside the query. I think it can handle Lists of objects passed in from outside the query, but you can't pass in entire streams. If you want to use streams in JPQL.isIn(), you must actually create the stream in the query itself:

proxyStream.where((proxy, source)->{
   var proxies = source.stream(ProxyEntity.class).where(item -> item.getClientId().equals(id))
                            .select(ClientPerProxyEntity::getProxyId);
   return JPQL.isIn(proxy.getId(),proxies);
})

or something like that

OssNass commented 2 years ago

then why it worked in the second example ?

Could be the existence of source is the key?

I think you are right, I will try and tell you of the results

my2iu commented 2 years ago

I have no idea. It's been a while since I wrote the code for that, so maybe it does work. I can't really remember the details without digging through the code. But I don't think it should from what I can remember. Does that code appear inside another query?

Like I said, it might be the UUID issue. Which line does the exception occur from?

OssNass commented 2 years ago

The exception occurs in this line: proxyStream.where(proxy->JPQL.isIn(proxy.getId(),proxies)

my2iu commented 2 years ago

Yeah, then it must be an issue with passing a stream into the query. Jinq's streams are not serializable. The stream has to be created inside the query itself, so that Jinq can analyze it.

my2iu commented 2 years ago

I think you can also just call toList() to convert the stream into a list, and then you can pass the list into the query. But that will execute that subquery separately from the main query, which might be slow depending on what you're doing.

OssNass commented 2 years ago

The problem is, after a certain 2700 items in the list SQL server refuses to perform the match

my2iu commented 2 years ago

Yes, you will then need to run the whole query on the database. So you will have to construct the stream inside the query itself so that Jinq can analyze it and construct a database query from it.

OssNass commented 2 years ago

Yes, you will then need to run the whole query on the database. So you will have to construct the stream inside the query itself so that Jinq can analyze it and construct a database query from it.

Working on it, I have a kind of abstraction layer for allowing me to dynamically construct where condition using Jinq in Spring Boot, I have done the moving from Where to WhereWithSource validating now

OssNass commented 2 years ago

It worked, However, I need now validate every other old Where with the new WhereWithSource, I have a long day ahead of me. Thanks