The ERD has two inheritance relationships, one is Person extends InvolvedParty, other is PostalAddress extends Location.
Basically, when I was using the restRepo in the Spring data to save the Person object in a testing environment using H2 database.
The entitles as below:
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class InvolvedParty {
private Long partyId;
private String partyTypeCode;
private String preferredLanguageCode;
private String name;
@Id
@GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "party_generator")
@SequenceGenerator(name="party_generator", sequenceName = "Seq_PartyId", allocationSize = 1)
@Column(name = "PartyId", nullable = false)
public Long getPartyId() {
return partyId;
}
@Entity
public class Person extends InvolvedParty {
private String firstName;
private String middleName;
private String lastName;
private LocalDate dateOfBirth;
private LocalDate dateOfDeath;
private String genderCode;
private String nameSuffix;
private String personTitle;
private String residenceProvinceTerritoryCode;
private String maritalStatusCode;
private Long socialInsuranceNumber;
private Integer socialSecurityNumber;
private String taxExemptFlag;
private List<PartyRole> partyRoles;
}
@Entity
public class PartyRole implements Serializable{
private Long partyRoleId;
private String partyRoleTypeCode;
private LocalDate effectiveDate;
private LocalDate endDate;
private String statusCode;
private String statusReasonCode;
private List<PartyRoleLocationRelationship> partyRoleLocationRelationships = new ArrayList<>();
@Id
@GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "party_role_generator")
@SequenceGenerator(name="party_role_generator", sequenceName = "Seq_PartyRoleId", allocationSize = 1)
@Column(name = "PartyRoleId", nullable = false)
public Long getPartyRoleId() {
return partyRoleId;
}
@OneToMany(mappedBy = "partyRole", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference
public List<PartyRoleLocationRelationship> getPartyRoleLocationRelationships() {
return partyRoleLocationRelationships;
}
}
@Entity
public class PostalAddress extends Address {
@OneToMany(mappedBy = "postalAddress", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference
public List<PartyRoleLocationRelationship> getPartyRoleLocationRelationships() {
return partyRoleLocationRelationships;
}
}
@Entity
public class PartyRoleLocationRelationship implements Serializable {
private PartyRole partyRole;
private PostalAddress postalAddress;
private String partyRoleLocationRelationshipTypeCode;
private LocalDate effectiveDate;
private LocalDate endDate;
@Id
@ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinColumn(name = "PartyRoleId", referencedColumnName = "PartyRoleId")
@JsonBackReference
public PartyRole getPartyRole() {
return partyRole;
}
@Id
@ManyToOne(cascade = CascadeType.PERSIST, fetch = FetchType.LAZY)
@JoinColumn(name = "LocationId", referencedColumnName = "LocationId")
@JsonBackReference
public PostalAddress getPostalAddress() {
return postalAddress;
}
@Id
@Column(name = "PartyRoleLocationRelationshipTypeCode", nullable = false, length = 15)
public String getPartyRoleLocationRelationshipTypeCode() {
return partyRoleLocationRelationshipTypeCode;
}
@Id
@Column(name = "EffectiveDate", nullable = false)
public LocalDate getEffectiveDate() {
return effectiveDate;
}
}
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
public class Location {
private Long locationId;
private String locationTypeCode;
private String locationStatusCode;
@Id
@GeneratedValue(strategy= GenerationType.SEQUENCE, generator = "location_generator")
@SequenceGenerator(name="location_generator", sequenceName = "Seq_LocationId", allocationSize = 1)
@Column(name = "LocationId", nullable = false)
public Long getLocationId() {
return locationId;
}
}
@Entity
public class Address extends Location {
private String electronicAddressTypeCode;
private String addressTypeCode;
private String invalidAddressFlag;
}
The calling code:
person = new Person();
person.setLastName("tan");
person.setSocialInsuranceNumber(123456789L);
person.setDateOfBirth(LocalDate.parse("1998-07-26"));
person.setPartyTypeCode(PartyTypeCode.PERSON.toString());
PartyRole partyRole = new PartyRole();
partyRole.setPartyRoleTypeCode("dummy");
partyRole.setEffectiveDate(LocalDate.parse("1998-07-26"));
PostalAddress postalAddress = new PostalAddress();
postalAddress.setPostalCode("123");
postalAddress.setCpValidationFlag("Y");
postalAddress.setMunicipalityName("Montreal");
postalAddress.setProvinceTerritoryCode("QC");
postalAddress.setLocationTypeCode("dummy");
PartyRoleLocationRelationship partyRoleLocationRelationship = new PartyRoleLocationRelationship();
PartyRoleLocationRelationshipPK relId = new PartyRoleLocationRelationshipPK();
relId.setPartyRoleLocationRelationshipTypeCode("d");
relId.setEffectiveDate(LocalDate.of(2018, 3, 6));
relId.setPartyRole(partyRole);
relId.setPostalAddress(postalAddress);
partyRoleLocationRelationship.setEndDate(LocalDate.of(2018, 3, 22));
partyRoleLocationRelationship.setId(relId);
partyRole.getPartyRoleLocationRelationships().add(partyRoleLocationRelationship) ;
postalAddress.getPartyRoleLocationRelationships().add(partyRoleLocationRelationship);
List<PartyRole> partyRoles = new ArrayList<>();
partyRoles.add(partyRole);
person.setPartyRoles(partyRoles);
//create new person in the database
person = personRepository.save(person);
Hibernate threw some errors:
java.lang.NullPointerException at org.hibernate.type.descriptor.java.AbstractTypeDescriptor.extractHashCode(AbstractTypeDescriptor.java:65) at org.hibernate.type.AbstractStandardBasicType.getHashCode(AbstractStandardBasicType.java:187) at org.hibernate.type.AbstractStandardBasicType.getHashCode(AbstractStandardBasicType.java:191) at org.hibernate.type.EntityType.getHashCode(EntityType.java:355) at org.hibernate.type.ComponentType.getHashCode(ComponentType.java:245) at org.hibernate.engine.spi.EntityKey.generateHashCode(EntityKey.java:59) at org.hibernate.engine.spi.EntityKey.(EntityKey.java:54) at org.hibernate.internal.AbstractSessionImpl.generateEntityKey(AbstractSessionImpl.java:338) at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:158) at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:121) at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67) at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189) at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132) at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:765) at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:758) at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:80) at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:398) at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323) at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:162) at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:431) at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:363) at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326) at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:162) at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:111)
I debugged the process, the error was originated from when JPA trying to save PartyRoleLocationRelationship which has embedded Ids, it would need to get the id from PartyRole but would also need get the id from PostalAddress table, since PostalAddress extends Location so the cause was probably PostalAddress could not get the id from its parent Location.
PartyRoleLocationRelationship, PartyRoleId was not null but the LocationId was null that’s why it threw nullpointexception.
There must be some mistakes in my mappings that caused the issue. probably I was not dealing the relations between PartyRoleLocationRelationship, PartyRole, PostalAddress correctly?