-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hibernate Reactive's Panache persist methods should return the persisted entity #14475
Comments
/cc @DavideD, @FroMage, @Sanne, @gavinking, @gsmet, @loicmathieu, @yrodiere |
Same for the |
Can you show some code examples that will benefit from this change? |
@DavideD sure, here is one example: private Uni<Extension> createExtension(io.quarkus.dependencies.Extension ext, PlatformRelease platformRelease) {
Supplier<Uni<? extends Extension>> createNewExtension = () -> {
Extension newExtension = new Extension();
newExtension.groupId = ext.getGroupId();
newExtension.artifactId = ext.getArtifactId();
newExtension.name = ext.getName();
newExtension.description = ext.getDescription();
return newExtension.persistAndFlush()
.onItem().transform(x -> newExtension);
};
return Extension.findByGroupIdAndArtifactId(ext.getGroupId(), ext.getArtifactId())
.onItem().ifNull().switchTo(createNewExtension)
.onItem().transformToUni(extension ->
ExtensionRelease.findByExtensionAndVersion(extension, ext.getVersion())
.onItem().ifNull()
.switchTo(() -> {
ExtensionRelease extensionRelease = new ExtensionRelease();
extensionRelease.extension = extension;
extensionRelease.version = ext.getVersion();
extensionRelease.metadata = toJsonNode(ext.getMetadata());
extensionRelease.platforms.add(platformRelease);
return extensionRelease.persistAndFlush()
.onItem().transform(x -> extensionRelease);
})
.onItem()
.transform(extensionRelease -> {
// Add release to extension
extension.releases.add(extensionRelease);
return extension.persistAndFlush();
}).onItem().transform(x -> extension)
);
} AFAIU this enhancement would get rid of the |
Even after staring at that code for 5 minutes I've no idea what you're trying to do there. But I speculate that perhaps this issue can be resolved by trying to clean up your use of the Mutiny APIs, making use of the new operations we added to Mutiny. For example, using I might be wrong. |
Welcome to my world :) This example is a One-to-Many relationship between |
I think in Hibernate Reactive one could convert this type of code:
to something like
or this:
to this:
|
Actually, the doSomethingInTx doesn't make much difference. This is a simpler use case for Hibernate Reactive:
to this:
|
Your third example is a case for (It's one of the last things we requested, remember.) |
For example: Extension extension = new Extension(...)
return session
.withTransaction( tx ->
session
.persist( extension )
.replaceWIth( extension )
); |
I see, thanks. You still need the additional By the way, I don't have strong opinions either way, but I think it helps to write down some examples as part of the issue. |
Also @DavideD:
|
Well I think that's fine personally. I mean, what's actually wrong with: return session.withTransaction( tx -> {
Extension extension = new Extension(...);
return session.persist(extension)
.replaceWith(extension);
} ); This compares perfectly favorably to the equivalent non-reactive code: return session.withTransaction( tx -> {
Extension extension = new Extension(...);
session.persist(extension);
return extension;
} ); |
Just one last point for completeness. |
I suppose that's the way it is. |
This is a RFE for Quarkus's "HR with Panache", so you don't need to change the HR API, this is about the Panache layer. Originally I made I think it's an acceptable enhancement and doesn't cost anything. It's not like |
Excuse me, I should say the proper style is too use |
Well, here's where I document the mapping: For sure it's not quite as nice on the |
Yes, please. |
What about the non-reactive flavor of panache which currently returns Also public Fruit addFruit(@Valid Fruit fruit) {
return fruitRepository.persist(fruit);
} Is much more elegant and simple than public Fruit addFruit(@Valid Fruit fruit) {
fruitRepository.persist(fruit);
return fruit;
} |
@edeandrea agreed, that could be changed too |
@gastaldi would you like me to open a separate issue for it? |
@gastaldi @edeandrea I'm not against it but I'm pretty sure we already discuss this and dismissed it. |
I'm curious to know what @FroMage thinks about it first. I recall seeing some discussions around it as @loicmathieu mentioned |
I don't think he's a fan :) |
Well, I don't think it's very useful for the non-reactive cases, because we don't usually chain the calls, and this example is really trivial and not common in real code. But it wouldn't hurt I guess. |
Is it possible to backport it to 1.13.x? :) |
I'd rather not, this is already a backport to 2.x as it is already branched, and it can potentially break some code due to method generic return type change so we cannot add it in a micro version. |
Fixes quarkusio#14475 (cherry picked from commit 4ebfa20)
@FroMage / @loicmathieu / @gsmet / @gastaldi after updating to Is this by design? Why do they not return This means if I want to showcase the same use case in both the repository & active record patterns, my code now needs to be different. Active record@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Uni<Fruit> addFruit(@Valid Fruit fruit) {
return Panache.withTransaction(() ->
Fruit.persist(fruit)
.replaceWith(fruit)
);
} Repository@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Uni<Fruit> addFruit(@Valid Fruit fruit) {
return Panache.withTransaction(() -> this.fruitRepository.persist(fruit));
} Furthermore, I am not able to properly mock the non-static |
Entity and repository should offers the same API and they do see https://github.com/quarkusio/quarkus/blob/main/extensions/panache/hibernate-reactive-panache/runtime/src/main/java/io/quarkus/hibernate/reactive/panache/PanacheEntityBase.java#L55 and https://github.com/quarkusio/quarkus/blob/main/extensions/panache/hibernate-reactive-panache/runtime/src/main/java/io/quarkus/hibernate/reactive/panache/PanacheRepositoryBase.java#L52 Now the persist method that takes a varargs still returns Uni, we could have return the array of persisted entity but we didn't choose to do so as use cases are less attractive for the various persist variant. The two exemples you show should works with CR3. |
What I'm saying is my examples should look like the following (i.e. I shouldn't have to chain Active record@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Uni<Fruit> addFruit(@Valid Fruit fruit) {
return Panache.withTransaction(() -> Fruit.persist(fruit));
} Repository@POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Uni<Fruit> addFruit(@Valid Fruit fruit) {
return Panache.withTransaction(() -> this.fruitRepository.persist(fruit));
} I can't use the non-static PanacheMock.doReturn(Uni.createFrom().item(new Fruit(1L, "Grapefruit", "Summer fruit")))
.when(Fruit.class).persist(); does not work and the mocking does not happen. |
@edeandrea what you describe as nothing to do with the changes I made, this is a mocking issue, please open an issue with a reproducer but Mockito should be able to mock your method, or PanacheMock, one of the two. |
Mockito can not mock it because the mock is a class, not an instance (i.e. you can't do All I'm trying to say is that the behavior of
|
No |
That reference you made is not to the correct method. That reference would be for
|
OK, you mis-use the API, if you want to persist a single entity you should use the instance method not the static one. As I already said, the static one taken a varags cannot return a So the correct usage should be @POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Uni<Fruit> addFruit(@Valid Fruit fruit) {
return Panache.withTransaction(() -> fruit.persist()));
} |
Ok thanks. Then my ticket (#17697) is blocking me from doing so and forcing me to use |
Description
In the
PanacheEntityBase
from thehibernate-reactive-panache
, it would be nice if thepersist()
andpersistAndFlush()
returned the persisted entity in theUni
object.Implementation ideas
Change the method signature from
Uni<Void>
toUni<T>
The text was updated successfully, but these errors were encountered: