0 Replies Latest reply on Aug 16, 2004 2:09 PM by komone

    Maintaining uniqueness of non-pk field

    komone


      Hi,

      I am using JBoss 3.2.x + CMP 2.x. I'm using synthetic primary keys, but I have other fields that must be allowed to be updated, but must remain unique.

      To take the simplest case I can think of, suppose we have a "name" field which must be allowed to be updated, but just not to a name that's already in use:

      public abstract class NamedEntity implements EntityBean {
       /**
       * @ejb.interface-method
       * @ejb.persistence
       * @ejb.pk-field
       */
       public abstract String getId();
      
       /**
       * NOT an interface method.
       */
       public abstract void setId(String id);
      
       /**
       * @ejb.interface-method
       * @ejb.persistence
       */
       public abstract String getName();
      
       /**
       * @ejb.interface-method
       */
       public abstract void setName(String name);
      
       /**
       * @ejb.create-method
       */
       public String ejbCreate(String name) throws CreateException {
       setId(NamedUtil.generateGUID(this));
       setName(name);
       return null;
       }
      
       // and so on....
      }


      Of course, the obvious solution to this code snippet is to ditch the id field, and make the "name" field the primary key; But this is the exact piece of bad practice (i.e. using business values as PKs) that I'm trying to avoid.

      Finally, my real question. What's the best way of managing such unique non-pk fields? Should I have do all my checking in the Session or SessionFacade beans? Is there an accepted pattern for maintaining uniqueness that I'm missing?

      (It would be nice if there was the concept of "candidate keys" in EJB... and come to that the idea of "domains" too, both of which exist in RDBMS theory but never, sadly, made it into SQL... however, this is another discussion entirely!).

      Right now, it seems to me that it must be done at the controller level... as I can't see a way to enforce this uniqueness at entity level. In the entity bean, I could enforce the restriction in the ejbCreate method by using the entity context to get the entity's home, and then calling the appropriate finder method; But even then I cannot enforce uniqueness for updates i.e. at setName, since that method is, by necessity, abstract in CMP.

      The inevitable outcome seems to be the following...

      public abstract class NamedControllerStatelessBean implements SessionBean {
       protected NamedLocalHome home = null;
      
       // ...get the entity home etc...
      
       public void addName(String name) throws MyApplicationException {
       try {
       if (name != null && name.trim() != "") {
       Collection c = this.home.findByName(name.trim());
       if (c.size() == 0) {
       this.home.create(name);
       }
       }
       } catch (FinderException e) {
       throw new MyApplicationException(e);
       } catch (CreateException e) {
       throw new MyApplicationException(e);
       }
       }
      
       // ...obviously, the update name method does similar stuff....
       public void updateName(String guid, String name) throws MyApplicationException {
       // ...
       }
      }

      This solution seems slightly clunky to me. I still feel that I should be able to enforce this uniqueness at entity level.

      Any comments appreciated.

      /k1