· May 20, 2019

Something similar to hibernate/criteria on InterSystems Cache?

Hi everyone,

Im new  in cache, i came from Java and im missing some features that i couldn't find in the documentation,  I hope you can help me with this questions.

Just a brief introducction: 

- Im in a project with old cache version, so saddly i can't use Eclipse + Atelier, so im using Studio.

- Currently im in a project with persistent classes, we want to turn apart the globals and focus on tables. 

The questions:

Is there any way to make something like hibernate for cache %Persistent classes? For example, if i want to get all the records for a table in Java+Hibernate+Criteria i'll do something like this:

myListOfObjects = myPersistentClass.list(); // Equivalent to SELECT *

In cache i have to  create a %SQL.Statement, put the query inside and get the recordSet, iterate it and then get a list of %Persistent objects, for every object i want to use it.

I tried to create some class that inheritance from %Persistent and contains all the methods i want to be used for the rest of persistent objects. With this i only have the data access methods in one place (something similar to the sample Employee who extends from Person, but that creates some weird table called Person that only will contains the ID's and it will have the ID duplicated by every class that extends from it).

Another example, i have some dictonary tables that all of them contains a column called "CODE" i want all of the persistent classes that references a dictionary table own a method to get all the records " WHERE CODE = Xparameter" and this method only returns one result.

myObject = myPersistentClass.getByCode(Xparameter); // Equivalent to SELECT * FROM X WHERE CODE = "Xparameter"

In this example i asked for the most easy questions that came to my mind, i don't only want to achive a "SELECT *" and a "WHERE CODE = ", this question goes far from that. Im looking for a better way to get information from %Persistent classes with good practices.

Is there any accepted way to achive this?

I hope i explained myself correctly.

Discussion (5)2
Log in or sign up to continue

Hi, with regard to your second question, if your property "CODE" is unique and indexed, ie, your class definition includes something like:

Index CodeIndex on CODE [Unique];

 Then there is a generated method you can use to open the object that has CODE=Xparameter:

set myObject = ##class(User.MyPersistentClass).CodeIndexOpen(Xparameter, concurrency, .sc)

For any unique index, the method name is always "[index-name]Open".  You can read more about auto-generated methods here:

With regard to your first question, I'm not aware of any system method that returns a list of all saved objects for a class, but you could implement that by creating a class method that creates and executes the appropriate query, then iterates over the results and copies them to a list.  I would be cautious about doing something like this with large tables though, since you would essentially be loading the entire table into memory.  This could lead to <STORE> errors:

A better solution might be to implement some kind of iterator method that only loads one object at a time.

I don't know of anything similar to Hibernate in Caché. If you want to encapsulate some data access logic inside of a class, it's helpful to define a class query that other objects can access through dynamic SQL.

More specific to your getByCode example, I use the index auto-generated methods a lot. For example in your dictionary table I would create a unique index on Code Index CodeIndex On Code [ Unique ]; and then use ##class(Whatever.Dictionary).CodeIndexOpen() to open the object I want.