I am relatively new to Quarkus, and much so with Reactive Java/Mutiny, but I am trying to create a related database entity after creating another entity. Example: Saving a User
object, then creating a related UserProfile
object that has a one-to-one relationship with User
.
In other frameworks I would do the following (within a REST API function call):
User
instance, user1
.UserProfile
instance with profile.user_id = user1.id
I've created a UserResource
below. This seems to work fine -- both HTTP response and database contain the expected data, but is there a better way? It seems like this could be done with just one transaction instead?
@ApplicationScoped
@Path("/api/user")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class UserResource {
@Inject
UserRepository userRepository;
@Inject
UserProfileRepository userProfileRepository;
@GET
public Uni<List<UserEntity>> list() {
return userRepository.listAll();
}
@GET
@Path("/{id}")
public Uni<UserEntity> get(Long id) {
return userRepository.findById(id);
}
@POST
@Path("/")
public Uni<Response> create(UserEntity user) {
return Panache
.withTransaction(() -> userRepository.persist(user))
.onItem()
.transformToUni(item -> {
System.out.println(item);
var userProfile = new UserProfileEntity();
userProfile.setUser(item);
userProfile.setDisplayName("My Name");
return Panache.withTransaction(() -> userProfileRepository.persist(userProfile));
})
.invoke(item -> System.out.println(item))
.replaceWith(Response.ok(user).status(Status.CREATED)::build);
}
}
Yes, you shouldn't have to use two transactions.
The solution may change depending on the mapping you are using.
@POST
@Path("/")
public Uni<Response> create(UserEntity user) {
System.out.println(user);
var userProfile = new UserProfileEntity();
userProfile.setUser(user);
// If bidirectional association: user.setUserProfile(userProfile)
userProfile.setDisplayName("My Name");
return Panache
.withTransaction(() -> userRepository
.persist(user)
.call( () -> userProfileRepository.persist(userProfile))
)
.invoke(item -> System.out.println(item))
.replaceWith(Response.ok(user).status(Status.CREATED)::build);
}
@POST
@Path("/")
public Uni<Response> create(UserEntity user) {
System.out.println(user);
var userProfile = new UserProfileEntity();
userProfile.setUser(user);
// If bidirectional association: user.setUserProfile(userProfile)
userProfile.setDisplayName("My Name");
return Panache
.withTransaction(() -> userRepository.persist(user))
.invoke(item -> System.out.println(item))
.replaceWith(Response.ok(user).status(Status.CREATED)::build);
}
@POST
@Path("/")
public Uni<Response> create(UserEntity user) {
System.out.println(user);
var userProfile = new UserProfileEntity();
userProfile.setUser(user);
// If bidirectional association: user.setUserProfile(userProfile)
userProfile.setDisplayName("My Name");
return Panache.withTransaction(user::persist)
.invoke(item -> System.out.println(item))
.replaceWith(Response.ok(user).status(Status.CREATED)::build);
}
Here's the link to the documentation of cascade type PERSIST in Hibernate ORM documentation