PLEASE HELP I have tried for days now to get this simple nullable relationship to work in hibernate to no avail.
In fact, I spent 3 hours simply preparing this question to be as simple as possible without a bunch of db columns that aren’t relevant to the problem, by commenting out countless lines of code, dropping the db and recreating the db with fewer columns in these tables, removing an update trigger that was on this table, etc. (tested after and still got the same errors.)
The relationship is as follows.
-A company can have a PIA agreement, but is not required to have one.
→ Based on this, I have concluded I need to use ‘many-to-one’ in Company.hbm.xml, because although a company can only have a max of one pia agreement, it seems you can’t “null” the realtionship if you make it one-to-one, so I’m forced to save a company with a pia if I use one-to-one. Even when using “many-to-one” I am facing issues when updating the Company regardless of if a Pia has been set on the object or not.
After exhausting what I could find on the internet myself I have been going back and forth with ChatGPT for almost 10 hours now, and have made 50+ build attempts to try to find something that works, with no luck.
I have a feeling it’s something wrong in either of the two .hbm.xml files for these tables.
Create Company table mysql code:
CREATE TABLE company (
id SMALLINT AUTO_INCREMENT,
name varchar(60) default NULL,
PRIMARY KEY (id)
) Engine=InnoDB;
COMMIT;
Create Pia table mysql code:
CREATE TABLE pia (
company_id smallint,
agreement_number varchar(50),
PRIMARY KEY (company_id),
FOREIGN KEY (company_id) REFERENCES company (id)
) Engine=InnoDB;
COMMIT;
As of right now I have these entries in the two tables (scroll down for image, was only allowed to attach 1 image)
So Company has 1 entry, but Pia has none.
Currently, when I try to update the company with the same info that’s already in there now, this happens (see request body in image, “#1” in red) :
WARN [org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions()] (default task-19) SQL Error: 1048, SQLState: 23000
ERROR [org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions()] (default task-19) (conn=81) Column 'id' cannot be null
ERROR [org.hibernate.internal.ExceptionMapperStandardImpl.mapManagedFlushFailure()] (default task-19) HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement]
(see null pointer exception too, but in a different log)
And when I update the company to now have a PIA agreement, this happens (see request body in image, “#2” in red):
java.lang.NullPointerException
**In both cases, **
it fails on the “template.saveOrUpdate(company);” line below.
I believe I can call saveOrUpdate() to handle more scenarios than just .save() and .update() according to chatgpt, such as if the company already exists but the pia agreement needs to be inserted.
HCompanyDAOImpl.java
@Component
public class HCompanyDAOImpl extends HBaseDAOImpl implements CompanyDAO {
public HCompanyDAOImpl(HibernateTemplate template) {
this.template = template;
}
@Transactional
@Override
public int updateCompany(Company company) {
int result = 0;
try {
template.saveOrUpdate(company);
result = 1;
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
... other methods
}
HBaseDAOImpl.java
public abstract class HBaseDAOImpl {
protected HibernateTemplate template;
}
CompanyRestController.java
@RequestMapping(value = "/updateCompanyData", method = RequestMethod.POST)
public void updateCompanyData(@RequestBody Company company) {
companyDelegate.updateCompanyData(company);
}
CompanyDelegate.java
public void updateCompanyData(Company company) {
Company co = companyDAO.findCompanyByCompanyId(company.getId());
companyDAO.updateCompany(company);
}
Company.hbm.xml
<class name="com.something.something.something.Company" table="COMPANY">
<id name="id" column="ID">
<generator class="increment"/>
</id>
<property name="name" column="NAME"/>
<many-to-one name="pia" class="com.something.something.something.Pia" outer-join="true" not-found="ignore" not-null="false" cascade="save-update">
<column name="id" />
</many-to-one>
</class>
Pia.hbm.xml
<class name="com.something.something.something.Pia" table="PIA">
<id name="companyId" column="company_id">
<generator class="foreign">
<param name="property">company</param>
</generator>
</id>
<property name="agreementNumber" column="AGREEMENT_NUMBER"/>
</class>
Company.java (POJO)
public class Company {
private Integer id;
private String name;
private Pia pia = null;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setPia(Pia pia) { this.pia = pia; }
public Pia getPia() {
return pia;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (o == null || getClass() != o.getClass())
return false;
Company company = (Company) o;
if (id != company.id)
return false;
if (name != null ? !name.equals(company.name) : company.name != null)
return false;
if (pia != null ? !pia.equals(company.pia) : company.pia != null)
return false;
return true;
}
@Override
public int hashCode() {
int result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + (pia != null ? pia.hashCode() : 0);
return result;
}
}
Pia.java (POJO)
public class Pia {
private Integer companyId;
private String agreementNumber;
public Integer getCompanyId() {
return companyId;
}
public void setCompanyId(Integer companyId) {
this.companyId = companyId;
}
public String getAgreementNumber() {
return agreementNumber;
}
public void setAgreementNumber(String agreementNumber) {
this.agreementNumber = agreementNumber;
}
}
Any help or pointers as to what could be possibly going wrong would be greatly appreciated as I am officially out of ideas