Null foreign key in bi-directional one-to-one mapping

I’m having some trouble with a bi-directional one-to-one mapping, using a sub-class in a table-per-hierarchy structure.

The table structure looks something like this:

EVENT_GROUP
  EVENT_GROUP_ID
  HYDRAULIC_MODEL_ID
  HYDROLOGICAL_ESTIMATE_ID

ANALYSIS
  ANALYSIS_ID 
  ANALYSIS_TYPE (hydraulicModel | hydrologicalEstimate)
  EVENT_GROUP_ID

The foreign key mappings look like so:

HYDRAULIC_MODEL_ID -> ANALYSIS_ID
HYDROLOGICAL_ESTIMATE_ID -> ANALYSIS_ID
ANALYSIS.EVENT_GROUP_ID -> EVENT_GROUP.EVENT_GROUP_ID

The problem is that if I create a new EventGroup and give it a HydraulicModel, then save it, while the EVENT_GROUP row is populated fine, the EVENT_GROUP_ID is missing in the ANALYSIS table.

The classes are as follows:

Analysis.java

@Entity
@org.hibernate.annotations.Entity(dynamicInsert = true)
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Table(name = "ANALYSIS")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "ANALYSIS_TYPE", discriminatorType =  DiscriminatorType.STRING)
public abstract class Analysis implements Serializable {

    private static final long serialVersionUID = 1L;
    @Column(name = "ANALYSIS_TYPE", insertable = false, updatable = false)
    protected String analysisType;

    @Id
    @GeneratedValue(generator = "AnalysisIdGenerator")
    @GenericGenerator(...)
    @Column(name = "ANALYSIS_ID")
    private Integer id;

    ... some other variables ...

    public Analysis() {
        this.analysisType = this.getTypeCode().toString();
    }

    public abstract AnalysisTypeCode getTypeCode();

    public abstract void setEventGroup(EventGroup eventGroup);
    public abstract EventGroup getEventGroup();
}

HydraulicModel.java:

@Entity
@DiscriminatorValue("hydraulicModelling")
public class HydraulicModel extends Analysis implements Serializable {

    @OneToOne(mappedBy = "hydraulicModel")
    @NotNull
    private EventGroup eventGroup;

    public HydraulicModel() {
        this.setAnalysisType("hydraulicModelling");
    }

    public HydraulicModel(EventGroup eventGroup) {
        this.eventGroup = eventGroup;
    }

    @Override
    public AnalysisTypeCode getTypeCode() {
        return AnalysisTypeCode.hydraulicModelling;
    }

    @Override
    public EventGroup getEventGroup() {
        return eventGroup;
    }

    @Override
    public void setEventGroup(EventGroup eventGroup) {
        this.eventGroup = eventGroup;
    }
}

(I haven’t implemented HydrologicalEstimate yet, but it’s essentially the same as HydraulicModel)

EventGroup.java

@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Table(name = "EVENT_GROUP")
public class EventGroup implements Serializable {

... some instance variables ...

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "HYDRAULIC_MODELLING_ID")
private HydraulicModel hydraulicModel;

@Id
@GeneratedValue(generator = "EventGroupIdGenerator")
@GenericGenerator(...)
@Column(name = "EVENT_GROUP_ID")
private Integer id;

public EventGroup() {
    super();
}

public Integer getId() {
    return this.id;
}

public void setId(Integer id) {
    this.id = id;
}

public HydraulicModel getHydraulicModel() {
    return hydraulicModel;
}

public void setHydraulicModel(HydraulicModel hydraulicModel) {
    this.hydraulicModel = hydraulicModel;
}

}

And, finally, the test code which runs the whole thing:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({ "/test_applicationContext.xml" })
@Transactional
public class AnalysisRepositoryTest {

    @Autowired
    public FloodStudyRepository floodStudyRepository;
    @Autowired
    public AnalysisRepository analysisRepository;

    private FloodStudy study;
    private EventGroup eg;

    @Before
    public void setupEventGroup() {
        study = TestUtils.createStudyWithEventGroup(floodStudyRepository);
        eg = study.getEventGroupList().get(0);
    }

    @Test
    @Rollback(false)
    public void createHydraulicModel() {

        HydraulicModel model = new HydraulicModel(eg, "");
        model.setEventGroup(eg);
        analysisRepository.save(model);
    }
}

I get the same behaviour whether I save using the AnalysisRepository as shown, or if I save the whole study using the floodStudyRepository. The database is Oracle 11.


Source: oracle

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.