experimental support for reactive Jakarta Data repositories
this time with uni-fied access to the M.SS Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
parent
d52edeb0e5
commit
c5f9ada2fc
|
@ -0,0 +1,106 @@
|
|||
package org.hibernate.processor.test.data.reactive;
|
||||
|
||||
import io.smallrye.mutiny.Uni;
|
||||
import jakarta.data.Limit;
|
||||
import jakarta.data.Order;
|
||||
import jakarta.data.Sort;
|
||||
import jakarta.data.page.Page;
|
||||
import jakarta.data.page.PageRequest;
|
||||
import jakarta.data.repository.By;
|
||||
import jakarta.data.repository.Delete;
|
||||
import jakarta.data.repository.Find;
|
||||
import jakarta.data.repository.Insert;
|
||||
import jakarta.data.repository.OrderBy;
|
||||
import jakarta.data.repository.Query;
|
||||
import jakarta.data.repository.Repository;
|
||||
import jakarta.data.repository.Save;
|
||||
import jakarta.data.repository.Update;
|
||||
import org.hibernate.reactive.mutiny.Mutiny;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
@Repository
|
||||
public interface Library2 {
|
||||
|
||||
Uni<Mutiny.StatelessSession> session(); //required
|
||||
|
||||
@Find
|
||||
Uni<Book> book(String isbn);
|
||||
|
||||
@Find
|
||||
Uni<List<Book>> books(@By("isbn") List<String> isbns);
|
||||
|
||||
@Find
|
||||
Uni<Book> book(String title, LocalDate publicationDate);
|
||||
|
||||
@Find
|
||||
Uni<List<Book>> publications(Type type, Sort<Book> sort);
|
||||
|
||||
@Find
|
||||
@OrderBy("title")
|
||||
Uni<List<Book>> booksByPublisher(String publisher_name);
|
||||
|
||||
@Query("where title like :titlePattern")
|
||||
@OrderBy("title")
|
||||
Uni<List<Book>> booksByTitle(String titlePattern);
|
||||
|
||||
// not required by Jakarta Data
|
||||
record BookWithAuthor(Book book, Author author) {}
|
||||
@Query("select b, a from Book b join b.authors a order by b.isbn, a.ssn")
|
||||
Uni<List<BookWithAuthor>> booksWithAuthors();
|
||||
|
||||
@Insert
|
||||
Uni<Void> create(Book book);
|
||||
|
||||
@Insert
|
||||
Uni<Void> create(Book[] book);
|
||||
|
||||
@Update
|
||||
Uni<Void> update(Book book);
|
||||
|
||||
@Update
|
||||
Uni<Void> update(Book[] books);
|
||||
|
||||
@Delete
|
||||
Uni<Void> delete(Book book);
|
||||
|
||||
@Delete
|
||||
Uni<Void> delete(Book[] book);
|
||||
|
||||
@Save
|
||||
Uni<Void> upsert(Book book);
|
||||
|
||||
@Find
|
||||
Uni<Author> author(String ssn);
|
||||
|
||||
@Insert
|
||||
Uni<Void> create(Author author);
|
||||
|
||||
@Update
|
||||
Uni<Void> update(Author author);
|
||||
|
||||
@Insert
|
||||
Uni<Publisher[]> insertAll(Publisher[] publishers);
|
||||
|
||||
@Save
|
||||
Uni<Publisher> save(Publisher publisher);
|
||||
|
||||
@Delete
|
||||
Uni<Publisher> delete(Publisher publisher);
|
||||
|
||||
@Find
|
||||
@OrderBy("isbn")
|
||||
Uni<Page<Book>> allBooks(PageRequest<Book> pageRequest);
|
||||
|
||||
@Find
|
||||
@OrderBy("name")
|
||||
@OrderBy("address.city")
|
||||
Uni<List<Author>> allAuthors(Order<Author> order, Limit limit);
|
||||
|
||||
@Find
|
||||
Uni<List<Author>> authorsByCity(@By("address.city") String city);
|
||||
|
||||
@Find
|
||||
Uni<List<Author>> authorsByCityAndPostcode(String address_city, String address_postcode);
|
||||
}
|
|
@ -18,13 +18,14 @@ import static org.hibernate.processor.test.util.TestUtil.getMetaModelSourceAsStr
|
|||
*/
|
||||
public class ReactiveTest extends CompilationTest {
|
||||
@Test
|
||||
@WithClasses({ Publisher.class, Author.class, Address.class, Book.class, Library.class })
|
||||
@WithClasses({ Publisher.class, Author.class, Address.class, Book.class, Library.class, Library2.class })
|
||||
public void test() {
|
||||
System.out.println( getMetaModelSourceAsString( Author.class ) );
|
||||
System.out.println( getMetaModelSourceAsString( Book.class ) );
|
||||
System.out.println( getMetaModelSourceAsString( Author.class, true ) );
|
||||
System.out.println( getMetaModelSourceAsString( Book.class, true ) );
|
||||
System.out.println( getMetaModelSourceAsString( Library.class ) );
|
||||
System.out.println( getMetaModelSourceAsString( Library2.class ) );
|
||||
assertMetamodelClassGeneratedFor( Author.class, true );
|
||||
assertMetamodelClassGeneratedFor( Book.class, true );
|
||||
assertMetamodelClassGeneratedFor( Publisher.class, true );
|
||||
|
@ -32,5 +33,6 @@ public class ReactiveTest extends CompilationTest {
|
|||
assertMetamodelClassGeneratedFor( Book.class );
|
||||
assertMetamodelClassGeneratedFor( Publisher.class );
|
||||
assertMetamodelClassGeneratedFor( Library.class );
|
||||
assertMetamodelClassGeneratedFor( Library2.class );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -181,21 +181,24 @@ public abstract class AbstractQueryMethod implements MetaAttribute {
|
|||
|
||||
boolean isUsingStatelessSession() {
|
||||
return HIB_STATELESS_SESSION.equals(sessionType)
|
||||
|| MUTINY_STATELESS_SESSION.equals(sessionType);
|
||||
|| MUTINY_STATELESS_SESSION.equals(sessionType)
|
||||
|| UNI_MUTINY_STATELESS_SESSION.equals(sessionType);
|
||||
}
|
||||
|
||||
boolean isReactive() {
|
||||
return MUTINY_SESSION.equals(sessionType)
|
||||
|| MUTINY_STATELESS_SESSION.equals(sessionType)
|
||||
|| UNI_MUTINY_SESSION.equals(sessionType);
|
||||
|| UNI_MUTINY_SESSION.equals(sessionType)
|
||||
|| UNI_MUTINY_STATELESS_SESSION.equals(sessionType);
|
||||
}
|
||||
|
||||
boolean isReactiveSession() {
|
||||
return UNI_MUTINY_SESSION.equals(sessionType);
|
||||
return UNI_MUTINY_SESSION.equals(sessionType)
|
||||
|| UNI_MUTINY_STATELESS_SESSION.equals(sessionType);
|
||||
}
|
||||
|
||||
String localSessionName() {
|
||||
return isReactiveSession() ? "resolvedSession" : sessionName;
|
||||
return isReactiveSession() ? "_session" : sessionName;
|
||||
}
|
||||
|
||||
void chainSession(StringBuilder declaration) {
|
||||
|
@ -206,7 +209,7 @@ public abstract class AbstractQueryMethod implements MetaAttribute {
|
|||
.append(sessionName)
|
||||
.append(".chain(")
|
||||
.append(localSessionName())
|
||||
.append(" -> {\n\t");
|
||||
.append(" -> {\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -655,9 +658,14 @@ public abstract class AbstractQueryMethod implements MetaAttribute {
|
|||
break;
|
||||
case JD_PAGE:
|
||||
if ( isReactive() ) {
|
||||
if ( returnTypeName == null ) {
|
||||
throw new AssertionFailure("entity class cannot be null");
|
||||
}
|
||||
declaration
|
||||
.append("\t\t\t.getResultList()\n")
|
||||
.append("\t\t\t.map(_results -> ");
|
||||
.append("\t\t\t.map(_results -> (Page<")
|
||||
.append(annotationMetaEntity.importType(returnTypeName))
|
||||
.append(">)");
|
||||
}
|
||||
else {
|
||||
declaration
|
||||
|
@ -741,8 +749,8 @@ public abstract class AbstractQueryMethod implements MetaAttribute {
|
|||
|
||||
boolean isUnifiableReturnType(@Nullable String containerType) {
|
||||
return containerType == null
|
||||
|| LIST.equals(containerType)
|
||||
|| JD_PAGE.equals(containerType)
|
||||
|| JD_CURSORED_PAGE.equals(containerType);
|
||||
|| LIST.equals(containerType)
|
||||
|| JD_PAGE.equals(containerType)
|
||||
|| JD_CURSORED_PAGE.equals(containerType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1152,7 +1152,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
private void addLifecycleMethod(ExecutableElement method) {
|
||||
final TypeMirror returnType = ununi(method.getReturnType());
|
||||
if ( !HIB_STATELESS_SESSION.equals(sessionType)
|
||||
&& !MUTINY_STATELESS_SESSION.equals(sessionType) ) {
|
||||
&& !MUTINY_STATELESS_SESSION.equals(sessionType)
|
||||
&& !UNI_MUTINY_STATELESS_SESSION.equals(sessionType) ) {
|
||||
context.message( method,
|
||||
"repository must be backed by a 'StatelessSession'",
|
||||
Diagnostic.Kind.ERROR );
|
||||
|
@ -1593,6 +1594,8 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
case HIB_STATELESS_SESSION:
|
||||
case MUTINY_SESSION:
|
||||
case MUTINY_STATELESS_SESSION:
|
||||
// case UNI_MUTINY_SESSION:
|
||||
// case UNI_MUTINY_STATELESS_SESSION:
|
||||
return "session";
|
||||
default:
|
||||
return sessionGetter;
|
||||
|
@ -2622,11 +2625,13 @@ public class AnnotationMetaEntity extends AnnotationMeta {
|
|||
private boolean usingReactiveSession(String sessionType) {
|
||||
return MUTINY_SESSION.equals(sessionType)
|
||||
|| MUTINY_STATELESS_SESSION.equals(sessionType)
|
||||
|| UNI_MUTINY_SESSION.equals(sessionType);
|
||||
|| UNI_MUTINY_SESSION.equals(sessionType)
|
||||
|| UNI_MUTINY_STATELESS_SESSION.equals(sessionType);
|
||||
}
|
||||
|
||||
private boolean usingStatelessSession(String sessionType) {
|
||||
return HIB_STATELESS_SESSION.equals(sessionType)
|
||||
|| MUTINY_STATELESS_SESSION.equals(sessionType);
|
||||
|| MUTINY_STATELESS_SESSION.equals(sessionType)
|
||||
|| UNI_MUTINY_STATELESS_SESSION.equals(sessionType);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import static org.hibernate.processor.util.Constants.MUTINY_SESSION;
|
|||
import static org.hibernate.processor.util.Constants.MUTINY_SESSION_FACTORY;
|
||||
import static org.hibernate.processor.util.Constants.MUTINY_STATELESS_SESSION;
|
||||
import static org.hibernate.processor.util.Constants.UNI_MUTINY_SESSION;
|
||||
import static org.hibernate.processor.util.Constants.UNI_MUTINY_STATELESS_SESSION;
|
||||
|
||||
/**
|
||||
* Used by the container to instantiate a Jakarta Data repository.
|
||||
|
@ -51,8 +52,9 @@ public class DefaultConstructor implements MetaAttribute {
|
|||
|
||||
private boolean isReactive() {
|
||||
return MUTINY_SESSION.equals(sessionTypeName)
|
||||
|| MUTINY_STATELESS_SESSION.equals(sessionTypeName)
|
||||
|| UNI_MUTINY_SESSION.equals(sessionTypeName);
|
||||
|| MUTINY_STATELESS_SESSION.equals(sessionTypeName)
|
||||
|| UNI_MUTINY_SESSION.equals(sessionTypeName)
|
||||
|| UNI_MUTINY_STATELESS_SESSION.equals(sessionTypeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -96,19 +98,24 @@ public class DefaultConstructor implements MetaAttribute {
|
|||
.append("Factory.unwrap(")
|
||||
.append(annotationMetaEntity.importType(isReactive() ? MUTINY_SESSION_FACTORY : HIB_SESSION_FACTORY))
|
||||
.append(".class).openStatelessSession()");
|
||||
if ( isReactive() ) {
|
||||
if ( MUTINY_SESSION.equals(sessionTypeName)
|
||||
|| MUTINY_STATELESS_SESSION.equals(sessionTypeName) ) {
|
||||
// this is crap
|
||||
declaration
|
||||
.append(".await().indefinitely()");
|
||||
}
|
||||
declaration
|
||||
.append(";\n}\n\n");
|
||||
declaration.append('@')
|
||||
.append(annotationMetaEntity.importType("jakarta.annotation.PreDestroy"))
|
||||
.append("\nprivate void closeSession() {")
|
||||
.append("\n\t")
|
||||
.append(sessionVariableName)
|
||||
.append(".close();")
|
||||
.append("\n}\n\n");
|
||||
// TODO: is it a problem that we never close the session?
|
||||
if ( !isReactive() ) {
|
||||
declaration.append('@')
|
||||
.append(annotationMetaEntity.importType("jakarta.annotation.PreDestroy"))
|
||||
.append("\nprivate void closeSession() {")
|
||||
.append("\n\t")
|
||||
.append(sessionVariableName)
|
||||
.append(".close();")
|
||||
.append("\n}\n\n");
|
||||
}
|
||||
}
|
||||
inject( declaration );
|
||||
declaration
|
||||
|
|
|
@ -89,11 +89,23 @@ public class IdFinderMethod extends AbstractFinderMethod {
|
|||
}
|
||||
|
||||
private void findWithNoFetchProfiles(StringBuilder declaration) {
|
||||
if ( isReactiveSession() ) {
|
||||
declaration
|
||||
.append(".chain(")
|
||||
.append(localSessionName())
|
||||
.append(" -> ")
|
||||
.append(localSessionName());
|
||||
}
|
||||
declaration
|
||||
.append(isUsingStatelessSession() ? ".get(" : ".find(")
|
||||
.append(annotationMetaEntity.importType(entity))
|
||||
.append(".class, ")
|
||||
.append(paramName)
|
||||
.append(paramName);
|
||||
if ( isReactiveSession() ) {
|
||||
declaration
|
||||
.append(')');
|
||||
}
|
||||
declaration
|
||||
.append(");\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import static org.hibernate.processor.util.Constants.MUTINY_SESSION;
|
|||
import static org.hibernate.processor.util.Constants.MUTINY_STATELESS_SESSION;
|
||||
import static org.hibernate.processor.util.Constants.UNI;
|
||||
import static org.hibernate.processor.util.Constants.UNI_MUTINY_SESSION;
|
||||
import static org.hibernate.processor.util.Constants.UNI_MUTINY_STATELESS_SESSION;
|
||||
|
||||
public class LifecycleMethod implements MetaAttribute {
|
||||
private final AnnotationMetaEntity annotationMetaEntity;
|
||||
|
@ -110,7 +111,22 @@ public class LifecycleMethod implements MetaAttribute {
|
|||
}
|
||||
|
||||
private void delegateCall(StringBuilder declaration) {
|
||||
if ( isReactive() ) {
|
||||
if ( isReactiveSession() ) {
|
||||
declaration
|
||||
.append("\t\treturn ")
|
||||
.append(sessionName)
|
||||
.append(".chain(")
|
||||
.append(localSessionName())
|
||||
.append(" -> ")
|
||||
.append(localSessionName())
|
||||
.append('.')
|
||||
.append(operationName)
|
||||
.append('(')
|
||||
.append(parameterName)
|
||||
.append(')')
|
||||
.append(')');
|
||||
}
|
||||
else if ( isReactive() ) {
|
||||
declaration
|
||||
.append("\t\treturn ")
|
||||
.append(sessionName)
|
||||
|
@ -229,6 +245,16 @@ public class LifecycleMethod implements MetaAttribute {
|
|||
private boolean isReactive() {
|
||||
return MUTINY_SESSION.equals(sessionType)
|
||||
|| MUTINY_STATELESS_SESSION.equals(sessionType)
|
||||
|| UNI_MUTINY_SESSION.equals(sessionType);
|
||||
|| UNI_MUTINY_SESSION.equals(sessionType)
|
||||
|| UNI_MUTINY_STATELESS_SESSION.equals(sessionType);
|
||||
}
|
||||
|
||||
boolean isReactiveSession() {
|
||||
return UNI_MUTINY_SESSION.equals(sessionType)
|
||||
|| UNI_MUTINY_STATELESS_SESSION.equals(sessionType);
|
||||
}
|
||||
|
||||
String localSessionName() {
|
||||
return isReactiveSession() ? '_' + sessionName : sessionName;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,7 +106,8 @@ public final class Constants {
|
|||
public static final String TUPLE = "jakarta.persistence.Tuple";
|
||||
|
||||
public static final String UNI = "io.smallrye.mutiny.Uni";
|
||||
public static final String UNI_MUTINY_SESSION = UNI+"<org.hibernate.reactive.mutiny.Mutiny.Session>";
|
||||
public static final String UNI_MUTINY_SESSION = UNI + "<" + MUTINY_SESSION + ">";
|
||||
public static final String UNI_MUTINY_STATELESS_SESSION = UNI + "<" + MUTINY_STATELESS_SESSION + ">";
|
||||
public static final String UNI_INTEGER = UNI+"<java.lang.Integer>";
|
||||
public static final String UNI_VOID = UNI+"<java.lang.Void>";
|
||||
public static final String UNI_BOOLEAN = UNI+"<java.lang.Boolean>";
|
||||
|
|
Loading…
Reference in New Issue