1 2 Previous Next 23 Replies Latest reply on Jul 27, 2006 5:50 PM by wcydaip

    Enum attributes in Entity Beans ...

    epbernard

      I've documented that enum are supported as a basic type (chapter 2.2.2.1. in Hibernate annotations reference doc)

        • 1. Re: Enum attributes in Entity Beans ...

          I've tried it out, but i have some problems with it.

          Configuration:

          JBoss 4.0.2
          EJB 3 Beta
          Windows XP
          JDK 1.5.0.2

          I've got the following entity bean:

          @Entity
          @Table(name = "class")
          public class JClass implements java.io.Serializable {
          
           private static final long serialVersionUID = 1L;
          
           private Long key;
           private Long version;
          
           public void setKey(Long key) {
           this.key = key;
           }
          
           @Id(generate=GeneratorType.AUTO)
           @Column(name="id")
           public Long getKey() {
           return this.key;
           }
          
           @Version
           @Column(name="version")
           public Long getVersion() {
           return version;
           }
          
           public void setVersion(Long version) {
           this.version = version;
           }
          
           public void setScope(Scope scope) {
           this.scope = scope;
           }
          
           @Column(name="scope")
           public Scope getScope() {
           return scope;
           }
          
          }
          


          where Scope is an enum :

          
          import java.io.Serializable;
          
          public enum Scope implements Serializable {
          
           PUBLIC,
           PROTECTED,
           PRIVATE;
          
          }
          
          


          My persistence.xml contains the following:

          <entity-manager>
           <name>JavaLibraryEntityManager</name>
           <provider>org.hibernate.ejb.HibernatePersistence</provider>
           <jta-data-source>java:/JavaLibraryds</jta-data-source>
          
           <properties>
           <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect"/>
           <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
           <property name="hibernate.hbm2ddl.auto" value="create"/>
           </properties>
          </entity-manager>
          


          When i deploy the software it creates the class table for me.
          According to chapter 2.2.2.1 the database column can be a string type or an int type (storing the ordinal).

          In this case JBoss creates a int(11) column for me.

          But when i try to persist an object i get the following error:

          SQL Type not supported for Enums: 1

          What can i do about it?
          If it is a bug i would like to know so that i can create a jira issue.

          • 2. Re: Enum attributes in Entity Beans ...
            epbernard

            Hum, weird because SQL Type 1 is CHAR (not INT)
            Are you sure you point to the appropriate DB?

            Open a case anyway in the Hibernate JIRA (HibernateExt/annotations), I'll install MySql somewhere to check that. Be sure to give me the driver version too.

            My implem is not fully robust yet, but for other reasons.

            • 3. Re: Enum attributes in Entity Beans ...

              i've created JIRA Issue:

              http://jira.jboss.org/jira/browse/EJBTHREE-206

              The version number of MySQL Connector/j is:

              mysql-connector-java-3.1.10-bin.jar

              • 4. Re: Enum attributes in Entity Beans ...
                dsouza

                Hi,

                I'm having a similar problem with Oracle. I don't know if it's the exact same cause.
                I have an entity bean much like the example above with an enum, also just like it. Jboss creates the table for me and sets the enum's colum as NUMBER(10) when I deploy it.
                When I try to insert a row, Oracle doesn't say anything except for:

                17:38:27,468 WARN [JDBCExceptionReporter] SQL Error: 17023, SQLState: null
                17:38:27,468 ERROR [JDBCExceptionReporter] Unsupported feature
                17:38:27,484 ERROR [AbstractFlushingEventListener] Could not synchronize database state with session

                I can see that the issue created for it has been corrected for the next hibernate beta, but I also read something about it being specifically a MySQL issue. I was wondering what else has been discovered about it and if the fix would also make it work for Oracle.

                Thanks
                Denis Souza

                • 5. Re: Enum attributes in Entity Beans ...

                  dsouza,

                  The bug has been resolved (not yet solved), so i would expect that a sollution is provided within the next week.

                  I've done the following work arround so that i can still use Enums:

                  I've added a constructor to te enum wich can contain a int value :

                  public enum Scope implements Serializable {
                  
                   PUBLIC(0),
                   PROTECTED(1),
                   PRIVATE(2);
                  
                   private int type = 0;
                  
                   private Scope(int type) {
                   this.type = type;
                   }
                  
                   public int getType() {
                   return type;
                   }
                  
                  }
                  


                  And i made the following changes to the entity:

                  I've made the get/set method with the enum @Transient so that it is not stored in the database. Then i created a new set of get/set methods:

                  public class MyEntity implements java.io.Serializable {
                  
                   private Scope scope = Scope.PUBLIC;
                  
                   ...
                  
                   public void setScopeType(int scopeType) {
                   for (Scope scope : Scope.values()) {
                   if (scope.getType() == scopeType) {
                   this.scope = scope;
                   return;
                   }
                   }
                  
                   throw new IllegalArgumentException("ScopeType is not valid.");
                   }
                  
                   @Column(name="scope", nullable=false)
                   public int getScopeType() {
                   return scope.getType();
                   }
                  }
                  


                  So in my code i still use the enums but for storage i use the type value of the enum. If this bug is solved i only have to remove the added get/set method and remove the @Transient annotation.

                  • 6. Re: Enum attributes in Entity Beans ...
                    dsouza

                    Thanks, that's a really good workaround. The one I was using wasn't nearly as elegant.

                    • 7. Re: Enum attributes in Entity Beans ...
                      epbernard

                      FYI, I solved the issue for MySQL, it was a driver limitation. It may also work for Oracle.
                      If someone can test the Hibernate Annotations in CVS on Oracle it would be cool.

                      • 8. Re: Enum attributes in Entity Beans ...
                        dsouza

                        I checked out CVS and tested it with Oracle. This is what I get now:

                        18:39:06,328 ERROR [AbstractFlushingEventListener] Could not synchronize database state with session
                        org.hibernate.HibernateException: Unable to persist an Enum in a column of SQL Type: 3
                         at org.hibernate.type.EnumType.isOrdinal(EnumType.java:191)
                         at org.hibernate.type.EnumType.nullSafeSet(EnumType.java:117)
                         at org.hibernate.type.CustomType.nullSafeSet(CustomType.java:143)
                         at org.hibernate.persister.entity.BasicEntityPersister.dehydrate(BasicEntityPersister.java:1646)
                         at org.hibernate.persister.entity.BasicEntityPersister.dehydrate(BasicEntityPersister.java:1623)
                        


                        In the database, a column of type NUMBER(10) is created.
                        Is there something else that must be done for it to work? My code looks exactly like the sample ronaldmathies sent (except for the class and method names, of course).


                        • 9. Re: Enum attributes in Entity Beans ...
                          epbernard

                          Arggg, stupid oracle driver.
                          OK, this should now pass on Oracle DB, please test.
                          (be careful readonly CVS is not sync with rw until some time (24h max)

                          • 10. Re: Enum attributes in Entity Beans ...
                            dsouza

                            Ok, I tested it again for Oracle and it did work, however I did run into some other problems.

                            I have a cactus test suite that inserts/updates/deletes entities in the database to make sure they're working and that they have the appropriate permissions. So in order to test the use of enums in an entity I used one of my entity tests (for an entity that needs an enum).

                            Basically I have this line of code in my test suite:

                            interfaceMessage.setMessageType(InterfaceMessageType.WARNING);
                            

                            where InterfaceMessageType is my enum. If I change the line to
                            interfaceMessage.setMessageType(InterfaceMessageType.ERROR);
                            

                            and redeploy without restarting JBOSS, I get the following exception:

                            org.hibernate.PropertyAccessException: exception setting property value with CGLIB (set hibernate.cglib.use_reflection_optimizer=false for more info) setter of entity.iface.InterfaceMessage.setMessageType
                             at org.hibernate.tuple.PojoEntityTuplizer.setPropertyValuesWithOptimizer(PojoEntityTuplizer.java:209)
                             at org.hibernate.tuple.PojoEntityTuplizer.setPropertyValues(PojoEntityTuplizer.java:179)
                             at org.hibernate.persister.entity.BasicEntityPersister.setPropertyValues(BasicEntityPersister.java:2981)
                            ...
                            Caused by: net.sf.cglib.beans.BulkBeanException: entity.enums.InterfaceMessageType
                             at entity.iface.InterfaceMessage$$BulkBeanByCGLIB$$48beb320.setPropertyValues(<generated>)
                             at org.hibernate.tuple.PojoEntityTuplizer.setPropertyValuesWithOptimizer(PojoEntityTuplizer.java:206)
                             ... 84 more
                            Caused by: java.lang.ClassCastException: entity.enums.InterfaceMessageType
                             ... 86 more
                            


                            If I restart JBOSS everything works fine (until I change the code again). I really have no idea why this is happening but I thought maybe something from mixing the latest hibernate cvs with the ejb 3 beta release, but then again I guess it's unlikely since hibernate handles the persistence. Any ideas of what might be causing this?

                            Another problem is that the latest cvs broke some of my other code. Maybe it's something that's really changed for good and I'm not up to date yet, but I'm getting the following exception:

                            org.jboss.tm.JBossRollbackException: Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=brain/24, BranchQual=, localId=24] status=STATUS_NO_TRANSACTION; - nested throwable: (java.lang.ClassCastException: java.util.ArrayList)
                            
                            java.lang.RuntimeException: org.jboss.tm.JBossRollbackException: Unable to commit, tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=brain/24, BranchQual=, localId=24] status=STATUS_NO_TRANSACTION; - nested throwable: (java.lang.ClassCastException: java.util.ArrayList)
                            at org.jboss.aspects.tx.TxPolicy.handleEndTransactionException(TxPolicy.java:185)
                            at org.jboss.aspects.tx.TxPolicy.endTransaction(TxPolicy.java:167)
                            at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:74)
                            ...
                            


                            Looks like some problem in using ArrayList in OneToMany or ManyToMany relationships. Just thought you should know in case it's a new bug or something.

                            • 11. Re: Enum attributes in Entity Beans ...

                              It seems that the problem still excists for Oracle. Maybe you can re-open the JIRA issue (keep in mind that this should be done in the the hibernate JIRA and not in the JBoss JIRA) (or make a follow up on it). And specify your'e environment (especialy the ojdbc driver version and oracle version).

                              • 12. Re: Enum attributes in Entity Beans ...
                                epbernard

                                No there are completely unrelated problems.

                                • 13. Re: Enum attributes in Entity Beans ...
                                  ryoung2504

                                  How do you use the enum fields in a named query?

                                  The following syntax doesn't work:

                                  @NamedQuery(name = "DeliveryLocation_findByOwningCustomerId", queryString = "SELECT record FROM Location AS record where record.locationType = LocationType.DELIVERY record.owningCustomer.id = :owningCustomerId")


                                  where LocationType is an enum

                                  • 14. Re: Enum attributes in Entity Beans ...
                                    epbernard

                                    .setParameter("enum", enum.ordinal() ); if the DB stores it in a numeric column
                                    .setParameter("enum", enum.name() ); otherwise

                                    1 2 Previous Next