Avatar of Jack McKenzie
Jack McKenzie
 asked on

How should we annotate Java entities to persist lists and then make lazy loading work?

In Java, I have a requirement to allow user-defined properties.

Example:
Database table: property

Table Row:
ID: 1
Label: Annual Salary

Database table: contact
ID: 1
Email: test@example.com
...

In addition to existing columns for contacts, users will define their own columns in Property Manager. Such column is "Annual Revenue" (number) for example.

So we need a table:
Database table: contact_properties
ID: 1
Contact_id: 1
Property_id 1

In this table we link user-defined properties to contacts

We however need more. We have 4 fixed (immutable) field types: Text, Number, Checkbox, Dropdown.
Every user-defined property should have a type, something like in MS Excel, but easier.

And finally, every user-defined property should belong to some group. Groups are user-defined too.

Database table: property_group

Row:
ID: 1
Label: Contact Information

ID: 2
Label: Company information

...

How should we annotate entities in Java to persist the above? Attached is all source code (mini project). See the entity package in module-properties. I have also prepared something quickly in the App.java (main) to test persistence.

The current exceptoin is:
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: uk.co.mybigdata.crm.module.properties.entity.Property.optionList, could not initialize proxy - no Session
      at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:582) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
      at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:201) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
      at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:561) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
      at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:132) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
      at org.hibernate.collection.internal.PersistentBag.toArray(PersistentBag.java:283) ~[hibernate-core-5.2.17.Final.jar:5.2.17.Final]
      at uk.co.mybigdata.crm.application.App.run(App.java:85) [classes/:na]
      at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:797) [spring-boot-2.0.2.RELEASE.jar:2.0.2.RELEASE]
      ... 5 common frames omitted
elements.zip
JavaDatabases* hibernate* JPA

Avatar of undefined
Last Comment
Jack McKenzie

8/22/2022 - Mon
ASKER CERTIFIED SOLUTION
girionis

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
Jack McKenzie

ASKER
Transactions are managed by the container, as you see in the code, so I have annotated App.java run() with @Transactional and it has helped!

The full answer comes from StackOverflow (the exact same stack trace - Hibernate attempts to lazy load from a bag, uses a temporary session if needed, then throws the exception because the session has been closed = same last 3 stack trace steps).

https://stackoverflow.com/questions/19304671/cannot-fetch-lazy-jpa

The solution is to eager load the collection, or annotate the method @Transactional, or make the session scope broader, possibly with a filter.
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck