| Christian C I don't believe that your original model is valid according to the JPA specification. In the JPA specification, the documentation for @PrimaryKeyJoinColumn says, "The PrimaryKeyJoinColumn annotation specifies a primary key column that is used as a foreign key to join to another table." According to JPA, your mapping indicates that the foreign key column is Schedule.id and references ScheduleData.id. That doesn't make sense with Schedule.id being an IDENTITY column, and having ScheduleData#id share the same (generated) primary key value. That would mean that Schedule would need to be inserted first to get the IDENTITY column value, then your application would need to manually assign that value to ScheduleData#id}. I can't see how this could have worked with the foreign key that you added. In any case, Hibernate was assiging the foreign key direction incorrectly in the code you mention:
{if ( value.isReferenceToPrimaryKey() )
{ value.setForeignKeyType( ForeignKeyDirection.TO_PARENT ); }
so I guess that's why your mapping somehow worked. Now that this issue is fixed, I can see why your mapping no longer works. Your solution making the association bidirectional looks OK to me. If you want a solution that is unidirectional, then you should be able to move your IDENTITY mapping to ScheduleData#id, and annotate Schedule#data with @MapsId. That way, the FK column would default to be correct. Also, ScheduleData#id will be inserted first, and, because @MapsId is used instead of @PrimaryKeyJoinColumn, Hibernate will automatically assign Schedule#id to the value generated for ScheduleData#id. There should be no need for your application to manually sync the IDs.
@Entity
public class Schedule {
private int id;
private ScheduleData data = new ScheduleData();
@Id
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@MapsId
@BatchSize(size = 256)
public ScheduleData getData() {
return data;
}
public void setData(ScheduleData data) {
this.data = data;
}
}
@Entity
public class ScheduleData {
private int id;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
I haven't tried this myself, so it's possible what I said above is not absolutely correct. Please let us know if this works for you. |