Apply AttributeConverter not before first access

Hi there,

I wonder if there is a way to apply the AttributeConverter for field values only when the fields are read.
The background of my question is that I want to use the AttributeConverter to transparently encrypt and decrypt individual entity fields.
When I retrieve the entities from the database, all fields are always decrypted, regardless of whether I currently need them. This always incurs unnecessary conversion time.

An example is when my repository.findByXAndY(…) returns a large list of entities; the list is already filtered by the unencrypted fields X and Y. If I then stream through the list and apply a filter on the (encrypted in the database) field Z, all other encrypted fields (except for Z) in the filtered-out entities have been unnecessarily decrypted.

My research on this has not yielded much, as it seems the usual use case for the AttributeConverter is more about the straightforward translation from Java objects to database data types.

I can imagine that encryption occurs based on the field values, and decryption only happens when the getter methods are called (which would complicate updating the entity object, as all fields would first need to be ‘loaded’ again).

Are there any experiences out there?

I don’t really understand. Why can’t use you just an AttributeConverter with a trivial implementation of convertToEntityAttribute()?

You might also want to check out @ColumnTransformer.

Thanks gavinking for your reply.
I’ll read into you suggestions and will - if i find my question still not answered - provide some sample code to explain my concern more technically.

Okay, I read a lot stuff regarding @ColumnTransformer and guess I got the misunderstanding.

My question was not about how to convert values, but when.

To make it more clear I created a little example project to show you my point: GitHub - mieseprem/attributeConverter
The example code is written in a way I usually use Hibernate (implicite) with Springboot Data JPA (and please don’t stumble upon the wording ‘encrypt’ but the usage of just base64 encoding - just treat it as an example)

If you run the test method you’ll see the scenario that I was trying to explain in my initial question.

  • get entities by a ‘unencrypted’ attribute
  • filter results by (now unencrypted) attributes
  • see that all attributes of the entities are converted, even if never read

I know that all attributes are read because that’s how the creation of a Java entity object from a database object works. I’m just wondering if, since I’m using Hibernate in a Spring environment, there isn’t a way to initially create the entity objects only as proxies and convert the attributes only when they are accessed.

PS: I’m not a native speaker. Maybe my sentences are therefore not easy to understand. Sorry for that :slight_smile:

If you don’t want to decrypt values when you read them from the database, then change this:

  @Override
  public String convertToEntityAttribute(final String dbData) {
    if (dbData == null) {
      return null;
    }
    var string = new String(decoder.decode(dbData));
    System.out.println("'decrypt' < from '" + dbData + "' to: '" + string + "'");
    return string;
  }

to this:

  @Override
  public String convertToEntityAttribute(final String dbData) {
    return dbData;
  }

I must be missing something.

If you want to defer the decryption step I would recommend the following:

  • Don’t use an attribute converter and just read the encrypted data into your entity
  • Add custom getter methods to your entity classes that do the encryption on the fly
  • Use the custom methods

Okay, this is so obvoious, but I wasn’t able to see it.
It requires a lot of extra coding (to write all the Getter/Setter), but if it speeds the things up… I’ll give it a try :+1: