hibernate-reactive
hibernate-reactive copied to clipboard
support for Dynamic mapping models
hello, I was wondering if this was something possible to implement in reactive. Currently, the reactive session does not support the .save method for being able to work with a map as seen in the regular hibernate documentation here: https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#mapping-model-dynamic . When I look at the reactive documentation here: https://hibernate.org/reactive/documentation/1.1/reference/html_single/ I don't see any way to do that, and also don't see that method exposed in the reactive session. Thanks!
That's Hibernate ORM 6. Hibernate Reactive is using ORM 5 at the moment
https://docs.jboss.org/hibernate/orm/5.0/userguide/html_single/Hibernate_User_Guide.html#dynamic-model it looks like it was supported here as well under 2.10. Dynamic Model. Maybe i'm missing something
Sorry, my bad. I was just confused for a moment because I'm not familiar with this feature.
You are right, we haven't implemented this.
So I just tried the following:
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class entity-name="Book">
<id name="ISBN" column="isbn" length="32" type="string"/>
<property name="title" not-null="true" length="50" type="string"/>
<property name="author" not-null="true" length="50" type="string"/>
</class>
</hibernate-mapping>
@Test
public void test(TestContext context) {
Map<String, String> book = new HashMap<>();
book.put("ISBN", "9781932394153");
book.put("title", "Hibernate in Action");
book.put("author", "Christian Bauer and Gavin King");
book.put( DynamicMapInstantiator.KEY, "Book" );
test(
context,
getMutinySessionFactory()
.withSession( session -> session.persist( book )
.chain( session::flush )
)
.chain( v -> getMutinySessionFactory()
.withSession( session -> session.createQuery("from Book", Map.class)
.getSingleResult().invoke( map -> System.out.println( map.get("author") ) ) ) )
);
}
This code works!
Unfortunately, we're missing operations which accept a string entity name from the Session API. That means you can't use find(), for example.
I've pushed this test here: https://github.com/hibernate/hibernate-reactive/commit/78dab9a83794b8037f0735e9e4de39f6b9b31256.
So, I guess I'm struggling to know what to do here. I've never been clear on whether we needed to add overloads of all the Session methods that accept string entity names instead of classes.
On the one hand:
Sessionlooks a lot cleaner without them.- With the exception of
find(), you can do most of the work of these extra methods using anEntityNameResolver. - You don't strictly-speaking need find, since you can always use
createQuery("from Entity where id = ?")instead.
On the other hand:
- The ability to map a class multiple times to multiple entity names is, in some sense, a "basic" capability of Hibernate, even if it's a capability that is hardly used.
Session.find()is a pretty popular method!
@ingmarfjolla How much do you want this right now? Would you be just as happy using createQuery() instead of find()?
Sorry, I just realized my previous post is confusing, since I'm free-associating between JPA method naming and legacy Hibernate naming. To be clear, I'm talking about the Session method with this signature in H5:
Object get(String entityName, Serializable id);
But if we added this one, we should probably add all the others like:
void persist(String entityName, Object object);
Object merge(String entityName, Object object);
void delete(String entityName, Object object);
void refresh(String entityName, Object object);
void lock(String entityName, Object object);
and their overloads, which winds up being quite a lot of new methods!
hey @gavinking , so the reason I was asking was because I was trying to rewrite the debezium-quarkus extension to be reactive.
here https://github.com/ingmarfjolla/debeziumreactive/blob/quarkus-outbox-reactive-refactor/debezium-quarkus-outbox/runtime/src/main/java/io/debezium/outbox/quarkus/internal/AbstractEventDispatcher.java in the original implementation they were using the .save method.
In the attempt I was writing with persist : https://github.com/ingmarfjolla/debeziumreactive/blob/quarkus-outbox-reactive-refactor/debezium-quarkus-outbox-reactive/runtime/src/main/java/io/debezium/outbox/quarkus/internal/AbstractEventDispatcher.java my tests fail saying that the query didn't return anything.
Here were the tests: https://github.com/ingmarfjolla/debeziumreactive/blob/quarkus-outbox-reactive-refactor/debezium-quarkus-outbox-reactive/integration-tests/src/test/java/io/debezium/outbox/quarkus/it/AbstractOutboxTest.java
Though seeing your code, i tried adding the DynamicMapInstantiator.KEY, "entityname" and it didn't work, but I think i may be missing more things. I might need to look into EntityNameResolver as an option. Reactive is pretty new to me. Thank you for looking into it and taking the time
Well the code you showed me should be really straightforward to make work in reactive.
FTR I did not have to try very hard to get my test working, 10 mins or something, max, and most of that was just figuring out where I had to put the XML file, since we never tested XML mapping in HR before.
i'm definitely doing something wrong, but I'm not sure what exactly. for some reason when i get to my persist method here
@Inject
Mutiny.SessionFactory sessionFactory;
protected Uni<Void> persist(Map<String, Object> dataMap) {
System.out.println(dataMap);
return sessionFactory.withSession(
session -> session.persist(dataMap)
.chain(session::flush));
}
the persist doesn't seem to get triggered. In my tests i'm succesffuly able to create a query with no issue. perhaps the way i'm creating a session is incorrect?
I mean, are you sure your stream is actually getting better executed? Have you put a break point in the callback?
I mean, try persisting a regular entity that way. From your description, it doesn't sound like the problem is anything to do with the dynamic entity.
so following your example here: https://github.com/hibernate/hibernate-reactive/blob/main/examples/native-sql-example/src/main/java/org/hibernate/reactive/example/nativesql/MutinyMain.java
i got to here: https://github.com/ingmarfjolla/debeziumreactive/blob/quarkus-outbox-reactive-refactor/debezium-quarkus-outbox-reactive/runtime/src/main/java/io/debezium/outbox/quarkus/internal/AbstractEventDispatcher.java and it persists! I have cleaning up to do but I think i'm on the right track
Actually, rethinking this, it's really only find(), persist(), and merge() which would need to have an overloaded version accepting an entity name, so that's not so bad. I guess we could do it.
If you didn't I think just having the DynamicMapInstantiator.KEY somewhere would help, since I hadn't been able to find it before you mentioned it. Did you see any issues with the way I wrote my method? I don't think i'm doing reactive right..