Uploaded image for project: 'Spring Roo'
  1. Spring Roo
  2. ROO-2350

GAE - @ManyToOne property never set / inneficient use

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Major
    • Resolution: Complete
    • Affects Version/s: 1.1.3.RELEASE
    • Fix Version/s: 1.1.4.RELEASE
    • Component/s: PERSISTENCE
    • Labels:
      None

      Description

      When having a @ManyToOne field with GOOGLE_APP_ENGINE, Spring ROO generates code that never sets the field and re-fetches it every time it is accessed:

      // Spring Roo 1.1.4.BUILD-SNAPSHOT [rev c6e48eb] log opened at 2011-04-15 18:13:20
      project --topLevelPackage com.test
      persistence setup --provider DATANUCLEUS --database GOOGLE_APP_ENGINE 
      entity --class ~.User --serializable --permitReservedWords 
      field string --fieldName name --notNull 
      json all
      controller scaffold --class ~.web.UserController --entity ~.User
      entity --class ~.UserRole --serializable 
      field string --fieldName name --notNull 
      field reference --fieldName user --type ~.User --cardinality MANY_TO_ONE --permitReservedWords 
      controller scaffold --class ~.web.UserRoleController
      focus --class ~.User
      field set --fieldName roles --type ~.UserRole --cardinality ONE_TO_MANY --mappedBy user 
      quit
      // Spring Roo 1.1.4.BUILD-SNAPSHOT [rev c6e48eb] log closed at 2011-04-15 18:14:49
      

      Generates a UserRole class:

      @RooJavaBean
      @RooToString
      @RooEntity
      @RooSerializable
      public class UserRole {
      
          @NotNull
          private String name;
      
          @ManyToOne
          private User user;
      }
      

      which generates UserRole_Roo_JavaBean.aj that contains the getter and setter for the User class

          public User UserRole.getUser() {
              if (this.userId != null) {
                  this.user = User.findUser(this.userId);
              } else {
                  this.user = null;
              }
              return this.user;
          }
          
          public void UserRole.setUser(User user) {
              if (user != null) {
                  if (user.getId () == null) {
                      user.persist();
                  }
                  this.userId = user.getId();
              } else {
                  this.userId = null;
              }
          } 
      

      HOWEVER, every time role.user is accessed, a query is made. This is very inefficient, especially if you access this property multiple times in a code block.

      Suggestion, take advantage of the field you are marking transient and generate the following instead:

      public User UserRole.getUser() {
          if (this.userId != null) {
              if (this.user == null || this.user.getId() != this.userId) {
                  this.user = User.findUser(this.userId);
              }
          } else {
              this.user = null;
          }
          return this.user;
      }
      
      public void UserRole.setUser(User user) {
          if (user != null) {
              if (user.getId () == null) {
                  user.persist();
              }
              this.userId = user.getId();
          } else {
              this.userId = null;
          }
          this.user = user;
      }
      

      This way the now marked transient field is utilized and subsequent requests don't result in calls to the database.

        Attachments

          Activity

            People

            Assignee:
            stewarta Alan Stewart
            Reporter:
            sdmurphy Scott Murphy
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Dates

              Created:
              Updated:
              Resolved: