Skip to content

Up and coming features for Persism 2.0

Dan Howard edited this page Nov 7, 2021 · 13 revisions

Persism 2.0 is in progress with the main goal to bring it to minimum Java 17. Persism 1.x (currently 1.2) will remain for Java 8 + developers.

Type safe parameters to query and fetch methods.

Currently Persism uses a String for the SQL statements and Object array for parameters. This causes some issues with method overloading. I would like methods that can leave out the SQL or parameters and use nice defaults. With String and Object array some overloads won't work. The issue comes if I have

query(Pojo.class, 1,2,3,4);

Where I don't need the SQL since I can assume that the parameters are primary keys. This would result in a query like this:

SELECT * FROM POJO WHERE 'ID' IN (1,2,3,4)

Which is a nice convenience! The issue comes if the primary keys are strings. In that case Java calls the overload passing the first primary key value as the SQL parameter. :(

In order to properly resolve this I marked the older methods deprecated and created 2 wrapper classes. SQL and Parameters so the new form would be:

import static net.sf.persism.Parameters.params;

import static net.sf.persism.SQL.sql;

...

query(Pojo.class, sql("SELECT column1, column2, column3, etc FROM POJO WHERE ID = ?"), params(1));

It seemed at first to be a bit overkill until I realized I could now more easily add extra features to both new types.

For SQL I added a where() method which looks like this:

query(Pojo.class, where("ID = ?"), params(1));

Because for Tables and Views Persism knows all the columns anyway so you don't have to spell them all out. Nice!

Property names for queries

Then I realized it would be nice if I could just use property names instead of column names in the where() method. This is useful if your column names are different and you don't want to have switch mental contexts to try to remember column names.

Let's say your schema/class looks like this:

CREATE TABLE Contacts(
 ID int NOT NULL PRIMARY KEY,
 [Contact Type] char(2) NOT NULL,
 [First Name] varchar(50) NOT NULL,
 [Last Name] varchar(50) NOT NULL )

// Reduced for brevity 
class Contact {
     int id;
     String contactType;
     String firstName;
     String lastName;
}

Prior versions you'd have to query like this:

query(Contact.class, "SELECT * FROM Contacts WHERE [Contact Type] = ?", "AA");

Now you can write it like this:

query(Contact.class, where(":contactType = ?"), params("AA"));

Note the colon ":" indicates the start of the property name. Persism parses and replaces the property name with the column name for you. Nice!

Named Parameters

Another new feature is the ability to use named parameters. These are useful where you have a complex WHERE clause that repeats values.

var sql = where("(:firstname = @name OR :company = @name) and :amountOwed > @owe ORDER BY :dateAdded");
var contacts = session.query(Contact.class, sql, params(Map.of("name", "Fred", "owe", 10)));

Named parameters use the common convention of using @ to indicate the parameter name. Use the new useful Map.of method to make things even easier!

Currently you can grab a build under the "persism2" branch. I'm still testing it for performance but it should be ready soon!

Let me know what you think!