Results 1 to 2 of 2

Thread: @CollectionOfElements

  1. #1
    Join Date
    Oct 2007
    Posts
    22

    Default @CollectionOfElements

    Hi, all.

    I'm trying to use Hibernate's @CollectionOfElements to map some name-value string pairs in a Map. It is saving out correctly, but does not read back in correctly. I'd greatly appreciate any insight into if I've done something wrong here or if this looks like a bug. I've tried it both on Oracle & Postgres databases, and it makes no diff.

    The mapped class:

    Code:
    import java.util.HashMap; 
    import java.util.Map; 
    import javax.persistence.Column; 
    import javax.persistence.Entity; 
    import javax.persistence.JoinColumn; 
    import javax.persistence.JoinTable; 
    import javax.persistence.Table; 
    import org.hibernate.annotations.CollectionOfElements; 
    import org.hibernate.annotations.MapKey; 
    .... 
    
    @Entity 
    @Table(name = "job") 
    public class Job { 
      .... 
      @CollectionOfElements() 
      @JoinTable(name = "job_parameters", joinColumns = { @JoinColumn(name = "job_id") }) 
      @MapKey(columns = { @Column(name = "name") }) 
      @Column(name = "value") 
      private Map<String, String> mParameters = new HashMap<String, String>(); 
    
      public Map<String, String> getParameters() { 
        return mParameters; 
      } 
    
      public void setParameters(Map<String, String> parameters) { 
        mParameters = parameters; 
      } 
    }

    The table of interest:

    create table job_parameters(UUID job_id, name varchar(256), value varchar(4000));



    Code that demos the problem:

    Code:
    public class BugTest extends AbstractTransactionalTestNGSpringContextTests { 
      @PersistenceContext 
      protected EntityManager mEntityManager; 
    
      @Test(groups = { "functional" }) 
      public void bugtest() { 
        Job j = new Job(); 
        j.getParameters().put("Test flag", "true"); 
        mJobDao.save(j); 
        mEntityManager.flush(); 
        mEntityManager.refresh(j); 
        System.out.println("NUMBER OF PARAMETERS: " + j.getParameters().keySet().size()); 
      } 
    }

    The problem:
    I've verified that the job parameters are written out correctly (and the log shows this as well), but when the object is refreshed (or just read in in a new session, where I'm really running into this issue), the data comes in from the db (see the log below with the values printed out), but does not actually get set in the Job.mParameters map.

    Log:

    Code:
    ... 
    14:09:02.246 [1] INFO  o.h.c.a.Version: Hibernate Annotations 3.3.1.GA 
    14:09:02.262 [1] INFO  o.h.c.Environment: Hibernate 3.2.6 
    14:09:02.277 [1] INFO  o.h.c.Environment: hibernate.properties not found 
    14:09:02.277 [1] INFO  o.h.c.Environment: Bytecode provider name : cglib 
    14:09:02.277 [1] INFO  o.h.c.Environment: using JDK 1.4 java.sql.Timestamp handling 
    14:09:02.356 [1] INFO  o.h.e.Version: Hibernate EntityManager 3.3.2.GA 
    14:09:02.387 [1] INFO  o.h.e.Ejb3Configuration: Processing PersistenceUnitInfo [ 
       name: DefaultPersistenceUnit 
       ...] 
    ... 
    14:09:05.199 [1] INFO  o.s.t.c.t.TransactionalTestExecutionListener: Began transaction (1): transaction manager [org.springframework.orm.jpa.JpaTransactionManager@174f02c]; rollback [true] 
    14:09:05.262 [1] DEBUG o.h.SQL: insert into job (executor_instance, can_be_rerun, executor_class, insert_tm, priority, queue_tm, start_tm, type_name, weight, id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?) 
    14:09:05.277 [1] TRACE o.h.t.StringType: binding null to parameter: 1 
    14:09:05.277 [1] TRACE o.h.t.BooleanType: binding 'true' to parameter: 2 
    14:09:05.277 [1] TRACE o.h.t.ClassType: binding 'com.foo.job.dbbacked.TestHelper$TestJobExecutor' to parameter: 3 
    14:09:05.277 [1] TRACE o.h.t.TimestampType: binding '2008-08-11 14:09:05' to parameter: 4 
    14:09:05.277 [1] TRACE o.h.t.IntegerType: binding '5' to parameter: 5 
    14:09:05.277 [1] TRACE o.h.t.TimestampType: binding null to parameter: 6 
    14:09:05.277 [1] TRACE o.h.t.TimestampType: binding null to parameter: 7 
    14:09:05.277 [1] TRACE o.h.t.StringType: binding 'com.foo.job.dbbacked.TestHelper$TestJobType' to parameter: 8 
    14:09:05.277 [1] TRACE o.h.t.IntegerType: binding '30' to parameter: 9 
    14:09:05.277 [1] DEBUG o.h.SQL: insert into job_parameters (job_id, name, value) values (?, ?, ?) 
    14:09:05.277 [1] TRACE o.h.t.StringType: binding 'Test flag' to parameter: 2 
    14:09:05.277 [1] TRACE o.h.t.StringType: binding 'true' to parameter: 3 
    14:09:05.293 [1] DEBUG o.h.SQL: select job0_.id as id4_0_, job0_.executor_instance as executor2_4_0_, job0_.can_be_rerun as can3_4_0_, job0_.executor_class as executor4_4_0_, job0_.insert_tm as insert5_4_0_, job0_.priority as priority4_0_, job0_.queue_tm as queue7_4_0_, job0_.start_tm as start8_4_0_, job0_.type_name as type9_4_0_, job0_.weight as weight4_0_ from job job0_ where job0_.id=? 
    14:09:05.309 [1] TRACE o.h.t.StringType: returning null as column: executor2_4_0_ 
    14:09:05.309 [1] TRACE o.h.t.BooleanType: returning 'true' as column: can3_4_0_ 
    14:09:05.309 [1] TRACE o.h.t.ClassType: returning 'com.foo.job.dbbacked.TestHelper$TestJobExecutor' as column: executor4_4_0_ 
    14:09:05.309 [1] TRACE o.h.t.TimestampType: returning '2008-08-11 14:09:05' as column: insert5_4_0_ 
    14:09:05.309 [1] TRACE o.h.t.IntegerType: returning '5' as column: priority4_0_ 
    14:09:05.309 [1] TRACE o.h.t.TimestampType: returning null as column: queue7_4_0_ 
    14:09:05.309 [1] TRACE o.h.t.TimestampType: returning null as column: start8_4_0_ 
    14:09:05.309 [1] TRACE o.h.t.StringType: returning 'com.foo.job.dbbacked.TestHelper$TestJobType' as column: type9_4_0_ 
    14:09:05.309 [1] TRACE o.h.t.IntegerType: returning '30' as column: weight4_0_ 
    14:09:05.324 [1] DEBUG o.h.SQL: select mparameter0_.job_id as job1_0_, mparameter0_.value as value0_, mparameter0_.name as name0_ from job_parameters mparameter0_ where mparameter0_.job_id=? 
    14:09:05.340 [1] TRACE o.h.t.StringType: returning 'true' as column: value0_ 
    14:09:05.340 [1] TRACE o.h.t.StringType: returning 'Test flag' as column: name0_ 
    NUMBER OF PARAMETERS: 0


    You can see from the insert that it does indeed insert the job_parameters table, and you can even see that on the refresh it's returning 'true' and 'Test flag' as it should. However, as you can see from the log, it thinks it has nothing in the Map. I've tried adding the following annotations / modifications one by one and in various combinations on the member variable, and they have no effect on this issue (still written out correctly, apparently read in from the db, but not set in the Map):

    Code:
      @CollectionOfElements(fetch = FetchType.EAGER) 
      @Fetch(FetchMode.JOIN) 
      @BatchSize(size = 60)
    This is with Hibernate Annotations 3.3.1.GA, Hibernate 3.2.6, Hibernate EntityManager 3.3.2.GA, and Spring 2.5.4.

    Can anyone see if I'm doing anything wrong, or have insight as to whether this might be a bug? I apologize that this is not exactly spring-specific (although we are using spring), but after a few days of this question sitting in the hibernate forum w/o a response, I thought I'd try here, since there's a lot of data access experience represented here.

    Thanks much in advance,
    Greg
    Last edited by GregThoen; Aug 22nd, 2008 at 04:39 PM.

  2. #2
    Join Date
    Oct 2007
    Posts
    22

    Default

    *sigh* Never mind. Part of the code I didn't post was the fact that we're using UUID's for the ids of all our objects, which requires our own UserType. I figured out finally that this was our problem by changing our id from a UUID to an int, and noticed that then the test worked fine. Looking at the UserType for UUID's that we wrote here (UUIDType), it appears that the guy who wrote the UserType had this in it:

    Code:
     @Override 
      public boolean equals(Object x, Object y) { 
        return x == y; 
      }
    rather than:

    Code:
      @Override 
      public boolean equals(Object x, Object y) { 
        return x.equals(y); 
      }
    I think he just copied/pasted a UserType implementation he found somewhere on the web (that must have been for a primitive type), and didn't know to change the .equals(). Turns out that this root problem caused a number of apparent hibernate bugs, including this one. Sorry for wasting anyone's time who might've actually read this ...

    Greg

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •