1

TLDR: Switched Hibernate Versions from 3. to 5.. Now, OneToOne Relationship with shared primary key that is only mapped in one class persists the two entities in the wrong order, violating a foreign key constraint. How to change the order?

In the process of migrating from a jboss 7 instance to a current wildfly, my team also had to update our hibernate version from 3 to 5.3.10.

While doing that, I encountered a problem with one of our entity constructs in which I have hit a brick wall.

The general concept is the following:

I have a main entity class that has multiple "modules" as attritubes which share the primary key of the main entity class. These modules are entity classes themselves and hold various logic and further relationships. However, the module entities don't have any other persistent attributes. They hold no reference to the main entity class either.

In that regard, it is (in the object oriented world of java) a unidirectional relationship with a shared primary key (I understand the shared primary key makes it bidirectional for the database).

The Java Code would be something like this:

@Entity(name = "mainEntity")
@Table(name = "main_entity")
public class MainEntity {
// Business Logic ...


@Id
  private Long id;

  @OneToOne( targetEntity = ModuleA.class, cascade = CascadeType.ALL, optional = false,
      orphanRemoval = true )
  @PrimaryKeyJoinColumn( name = "id", referencedColumnName = "id" )
private ModuleA moduleA;
// More Modules...

}

@Entity(name=moduleA)
@Table(name=module_a)
public class ModuleA {
  @Id
  private Long id;
  // other relationships to entirely different entities,
  // but no reference to mainEntity or other "modules"
}

In our previous system, this worked just fine. When using something like

entityManager.persist(mainEntity);

The modules would get persisted first, and afterwards the mainEntity.

However, with our updated hibernate version, this is not what happens. Using this mapping, the insertion order is reversed and the entityManager will try to persist the mainEntity first. This results in a violation of a foreign key constraint that should prevent inconsistencies between the tables.

On a side note: I tried changing

@PrimaryKeyJoinColumn(...)

into

@MapsId(value="id")

This actually changed the persitence order around correctly. However, doing this, caused hibernate to no longer properly understand the shared primary key -> While persisting worked for some reason,

entityManager.find(ModuleA.class,primaryKey);

did not work, yielding errors like "column mainEntity.moduleA_id does not exist."

Is there a way you can think of to express the need to persist the modules first, as Hibernate 3 did for us?

I'll greatly appreciate any help.

PS: This is my first question, if there's more information required, or if there's a problem with the formulation, do tell, please. :)

hpr
  • 36
  • 4

1 Answers1

0

Alright, after some Analysis I wanted to share what we have done about this.

Firstly, the mapping provided in the question works for Hibernate 3.6.10.Final up until Hibernate 5.2.13.Final where it starts to fail. Oddly, starting with 5.4.0.CR1 it starts working again.

We have not found a way to continue using this mapping with the constraint in place. In our case, we have decided the constraint was just not worth the hassle, but to map this kind of thing more reliably, we have found that working with @MapsId was more successful. There, the modules would need a reference to the MainEntity and would use @MapsId on that to derive its id.

hpr
  • 36
  • 4