views:

116

answers:

1

Hi , I am trying to evaluate a mapping in this Hibernate document : section 2.2.3.1. Generating the identifier property

http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/#entity-mapping-identifier

In the document , Person and MedicalHistory has @OneToOne mapping (MedicalHistory points to Person) , and the document suggests two mapping strategies :

First strategy :

@Entity
class MedicalHistory implements Serializable {
  @Id @OneToOne
  @JoinColumn(name = "person_id")
  Person patient;
}

@Entity
public class Person implements Serializable {
  @Id @GeneratedValue Integer id;
}

Second strategy :

@Entity
class MedicalHistory implements Serializable {
  @Id Integer id;

  @MapsId @OneToOne
  @JoinColumn(name = "patient_id")
  Person patient;
}

@Entity
class Person {
  @Id @GeneratedValue Integer id;
}

Everything works fine now , but...

To make things more complicated , I add another (3rd) table(class) that has a @ManyToOne relationship to MedicalHistory . And the first strategy will fail (while 2nd strategy still works).

I create another (3rd) class , naming MedicalLog , that has a @ManyToOne relationship to MedicalHistory :

@Entity
public class MedicalLog implements Serializable
{
  @Id @GeneratedValue
  private int id;

  @ManyToOne
  @JoinColumn(name="MedicalHistory_id")
  private MedicalHistory medicalHistory;

  private String action;      
  private Timestamp time;

  public MedicalLog(MedicalHistory mh , String action)
  {
    this.medicalHistory = mh;
    this.action = action;
  }
  // other methods
}

The exception occurs when hibernate initializes ... :

Caused by: org.hibernate.AnnotationException: A Foreign key refering destiny.play.MedicalHistory from destiny.play.MedicalLog has the wrong number of column. should be 0
at org.hibernate.cfg.annotations.TableBinder.bindFk(TableBinder.java:421)
at org.hibernate.cfg.ToOneFkSecondPass.doSecondPass(ToOneFkSecondPass.java:111)

Personally , I love strategy 1 more , because it doesn't introduce another Integer id variable. And I feel Object id (strategy 2) is more comfortable (OO style).

Anyway , although strategy 2 works , but I wonder is there any way to make strategy 1 also work ?

Thanks a lot !

-- updated : table creation --

Table creation (MySQL) :

CREATE TABLE IF NOT EXISTS `Person` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `MedicalHistory` (
  `patient_id` int(10) NOT NULL,
  PRIMARY KEY (`patient_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `MedicalLog` (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `MedicalHistory_id` int(10) NOT NULL,
  `action` varchar(15) NOT NULL,
  `time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

Hope it helps

A: 

The exception occurs when hibernate initializes...

What version of Hibernate EntityManager are you using? I couldn't reproduce the issue with 3.5.5-Final and the same annotated object model (firs strategy) on my pet project.

The following tables are created:

create table MedicalHistory (person_id integer not null, primary key (person_id), unique (person_id))    
create table MedicalLog (id integer generated by default as identity, action varchar(255), time timestamp, MedicalHistory_id integer, primary key (id))    
create table Person (id integer generated by default as identity, dept varchar(255), firstName varchar(255), gender varchar(255), lastName varchar(255), primary key (id))    
alter table MedicalHistory add constraint FK306558E319ACB65E foreign key (person_id) references Person    
alter table MedicalLog add constraint FKEDF39713FC40377E foreign key (MedicalHistory_id) references MedicalHistory

And Hibernate initializes without complains.

Pascal Thivent
Hi , I am using hibernate-core-3.5.5-Final , hibernate-annotations-3.5.5-Final , hibernate-entitymanager-3.5.5-Final , hibernate-jpa-2.0-api-1.0.0.Final , hibernate-validator-4.0.0.GA . But I am not using FK constraint , because I am using MySQL's MyISAM , there is no FK-constraint here.
smallufo
@smallufo Not having constraints at the DB level shouldn't be a problem. Or, are you asking Hibernate to validate the model?
Pascal Thivent
Well , it seems the code (with strategy 1) with @ManyToOne MedicalLog cannot be initialized in hibernate , that's the problem. I think it's not related to validation. When testing a simple DAO , hibernate loads these entities and throws the excpetion.
smallufo
@smallufo It can be initialized, and it does on my machine as I wrote. Hence my question about hbm2ddl.auto=validate. I did test to insert or query though.
Pascal Thivent
Sorry I didn't use hbm2ddl or other tools. I build this test app from bottom up . create db , class with annotations , jpa persistence.xml , DAO , and finally Spring .
smallufo