0

Is there a Java library that will allow me to execute JPQL queries against a basic Java Collection, effectively treating the collection as an in-memory database?

I am currently writing custom code for each query variant, which is error prone and hard to maintain. Due to the need to inter-operate with other code, I can't switch from collections to a true in-memory database like HSQLDB.

There are two workarounds I can think of. Because these collections are transient and processed frequently and in parallel, these workarounds seem like they would add too much overhead (but feel free to convince me otherwise). These are:

  1. Each time I need to run a JPQL query against a collection, stand up a temporary in-memory database, populate it from the collection, and run the query against the database. - The overhead I believe this would introduce isn't justified by the problem I'm trying to solve.
  2. Like #1 but keep the in-memory database around to cut down on overhead. - The transient nature of the collections means this isn't much better than #1 if I keep a database per collection. The parallel nature of these queries would make it non-trivial to reuse the same in-memory database instance across different collection queries.

Edit:

Here is the exact use case:

We are using Drools to perform validation on data as it changes on our server. Our validation rules necessitate a large amount of supporting data be loaded into the knowledge session.

For simplicity, we tried standing up a knowledge session each time it was needed so that we did not need to worry about stale data, however the time performance of this was unacceptable.

We're now switching to a knowledge session that we keep in sync with the database. The knowledge session is initially populated the first time it is accessed. A JPA callback listener records entity additions into a collection, and these entities are incorporated into the knowledge session at the next opportunity if they are applicable.

The wrinkle in this is that the design has to allow for rule changes and additions at a later date on a production system; rule changes may change the data needed for validation so the data loading mechanism has to be equally flexible.

From our first attempt we already have a mechanism in place whereby the rules define, via JPQL statements, what data should be loaded and we execute these JPQL statements to initially populate the knowledge session.

I am now leveraging these same JPQL statements to determine which entities from the JPA callback listener should be added to the knowledge session. To do so, I am writing code to interpret this JPQL and apply the where clause filters to the entities coming from the JPA callback listener. I would prefer to use a third-party library to do this for me.

If you think we should be tackling this completely differently, feel free to suggest a change. The design is convoluted, but unfortunately much of that is driven by customer requirements and can't be avoided.

  • 1
    I would never ever think on using any of those approaches. If you use Java 8, using the stream api will be highly effective and less error prone when creating your *queries*. Still, providing a sample of what you want/need could help us to provide better alternatives to solve this problem. – Luiggi Mendoza May 30 '15 at 16:16
  • I am not sure about the purpose of this. If testing, then go with DBUnit and some in-memory database, it should be fast and efficient enough, without affecting production code. If it's not testing, please explain the use case a little bit more... – Sandor Nemeth May 30 '15 at 16:47
  • Is this the question you meant to ask? http://stackoverflow.com/questions/1217228/what-is-the-java-equivalent-for-linq – MarkOfHall May 30 '15 at 16:54
  • DataNucleus JPA allows such a thing, since it also supports JDO and JDO queries require that as a feature – Neil Stockton May 30 '15 at 17:50
  • @LuiggiMendoza We're stuck on Java 6 unfortunately, but I think the stream API would still leave me with the problem of needing to translate existing JPQL into Java code that applies an equivalent filter. – Psion Omikron May 30 '15 at 21:37
  • @SteveHall My understanding of LINQ is it provides a nice fluid way to define a filter but it won't accept actual SQL and apply it as a filter, so I'm left with the same problem. (Also "There is nothing like LINQ for Java.") – Psion Omikron May 30 '15 at 21:41
  • @NeilStockton That sounds promising, can you point me to some documentation on how to use DataNucleus to apply a JPQL query to a collection? I looked but wasn't able to find it mentioned. – Psion Omikron May 30 '15 at 21:46
  • It seems that the design of your Drools connection would be simpler if you could keep all data of all collections in Drools WM all the time, or pass it all through the Engine for validation, even if there is (currently) no rule making use of the data item. Not enough information in the Q to suggest good approaches, though. – laune May 31 '15 at 05:22

1 Answers1

0

If you wanted to try DataNucleus JPA to do something of this nature, you need to get hold of their internal Query class I think, something like

Query q = em.createQuery(...)
org.datanucleus.store.query.Query dnq = ((org.datanucleus.api.jpa.JPAQuery)q).getInternalQuery();
dnq.setCandidates(myCollectionOfCandidates);
...
List results = q.getResultList();

You may also need

q.setHint("datanucleus.query.evaluateInMemory","true");

I've only ever used it for JDO API with candidate collections, but should work.

Neil Stockton
  • 11,383
  • 3
  • 34
  • 29