@@ -463,31 +463,85 @@ && containsAnnotation( method, HQL, SQL, FIND ) ) {
463463 initialized = true ;
464464 }
465465
466- private void addIdClassIfNeeded (List <? extends Element > fields , List <? extends Element > methods ) {
466+ /**
467+ * Creates a generated id class named {@code Entity_.Id} if the
468+ * entity has multiple {@code @Id} fields, but no {@code @IdClass}
469+ * annotation.
470+ */
471+ private void addIdClassIfNeeded (List <VariableElement > fields , List <ExecutableElement > methods ) {
467472 if ( hasAnnotation ( element , ID_CLASS ) ) {
468- return ;
473+ checkIdMembers ( fields , methods );
474+ }
475+ else {
476+ final List <MetaAttribute > components = getIdMemberNames ( fields , methods );
477+ if ( components .size () >= 2 ) {
478+ putMember ( ID_CLASS_MEMBER_NAME , new IdClassMetaAttribute ( this , components ) );
479+ }
469480 }
481+ }
482+
483+ private List <MetaAttribute > getIdMemberNames (List <VariableElement > fields , List <ExecutableElement > methods ) {
470484 final List <MetaAttribute > components = new ArrayList <>();
471- for ( Element field : fields ) {
485+ for ( var field : fields ) {
472486 if ( hasAnnotation ( field , ID ) && isPersistent ( field , AccessType .FIELD ) ) {
473487 final String propertyName = propertyName ( field );
474488 if ( members .containsKey ( propertyName ) ) {
475489 components .add ( members .get ( propertyName ) );
476490 }
477491 }
478492 }
479- for ( Element method : methods ) {
493+ for ( var method : methods ) {
480494 if ( hasAnnotation ( method , ID ) && isPersistent ( method , AccessType .PROPERTY ) ) {
481495 final String propertyName = propertyName ( method );
482496 if ( members .containsKey ( propertyName ) ) {
483497 components .add ( members .get ( propertyName ) );
484498 }
485499 }
486500 }
487- if ( components .size () < 2 ) {
488- return ;
501+ return components ;
502+ }
503+
504+ private void checkIdMembers (List <VariableElement > fields , List <ExecutableElement > methods ) {
505+ final AnnotationMirror annotationMirror = getAnnotationMirror ( element , ID_CLASS );
506+ if ( annotationMirror != null ) {
507+ final AnnotationValue annotationValue = getAnnotationValue ( annotationMirror );
508+ if ( annotationValue != null && annotationValue .getValue () instanceof DeclaredType declaredType ) {
509+ final TypeElement idClass = (TypeElement ) declaredType .asElement ();
510+ for ( var field : fields ) {
511+ if ( hasAnnotation ( field , ID ) && isPersistent ( field , AccessType .FIELD ) ) {
512+ idClass .getEnclosedElements ().stream ()
513+ .filter ( element -> element .getKind () == ElementKind .FIELD
514+ && element .getSimpleName ().contentEquals ( field .getSimpleName () ) )
515+ .findAny ()
516+ .ifPresentOrElse ( match -> {
517+ if ( !context .getTypeUtils ().isSameType ( field .asType (), match .asType () ) ) {
518+ context .message ( match ,
519+ "id field should be of type '" + field .asType () + "'" ,
520+ Diagnostic .Kind .ERROR );
521+ }
522+ },
523+ () -> context .message ( field ,
524+ "no matching field in id class '" + idClass .getSimpleName () + "'" ,
525+ Diagnostic .Kind .ERROR ) );
526+ }
527+ }
528+ for ( var method : methods ) {
529+ if ( hasAnnotation ( method , ID ) && isPersistent ( method , AccessType .PROPERTY ) ) {
530+ idClass .getEnclosedElements ().stream ()
531+ .filter ( element -> element .getKind () == ElementKind .METHOD
532+ && element .getSimpleName ().contentEquals ( method .getSimpleName () )
533+ && context .getTypeUtils ()
534+ .isSameType ( method .asType (), element .asType () ) )
535+ .findAny ()
536+ .ifPresentOrElse ( match -> {
537+ },
538+ () -> context .message ( method ,
539+ "no matching property in id class '" + idClass .getSimpleName () + "'" ,
540+ Diagnostic .Kind .ERROR ) );
541+ }
542+ }
543+ }
489544 }
490- putMember ( ID_CLASS_MEMBER_NAME , new IdClassMetaAttribute ( this , components ) );
491545 }
492546
493547 private boolean checkEntities (List <ExecutableElement > lifecycleMethods ) {
@@ -1767,7 +1821,7 @@ private List<OrderBy> orderByList(ExecutableElement method, TypeElement returnTy
17671821 final List <OrderBy > result = new ArrayList <>();
17681822 @ SuppressWarnings ("unchecked" )
17691823 final List <AnnotationValue > list = (List <AnnotationValue >)
1770- castNonNull ( getAnnotationValue ( orderByList , "value" ) ).getValue ();
1824+ castNonNull ( getAnnotationValue ( orderByList ) ).getValue ();
17711825 for ( AnnotationValue element : list ) {
17721826 result .add ( orderByExpression ( castNonNull ( (AnnotationMirror ) element .getValue () ), entityType , method ) );
17731827 }
@@ -1782,7 +1836,7 @@ private List<OrderBy> orderByList(ExecutableElement method, TypeElement returnTy
17821836 }
17831837
17841838 private OrderBy orderByExpression (AnnotationMirror orderBy , TypeElement entityType , ExecutableElement method ) {
1785- final String fieldName = castNonNull ( getAnnotationValue (orderBy , "value" ) ).getValue ().toString ();
1839+ final String fieldName = castNonNull ( getAnnotationValue (orderBy ) ).getValue ().toString ();
17861840 if ( fieldName .equals ("<error>" ) ) {
17871841 throw new ProcessLaterException ();
17881842 }
@@ -2138,7 +2192,7 @@ else if ( containsAnnotation( member, NATURAL_ID ) ) {
21382192 else {
21392193 final AnnotationMirror idClass = getAnnotationMirror ( entityType , ID_CLASS );
21402194 if ( idClass != null ) {
2141- final AnnotationValue value = getAnnotationValue ( idClass , "value" );
2195+ final AnnotationValue value = getAnnotationValue ( idClass );
21422196 if ( value != null ) {
21432197 if ( context .getTypeUtils ().isSameType ( param .asType (), (TypeMirror ) value .getValue () ) ) {
21442198 return FieldType .ID ;
@@ -2377,7 +2431,7 @@ private void addQueryMethod(
23772431 containerTypeName = containerType .getQualifiedName ().toString ();
23782432 }
23792433
2380- final AnnotationValue value = getAnnotationValue ( mirror , "value" );
2434+ final AnnotationValue value = getAnnotationValue ( mirror );
23812435 if ( value != null && value .getValue () instanceof String queryString ) {
23822436 addQueryMethod ( method , returnType , containerTypeName , mirror , isNative , value , queryString );
23832437 }
@@ -3026,7 +3080,7 @@ private static String parameterName(VariableElement parameter) {
30263080 final AnnotationMirror param = getAnnotationMirror ( parameter , "jakarta.data.repository.Param" );
30273081 if ( by != null ) {
30283082 final String name =
3029- castNonNull (getAnnotationValue (by , "value" ))
3083+ castNonNull (getAnnotationValue (by ))
30303084 .getValue ().toString ();
30313085 if ( name .contains ("<error>" ) ) {
30323086 throw new ProcessLaterException ();
@@ -3037,7 +3091,7 @@ private static String parameterName(VariableElement parameter) {
30373091 }
30383092 else if ( param != null ) {
30393093 final String name =
3040- castNonNull (getAnnotationValue (param , "value" ))
3094+ castNonNull (getAnnotationValue (param ))
30413095 .getValue ().toString ();
30423096 if ( name .contains ("<error>" ) ) {
30433097 throw new ProcessLaterException ();
0 commit comments