简体   繁体   中英

POST REST API with One-To-Many Mapping : Cannot be null error

I have two tables: tbl_services & tbl_sub_services . one service can have multiple sub-services. I am developing REST API using spring boot and trying to post data in services & subservices table. I can post data in services table but getting issue while posting in sub-services table. It's one-to-Many bidirectional Mapping.

Here is an exception which I am getting in postman.

{
"timestamp": "2019-06-09T04:10:22.002+0000",
"status": 500,
"error": "Internal Server Error",
"message": "could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement",
"trace": "org.springframework.dao.DataIntegrityViolationException: could not execute statement; SQL [n/a]; constraint [null]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement\n\tat 
.
.
.
.
'tbl_services_id' cannot be null\n\tat com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:117)\n\tat com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)\n\tat com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:955)\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1094)\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1042)\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1345)\n\tat com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1027)\n\tat com.zaxxer.hikari.pool.ProxyPreparedStatement.executeUpdate(ProxyPreparedStatement.java:61)\n\tat com.zaxxer.hikari.pool.HikariProxyPreparedStatement.executeUpdate(HikariProxyPreparedStatement.java)\n\tat org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:175)\n\t... 94 more\n",
"path": "/api/subservices"

Here is structure of both tables :

在此处输入图片说明

Entity Classes :
Services.class

@Entity
@Table(name="tbl_services")
public class Service {

// define fields
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="tbl_services_id")
private int id;

@Column(name="service_name")
private String serviceName;

@Column(name="service_desc")
private String serviceDesc;

@Column(name="service_image")
private String serviceImage;

@OneToMany(mappedBy="service",
        cascade= {CascadeType.PERSIST, CascadeType.MERGE,
            CascadeType.DETACH, CascadeType.REFRESH})
private List<SubService> subServices;

public List<SubService> getSubServices() {
    return subServices;
}

public void setSubServices(List<SubService> subServices) {
    this.subServices = subServices;
}
}

SubService.class

@Entity
@Table(name="tbl_sub_services")
public class SubService {

// define fields
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="tbl_sub_services_id")
private int id;

@ManyToOne(
        cascade= {CascadeType.PERSIST, CascadeType.MERGE,
                CascadeType.DETACH, CascadeType.REFRESH})
@JoinColumn(name="tbl_services_id")
@JsonIgnore
private Service service;

public Service getService() {
    return service;
}

@Column(name="sub_service_name")
private String subServiceName;

@Column(name="sub_service_desc")
private String subServiceDesc;

@Column(name="sub_service_image")
private String subServiceImage;

I am trying to post data from postman then I am getting an exception. Here is data which I am posting from postman.

在此处输入图片说明

Here is SubServicesHibernateDAOImpl.class

@Override
public void saveSubService(SubService theSubService) {
    // get the current hibernate session
    Session currentSession = entityManager.unwrap(Session.class);
    System.out.println("SubService object : "+theSubService);       
    currentSession.saveOrUpdate(theSubService);
}  

EDIT : Here is json payload I am receiving in saveSubService method :

[id=0, service=null, subServiceName=GST, subServiceDesc=GST is a subservice which currently having , subServiceImage=path-to-image]

You get:

could not execute statement; SQL [n/a]; constraint [null]

I see that you are passing the service in the request but I do not see you load it before the save of SubService :

@Override
public void saveSubService(SubService theSubService) {
    Session currentSession = entityManager.unwrap(Session.class);
    Service loadedService = currentSession.load(Service.class
           , theSubService.getService.getId();

    theSubService.setService(loadedService);         

    currentSession.saveOrUpdate(theSubService);
}

or try to simply merge as you have proper cascading already in place:

@Override
public void saveSubService(SubService theSubService) {
    // get the current hibernate session
    Session currentSession = entityManager.unwrap(Session.class);
    System.out.println("SubService object : "+theSubService);       
    currentSession.merge(theSubService);
}

Also, I am not sure why you need to unwrap the session. EntityManager and its interface would be sufficient in this case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM