I am working with a domain model class which is composed of an embedded object which implements the DomainEvent interface. DomainEvent can be any concrete class and is serialized by Jackson. To solve this in hibernate 5 I have used a CompositeUserType over two columns: event_body, and type_name.
{code:java}public class StoredEvent {
private DomainEvent event; private long eventId; private Instant occurredOn; private String typeName; }{code}
In Hibernate 5 the hbm.xml mapping was very simple and straightforward:
{code:xml}<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping default-access="field" default-cascade="all"> <class name="event.StoredEvent" table="stored_event" lazy="true"> <id name="eventId" type="long" column="event_id" unsaved-value="-1"> <generator class="identity" /> </id> <property name="event" type="port.adapter.persistence.hibernate.DomainEventUserType"> <column name="event_body"/> <column name="type_name"/> </property> <property name="typeName" column="type_name" insert="false" update="false"/> <property name="occurredOn" column="occurred_on"/> </class> </hibernate-mapping>{code}
The DomainEventUserType was also more or less simple to write:
Testing does work well, and I have provided a reproduced using the test-case-templates on my github: [https://github.com/itsmoonrack/hibernate-test-case-templates|https://github.com/itsmoonrack/hibernate-test-case-templates|smart-link]
In Hibernate 6.0 I did not successfully migrated this composite user type and in fact I tried multiple strategies (implementing the new CompositeUserType) but failed successfully.
I tried the following:
{code:xml}<component name="event" class="port.adapter.persistence.hibernate.DomainEventUserType"> <!-- I was expecting mapping would have been done on the "projection embeddable" --> <property name="eventBody" column="event_body"/> <property name="typeName" column="type_name"/> </component>{code}
but the metamodel mapper is telling me that it “*Could not locate field name [eventBody] on class [domain.model.DomainEvent]*”
I also tried to embbed a component
{code:java}public class StoredEventThatMayWork {
private ComponentMapped event; private long eventId; private Instant occurredOn;
public StoredEventThatMayWork(final DomainEvent event) { this.event = new ComponentMapped(event, event.getClass().getName()); this.occurredOn = event.occurredOn(); }
public static class ComponentMapped {
private DomainEvent eventBody; private String typeName;
public ComponentMapped(final DomainEvent event, final String typeName) { this.eventBody = event; this.typeName = typeName; } } }{code}
but it did not worked either: *Could not determine recommended JdbcType for* {{domain.model.DomainEvent}}
Either there is something I did not understood, either this functionality has been broken starting from 6.0, and I am currently blocked by this. Any way of having this fonctionality working for 6.0 ? I have provided three tests classes:
* hibernate-orm-5/ORMUnitTestCase which does work as expected * hibernate-orm-6/ORMUnitTestCase which yield *Could not locate field name [eventBody] on class [domain.model.DomainEvent]* * hibernate-orm-6/ORMUnitTestCaseThatMayWork with the component approach but yields *Could not determine recommended JdbcType for* {{domain.model.DomainEvent}}
see reproduced test case here: [https://github.com/itsmoonrack/hibernate-test-case-templates/tree/main/orm|https://github.com/itsmoonrack/hibernate-test-case-templates/tree/main/orm|smart-link]
Any help would be greatly appreciated, if its not a bug, then it might be a documentation bug to provide a migration path. I would be happy to write such a documentation if missing. |
|