How do I do lazy initialization of a value in a JPA Entity?

Viewed 111

As per the title, is there a way to be able to define a val in a JPA entity to be lazily evaluated - exclusively for memoization purpose?

I mean, I have a JPA entity defined like this:

@Entity(name = "users")
data class User(
        val username: String,
        //lotsa fields...
) {

        fun aFunctionThatWillBeCalledOften (dn: DeliveryNote): Boolean {
                return if (someCondition)
                        true
                else
                        memoizedWannaBeValue
        }


        @delegate:Transient
        private val memoizedWannaBeValue by lazy {
                //do a huge computation here
                result
        }

}

It will compile fine, however, when I try to run tests based on that, access to memoized value will fail with a nasty explosion:

java.util.concurrent.CompletionException: java.lang.NullPointerException: Cannot invoke "kotlin.Lazy.getValue()" because "<local2>" is null
    at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:314)
    at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:319)
    at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:645)
    at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506)
    at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2143)

Now, if I switch to a fun call it works fine, so I guess I'm doing something wrong, but I cannot understand exactly what...

1 Answers

you may make use of PostLoad annotation

@Entity
data class Foo(
   val input: String,
) {
  var output: String? = null,
  
  @PostLoad
  fun postLoad() {
     output = "${input} bar" 
  }
}
Related