2 Replies Latest reply on Mar 2, 2006 7:14 AM by Martin Heinemann

    ManyToOne to a composite primary key

    Borys Burnayev Newbie

      I've got what I think is a straightforward many-to-one to a composite primary key, which doesn't work as written. Here we go:

      User entity reads like this:
      @Entity
      @Table(name = "CTVUSERS")
      @IdClass(UserPK.class)
      @SequenceGenerator(name = "UserSeq", sequenceName = "SQ_USER")
      public class User {
      @Id
      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "UserSeq")
      @Column(name = "CTVUSERS_KEY")
      private Long userKey;

      @Id
      @Column(name = "CTVUSERS_START_DATE")
      private Date startDate;

      @Id
      @Column(name = "CTVUSERS_END_DATE")
      private Date endDate;
      ...
      }

      The UserPK is defined like this:
      public class UserPK implements Serializable {
      private static final long serialVersionUID = -7720874756224520523L;

      private Long userKey;

      private Date startDate;

      private Date endDate;

      public UserPK() {
      }

      @Override
      public boolean equals(Object obj) {
      if (!(obj instanceof UserPK))
      return false;
      UserPK userPK = (UserPK) obj;
      SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy");
      return userKey.equals(userPK.userKey) && formatter.format(startDate).equals(formatter.format(userPK.startDate))
      && formatter.format(endDate).equals(formatter.format(userPK.endDate));
      }

      @Override
      public int hashCode() {
      return userKey.hashCode() * startDate.hashCode() * endDate.hashCode();
      }
      }


      UserDistrict entity goes as follows:
      @Entity
      @Table(name = "CLRUS2DI")
      @SequenceGenerator(name = "DistrictUserSeq", sequenceName = "SQ_DISTRICT_USER")
      public class DistrictUser {
      @Id
      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "DistrictUserSeq")
      @Column(name = "CLRUS2DI_KEY")
      private Long id;

      @ManyToOne(cascade = CascadeType.ALL)
      @JoinColumns( { @JoinColumn(name = "CLRUS2DI_USERS_KEY", referencedColumnName="CTVUSERS_KEY"),
      @JoinColumn(name = "CLRUS2DI_BEGIN_DATE", referencedColumnName="CTVUSERS_START_DATE"),
      @JoinColumn(name = "CLRUS2DI_END_DATE", referencedColumnName="CTVUSERS_END_DATE") })
      private User user;
      ...
      }

      When I deploy the above I get:
      Caused by: org.hibernate.MappingException: Unable to find column with logical name: CTVUSERS_KEY in org.hibernate.mapping.Table(CTVUSERS) and its related supertables and secondary tables
      at org.hibernate.cfg.Ejb3JoinColumn.checkReferencedColumnsType(Ejb3JoinColumn.java:346)
      at org.hibernate.cfg.BinderHelper.createSyntheticPropertyReference(BinderHelper.java:80)
      at org.hibernate.cfg.FkSecondPass.doSecondPass(FkSecondPass.java:43)
      at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:233)
      at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:997)
      at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:722)
      at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:161)
      at org.hibernate.ejb.Ejb3Configuration.createEntityManagerFactory(Ejb3Configuration.java:567)
      at org.hibernate.ejb.Ejb3Configuration.createContainerEntityManagerFactory(Ejb3Configuration.java:245)
      at org.hibernate.ejb.HibernatePersistence.createContainerEntityManagerFactory(HibernatePersistence.java:108)
      at org.jboss.ejb3.entity.PersistenceUnitDeployment.start(PersistenceUnitDeployment.java:260)


      If I remove the many-to-one from DistrictUsers everything works fine.

      If I remove referenceColumnName's from the many-to-one specification, the code is deployed fine but then I have the following exception in runtime:
      Caused by: java.sql.SQLException: ORA-00904: "USER10_"."ENDDATE": invalid identifier

      at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
      at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331)
      at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288)
      at oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:743)
      at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:216)
      at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:799)
      at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1039)
      at oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:839)
      at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1132)
      at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3285)
      at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3329)
      at org.jboss.resource.adapter.jdbc.WrappedPreparedStatement.executeQuery(WrappedPreparedStatement.java:211)
      at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:139)
      at org.hibernate.loader.Loader.getResultSet(Loader.java:1669)
      at org.hibernate.loader.Loader.doQuery(Loader.java:662)
      at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:224)
      at org.hibernate.loader.Loader.loadEntity(Loader.java:1785)

      which is expected as the column names are different

      Any clues?