Merge branch 'update_ignores_soft_delete' of github.com:Ichtil/ebean into Ichtil-update_ignores_soft_delete

This commit is contained in:
Rob Bygrave
2022-07-27 21:22:16 +12:00
6 changed files with 170 additions and 31 deletions
@@ -1,13 +1,16 @@
package org.tests.o2m;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.ebean.DB;
import io.ebean.test.LoggedSql;
import io.ebean.xtest.BaseTestCase;
import org.junit.jupiter.api.Test;
import org.tests.o2m.dm.GoodsEntity;
import org.tests.o2m.dm.PersonEntity;
import org.tests.o2m.dm.WorkflowEntity;
import org.tests.o2m.dm.WorkflowOperationEntity;
import java.io.StringWriter;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@@ -161,4 +164,75 @@ class TestOneToManyStatelessUpdateResultsInSoftDelete extends BaseTestCase {
assertThat(ops).hasSize(1);
assertThat(goodsStateless.getWorkflowEntity().getOperations().get(0).getId()).isNotEqualTo(operation1.getId());
}
@Test
void softDeleteIncludedInQuery() throws Exception {
var defaultPerson = new PersonEntity();
defaultPerson.setName("test");
DB.save(defaultPerson);
// create GoodsEntity with 1 WorkflowOperationEntity
var goods = new GoodsEntity();
goods.setCreatedBy(defaultPerson);
goods.setName("ver1");
var workflow = new WorkflowEntity();
workflow.setRevision("ver1");
var operation1 = new WorkflowOperationEntity();
operation1.setName("ver1");
goods.setWorkflowEntity(workflow);
workflow.setOperations(List.of(operation1));
DB.save(goods);
// statelessly delete WorkflowOperationEntity
var goodsStateless = new GoodsEntity();
goodsStateless.setId(goods.getId());
var workflowStateless = new WorkflowEntity();
workflowStateless.setId(workflow.getId());
goodsStateless.setWorkflowEntity(workflowStateless);
workflowStateless.setOperations(List.of());
LoggedSql.start();
DB.update(goodsStateless);
// uncommenting this lines makes the test pass
//assertThat(goodsStateless.getWorkflowEntity().getOperations().size()).isEqualTo(0);
var sql = LoggedSql.stop();
sql.forEach(System.out::println);
System.out.println("BEFORE TRY");
LoggedSql.start();
try (var writer = new StringWriter()) {
var mapper = new ObjectMapper();
mapper.writeValue(writer, goodsStateless);
sql = LoggedSql.stop();
sql.forEach(System.out::println);
/*
select t0.id, t0.name, t0.workflow_entity_id, t0.version, t0.when_created, t0.when_modified from goods_entity t0 where t0.id = ?; --bind(4, ) --micros(161)
select t0.id, t0.name, t0.version, t0.when_created, t0.when_modified, t0.created_by, t0.updated_by, t0.workflow_entity_id from goods_entity t0 where t0.id = ?; --bind(4, ) --micros(525)
select t0.id, t0.name, t0.version, t0.when_created, t0.when_modified from person_entity t0 where t0.id = ?; --bind(1, ) --micros(325)
! is this even issue? - select does not check if workflow_entity is deleted
select t0.id, t0.revision, t0.version, t0.when_created, t0.when_modified from workflow_entity t0 where t0.id = ?; --bind(1, ) --micros(439)
select t0.id, t0.revision, t0.version, t0.when_created, t0.when_modified, t0.created_by, t0.updated_by from workflow_entity t0 where t0.id = ?; --bind(1, ) --micros(332)
select t0.id, t0.name, t0.version, t0.when_created, t0.when_modified from person_entity t0 where t0.id = ?; --bind(1, ) --micros(197)
select t0.workflow_id, t0.id, t0.position, t0.name, t0.workflow_id, t0.version, t0.when_created, t0.when_modified, t0.deleted from workflow_operation_entity t0 where (t0.workflow_id) in (?) order by t0.workflow_id, t0.position; --bind(Array[1]={1}) --micros(2776)
select t0.id, t0.position, t0.name, t0.version, t0.when_created, t0.when_modified, t0.deleted, t0.workflow_id, t0.created_by, t0.updated_by from workflow_operation_entity t0 where t0.id = ?; --bind(1, ) --micros(415)
!! ignores soft delete
also to note - when the DM extends BaseDomain instead of HistoryColumns, this bug does not happen
(presumably since @WhoCreated Person createdBy is lazy loaded, when it is eagerly loaded, this bug does not occur)
select t0.workflow_id, t0.id, t0.position, t0.name, t0.workflow_id, t0.version, t0.when_created, t0.when_modified, t0.deleted from workflow_operation_entity t0 where (t0.workflow_id) in (?) order by t0.workflow_id, t0.position; --bind(Array[1]={4}) --micros(585)
select t0.id, t0.position, t0.name, t0.version, t0.when_created, t0.when_modified, t0.deleted, t0.created_by, t0.updated_by, t0.workflow_id from workflow_operation_entity t0 where t0.id = ?; --bind(7, ) --micros(532)
*/
writer.flush();
var serialized = writer.toString();
System.out.println(serialized);
var readGoods = mapper.readValue(writer.toString(), GoodsEntity.class);
assertThat(readGoods.getWorkflowEntity().getOperations()).hasSize(0);
}
}
}
@@ -2,13 +2,10 @@ package org.tests.o2m.dm;
import org.tests.model.draftable.BaseDomain;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.*;
@Entity
public class GoodsEntity extends BaseDomain {
public class GoodsEntity extends HistoryColumns {
private String name;
@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
@@ -0,0 +1,39 @@
package org.tests.o2m.dm;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.ebean.annotation.WhenCreated;
import io.ebean.annotation.WhenModified;
import io.ebean.annotation.WhoCreated;
import io.ebean.annotation.WhoModified;
import org.tests.model.draftable.BaseDomain;
import javax.persistence.*;
import java.time.LocalDateTime;
@MappedSuperclass
public class HistoryColumns extends BaseDomain {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "created_by")
private PersonEntity createdBy;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "updated_by")
private PersonEntity updatedBy;
public PersonEntity getCreatedBy() {
return createdBy;
}
public void setCreatedBy(PersonEntity createdBy) {
this.createdBy = createdBy;
}
public PersonEntity getUpdatedBy() {
return updatedBy;
}
public void setUpdatedBy(PersonEntity updatedBy) {
this.updatedBy = updatedBy;
}
}
@@ -0,0 +1,26 @@
package org.tests.o2m.dm;
import org.tests.model.draftable.BaseDomain;
import javax.persistence.Entity;
@Entity
public class PersonEntity extends BaseDomain {
public PersonEntity() {
}
public PersonEntity(Long id) {
this.setId(id);
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@@ -1,6 +1,9 @@
package org.tests.o2m.dm;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.ebean.annotation.SoftDelete;
import io.ebean.annotation.Where;
import io.ebean.annotation.WhoCreated;
import org.tests.model.draftable.BaseDomain;
import javax.persistence.*;
@@ -8,31 +11,15 @@ import java.util.ArrayList;
import java.util.List;
@Entity
public class WorkflowEntity extends BaseDomain {
private String revision;
public class WorkflowEntity extends HistoryColumns {
private String revision;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "workflow_id")
private List<WorkflowOperationEntity> operations = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "workflow_id")
private List<WorkflowOperationEntity> operations = new ArrayList<>();
@SoftDelete
private boolean deleted;
public String getRevision() {
return revision;
}
public void setRevision(String revision) {
this.revision = revision;
}
public List<WorkflowOperationEntity> getOperations() {
return operations;
}
public void setOperations(List<WorkflowOperationEntity> operations) {
this.operations = operations;
}
@SoftDelete
private boolean deleted;
public boolean isDeleted() {
return deleted;
@@ -41,4 +28,20 @@ public class WorkflowEntity extends BaseDomain {
public void setDeleted(boolean deleted) {
this.deleted = deleted;
}
public String getRevision() {
return revision;
}
public void setRevision(String revision) {
this.revision = revision;
}
public List<WorkflowOperationEntity> getOperations() {
return operations;
}
public void setOperations(List<WorkflowOperationEntity> operations) {
this.operations = operations;
}
}
@@ -1,5 +1,6 @@
package org.tests.o2m.dm;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.ebean.annotation.SoftDelete;
import org.tests.model.draftable.BaseDomain;
@@ -8,14 +9,13 @@ import java.util.ArrayList;
import java.util.List;
@Entity
public class WorkflowOperationEntity extends BaseDomain {
public class WorkflowOperationEntity extends HistoryColumns {
private String name;
@ManyToOne
@JoinColumn(name = "workflow_id")
@JsonIgnore
private WorkflowEntity workflowEntity;
@SoftDelete
private boolean deleted;