I have a spring boot service which updates comments for a task. I have to 1) create a comment 2)later award points in another table. So I am adding these in @Transactional method
I am getting error while committing the entity. ConstraintViolation Error. Please see code below
Entities
@Entity
@Table(name = "TASK_COMMENTS")
public class TaskCommentEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@SequenceGenerator(name = "TASK_COMMENTS_TASKCOMMENTSID_GENERATOR", sequenceName = "TASK_COMMENTS_ID_SEQ", allocationSize=1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TASK_COMMENTS_TASKCOMMENTSID_GENERATOR")
@Column(name = "TASK_COMMENTS_ID")
private BigDecimal taskCommentsId;
//other columns
// bi-directional many-to-one association to TaskEntity
@ManyToOne
@JoinColumn(name = "TASK_ID", nullable = false)
private TaskEntity task;
}
@Entity
@Table(name = "TASK")
public class TaskEntity implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@SequenceGenerator(name = "TASK_ID_GENERATOR", sequenceName = "TASK_SEQ", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "TASK_ID_GENERATOR")
@Column(name = "TASK_ID")
private BigDecimal taskId;
// bi-directional many-to-one association to TaskCommentEntity
@OneToMany(mappedBy = "task", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@Fetch(value = FetchMode.SUBSELECT) // multiple other one-many associations are present. So subselect is used.
@OrderBy("updateDt DESC")
private List<TaskCommentEntity> taskComments = new ArrayList<>();
}
Controller
@RestController
public class TaskCommentService{
@Autowired//@EJB
TaskCommentBean taskCommentBean;
@PostMapping
public Response saveComment(@RequestBody TaskCommentVO taskCommentVO){
String userId = getUserId() // gets from session
taskCommentBean.processComment(taskCommentVO, userId);
}
}
Bean class
public class TaskCommentBean{
@Autowired
TaskCommentHelper taskCommentHelper;
@Autowired
TaskCommentReviewer taskCommentReviewer;
@PersistanceContext(name = "task.jpa")
EntityManager em;
@Transactional
public void processComment( TaskCommentVO taskCommentVO, String userId)
TaskEntity taskEntity = em.find(Task.class, taskCommentVO.getTaskId());
TaskCommentEntity taskCommentEntity = taskCommentHelper.createComment(taskCommentVO, userId); //Isn't returned entity managed by this time ?
if(taskCommentEntity != null){
Boolean clean = taskCommentReviewer.reviewComment(taskCommentVO.getCommentText());
if(clean){
taskCommentEntity.setCleanStatus("Y")
}
taskCommentEntity.setTask(taskEntity); // setting foreign key Many-to-one variable of managed entity.
// This is NOT getting set.
taskEntity.addTaskComment(taskCommentEntity);
em.merge( taskCommentEntity); // did not help
em.merge( taskEntity); //did not help
// Update other tables
em.persist()
// some times , here I get Connection closed Error. This is another issue.
}
}
TaskCommentHelper
Public class TaskCommentHelper{
@PersistanceContext(name = "task.jpa")
EntityManager em;
public TaskCommentEntity createComment(TaskCommentVO taskCommentVO){
TaskCommentEntity entity = new TaskCommentEntity();
entity.setCommentText(taskcommentVO.getCommentText());
// sets few more fields
em.persist();
return entity;
}
}
On completion of transactional method, I am getting constraint violation error. java.sql.SQLIntegrityConstraintViolationException: ORA-01400: cannot insert NULL into ("TASK_COMMENTS"."TASK_ID") Isn't updating managed entity a valid step. Can't I set it foreign key variable.
This works fine if I pass and set the taskEntity inside the TaskCommentHelper.createComment() method before em.persist();
public TaskCommentEntity createComment(TaskCommentVO taskCommentVO, TaskEntity taskEntity){
TaskCommentEntity entity = new TaskCommentEntity();
entity.setCommentText(taskcommentVO.getCommentText());
// sets few more fields
entity.setTask( taskEntity); // With this change - Works fine.
em.persist(entity);
return entity;
}
Also with this approach, other variable setCleanStatus(Y) is commited even when it is set after em.persist() in the caller method taskCommentBean.processComment();
Please let me know what needs to be corrected. Is it related to SpringBoot Transaction boundaries or something else.