Spring Roo
  1. Spring Roo
  2. ROO-384

Roo should support selection of user-supplied JPA @GenerationType value

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Minor Minor
    • Resolution: Won't Fix
    • Affects Version/s: None
    • Fix Version/s: None
    • Component/s: PERSISTENCE
    • Labels:
      None
    • Environment:
      all

      Description

      When using an identifier of type String our tests will not start up using DBUnit (using hibernate provider).. those tables that have an identifier of String are not loaded by Hibernate for DBUnit; most likely will happen beyond testing but didn't get that far.

      I have done a nasty wee hack that will check for a couple of new RooEntity annotation attributes that allow one to set the strategy and the generator (we also have another requirement to have our own generator).

      Added to RooEntity:

          String generatedValueGenerator() default "";
          String generatedValueStrategy() default "";
      
      Add to EntityMetadata to getIdentifierField - this is NOT so tidy :-):
      
              // Compute the column name, as required
              if ("NULL".equalsIgnoreCase(this.generatedValueStrategy))
              {
              }
              else if ("IDENTITY".equalsIgnoreCase(this.generatedValueStrategy))
              {
                  List<AnnotationAttributeValue<?>> generatedValueAttributes = new ArrayList<AnnotationAttributeValue<?>>();
                  generatedValueAttributes.add(new EnumAttributeValue(new JavaSymbolName("strategy"), new EnumDetails(new JavaType("javax.persistence.GenerationType"), new JavaSymbolName("IDENTITY"))));
                  AnnotationMetadata generatedValueAnnotation = new DefaultAnnotationMetadata(new JavaType("javax.persistence.GeneratedValue"), generatedValueAttributes);
                  annotations.add(generatedValueAnnotation);
              }
              else
              {
                  List<AnnotationAttributeValue<?>> generatedValueAttributes = new ArrayList<AnnotationAttributeValue<?>>();
      
                  // add a generator to javax.persistence.GeneratedValue
                  if(!"".equals(this.generatedValueGenerator))
                  {
                      generatedValueAttributes.add(new StringAttributeValue(new JavaSymbolName("generator"), this.generatedValueGenerator));
      
      //                generatedValueAttributes.add(new EnumAttributeValue(new JavaSymbolName("generator"), new EnumDetails(new JavaType("javax.persistence.GenerationType"), new JavaSymbolName("AUTO"))));
      
                      List<AnnotationAttributeValue<?>> genericGeneratorAttributes = new ArrayList<AnnotationAttributeValue<?>>();
      //                genericGeneratorAttributes.add(new EnumAttributeValue(new JavaSymbolName("strategy"), new EnumDetails(new JavaType("javax.persistence.GenerationType"), new JavaSymbolName("AUTO"))));
                      genericGeneratorAttributes.add(new StringAttributeValue(new JavaSymbolName("strategy"), this.generatedValueGenerator));
                      genericGeneratorAttributes.add(new StringAttributeValue(new JavaSymbolName("name"), this.generatedValueGenerator));
      //                @GenericGenerator(name = "IdGenerator", strategy = "IdGenerator")
                              
                      AnnotationMetadata genericGeneratorAttributesAnnotation = new DefaultAnnotationMetadata(new JavaType("org.hibernate.annotations.GenericGenerator"), genericGeneratorAttributes);
                      annotations.add(genericGeneratorAttributesAnnotation);      
                  }
                  else
                  {
                      generatedValueAttributes.add(new EnumAttributeValue(new JavaSymbolName("strategy"), new EnumDetails(new JavaType("javax.persistence.GenerationType"), new JavaSymbolName("AUTO"))));
                  }
      

        Issue Links

          Activity

          Hide
          Kermie de Frog added a comment -

          Should be linked to Roo-383

          Show
          Kermie de Frog added a comment - Should be linked to Roo-383
          Hide
          Ben Alex added a comment -

          Would you mind expanding on what you're trying to do here?

          I am unsure why we'd need Roo to support the indication of a GenerationType given AUTO is such a reasonable default. It is not Roo's vision to provide configuration options for every aspect of the JPA spec. For more advanced requirements we generally recommend people consider adding the identifier to their own entity and then providing the requisite accessor/mutator pair. That way it is possible to provide any JPA annotation at all. I also believe you can use an ITD to introduce a new annotation on a member provided by an ITD, so that's an even cleaner approach.

          One key issue is we ensure Roo base add-ons only use JPA standardized features. We do not wish the base add-ons to lock users into a particular persistence technology such as Hibernate, and the code fragment above would cause a Hibernate-specific annotation to be used. Is it possible to achieve your desired improvement without needing to use a specific JPA implementation's features?

          Show
          Ben Alex added a comment - Would you mind expanding on what you're trying to do here? I am unsure why we'd need Roo to support the indication of a GenerationType given AUTO is such a reasonable default. It is not Roo's vision to provide configuration options for every aspect of the JPA spec. For more advanced requirements we generally recommend people consider adding the identifier to their own entity and then providing the requisite accessor/mutator pair. That way it is possible to provide any JPA annotation at all. I also believe you can use an ITD to introduce a new annotation on a member provided by an ITD, so that's an even cleaner approach. One key issue is we ensure Roo base add-ons only use JPA standardized features. We do not wish the base add-ons to lock users into a particular persistence technology such as Hibernate, and the code fragment above would cause a Hibernate-specific annotation to be used. Is it possible to achieve your desired improvement without needing to use a specific JPA implementation's features?
          Hide
          Kermie de Frog added a comment -

          sorry, i guess there are two parts to this:

          1) GenerationType: I guess that we were trying to use as much of the Roo generated stuff as possible and use it with the existing code base we have - the less we deviate from a nice simple Roo approach the more it will benefit the project long term. In other words we don't wish to put into the entity stuff we can have auto generated for us)..

          For us we have a historic data that contains Strings for ID values (only for part of the domain).. Strings cant be associated with AUTO, so the default doesnt work for this case.. all other identifiers are fine as Auto is a good default.. Seeing as Roo supports Strings as an identifier type then it should default to not having AUTO as its generated type. However, there are times when it should also NOT be Auto as the non-string identifier may have to create values based on other set of rules.. hope I am being clear there..

          2) Generator: Yes you are right, you cant, nor should you, be expected to support within Roo addon Hibernate stuff... so please ignore me in this case this is just something we hacked in for our own purpose.. we were just testing to see how we could use Roo to replicate a quite complicated, inherited, discriminator based entity with its own generator class... to do this we hacked roo a bit... so please ignore this part.

          Show
          Kermie de Frog added a comment - sorry, i guess there are two parts to this: 1) GenerationType: I guess that we were trying to use as much of the Roo generated stuff as possible and use it with the existing code base we have - the less we deviate from a nice simple Roo approach the more it will benefit the project long term. In other words we don't wish to put into the entity stuff we can have auto generated for us).. For us we have a historic data that contains Strings for ID values (only for part of the domain).. Strings cant be associated with AUTO, so the default doesnt work for this case.. all other identifiers are fine as Auto is a good default.. Seeing as Roo supports Strings as an identifier type then it should default to not having AUTO as its generated type. However, there are times when it should also NOT be Auto as the non-string identifier may have to create values based on other set of rules.. hope I am being clear there.. 2) Generator: Yes you are right, you cant, nor should you, be expected to support within Roo addon Hibernate stuff... so please ignore me in this case this is just something we hacked in for our own purpose.. we were just testing to see how we could use Roo to replicate a quite complicated, inherited, discriminator based entity with its own generator class... to do this we hacked roo a bit... so please ignore this part.
          Hide
          Ben Alex added a comment -

          This is a relatively unusual use case in that you would essentially like to annotate a field introduced by one of Roo's ITDs. It seems a complicated approach to Roo-specific support for doing this. One nice approach you might like to consider is something along these lines, which allows you to write your own ITD that assigns your desired annotation to a member that is introduced by another ITD (thanks to Andy Clement for this code fragment):

          import java.lang.annotation.Retention;
          import java.lang.annotation.RetentionPolicy;
          
          @Retention(RetentionPolicy.RUNTIME)
          @interface Anno {}
          
          public aspect Demo {
              int Target.id;
          }
          class Target {
              int id2;
          }
          
          aspect Annotater {
              declare @field: * Target.*: @Anno; // annotate both id and id2
          }
          

          If you could try this out and confirm it works, it would be good as I think we can close this issue in that case.

          Show
          Ben Alex added a comment - This is a relatively unusual use case in that you would essentially like to annotate a field introduced by one of Roo's ITDs. It seems a complicated approach to Roo-specific support for doing this. One nice approach you might like to consider is something along these lines, which allows you to write your own ITD that assigns your desired annotation to a member that is introduced by another ITD (thanks to Andy Clement for this code fragment): import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) @ interface Anno {} public aspect Demo { int Target.id; } class Target { int id2; } aspect Annotater { declare @field: * Target.*: @Anno; // annotate both id and id2 } If you could try this out and confirm it works, it would be good as I think we can close this issue in that case.
          Hide
          Alan Stewart added a comment -

          Haven't heard back for a year, so closing for now

          Show
          Alan Stewart added a comment - Haven't heard back for a year, so closing for now
          Hide
          Mitchell Elutovich added a comment -

          I added the follow to ROO-1040 which seems from the comments was going to use this, never received a response. Trying again.

          Alan,
          Since ROO-384 has been closed after your comment in Sep 10 are you assuming that the work around there will also work here to a) remove the "@GeneratedValue(strategy = GenerationType.AUTO)" and/or b) to add the @PrePersist.

          Also I'm as of yet unclear how one orders ITDs onto ITDs; perhaps you or Andy or someone else knows how to enforce that Annotator will add Anno onto "id". (That Annotator is applied after Demo.) And how this is done when there is an ITD to an ITD to an ITD.

          Show
          Mitchell Elutovich added a comment - I added the follow to ROO-1040 which seems from the comments was going to use this, never received a response. Trying again. Alan, Since ROO-384 has been closed after your comment in Sep 10 are you assuming that the work around there will also work here to a) remove the "@GeneratedValue(strategy = GenerationType.AUTO)" and/or b) to add the @PrePersist. Also I'm as of yet unclear how one orders ITDs onto ITDs; perhaps you or Andy or someone else knows how to enforce that Annotator will add Anno onto "id". (That Annotator is applied after Demo.) And how this is done when there is an ITD to an ITD to an ITD.

            People

            • Assignee:
              Alan Stewart
              Reporter:
              Kermie de Frog
            • Votes:
              1 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: