mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
#118 - ENH: Add support for for Soft Deletes (Logical Deletion) ...
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
package com.avaje.tests.model.softdelete;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Version;
|
||||
|
||||
@Entity
|
||||
public class EBasicNoSDChild {
|
||||
|
||||
@Id
|
||||
Long id;
|
||||
|
||||
@Version
|
||||
Long version;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
EBasicSoftDelete owner;
|
||||
|
||||
String childName;
|
||||
|
||||
long amount;
|
||||
|
||||
public EBasicNoSDChild(EBasicSoftDelete owner, String childName, long amount) {
|
||||
this.owner = owner;
|
||||
this.childName = childName;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public EBasicNoSDChild() {
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Long getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(Long version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public EBasicSoftDelete getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(EBasicSoftDelete owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public String getChildName() {
|
||||
return childName;
|
||||
}
|
||||
|
||||
public void setChildName(String childName) {
|
||||
this.childName = childName;
|
||||
}
|
||||
|
||||
public long getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(long amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package com.avaje.tests.model.softdelete;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
@Entity
|
||||
public class EBasicSDChild extends BaseSoftDelete {
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
EBasicSoftDelete owner;
|
||||
|
||||
String childName;
|
||||
|
||||
long amount;
|
||||
|
||||
public EBasicSDChild(EBasicSoftDelete owner, String childName, long amount) {
|
||||
this.owner = owner;
|
||||
this.childName = childName;
|
||||
this.amount = amount;
|
||||
}
|
||||
|
||||
public EBasicSDChild() {
|
||||
}
|
||||
|
||||
public EBasicSoftDelete getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(EBasicSoftDelete owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public String getChildName() {
|
||||
return childName;
|
||||
}
|
||||
|
||||
public void setChildName(String childName) {
|
||||
this.childName = childName;
|
||||
}
|
||||
|
||||
public long getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
public void setAmount(long amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.avaje.tests.model.softdelete;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.OneToMany;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class EBasicSoftDelete extends BaseSoftDelete {
|
||||
@@ -9,6 +12,13 @@ public class EBasicSoftDelete extends BaseSoftDelete {
|
||||
|
||||
String description;
|
||||
|
||||
@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL)
|
||||
List<EBasicSDChild> children;
|
||||
|
||||
@OneToMany(mappedBy = "owner", cascade = CascadeType.ALL)
|
||||
List<EBasicNoSDChild> nosdChildren;
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@@ -24,4 +34,28 @@ public class EBasicSoftDelete extends BaseSoftDelete {
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public List<EBasicSDChild> getChildren() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public void setChildren(List<EBasicSDChild> children) {
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
public void addChild(String childName, long amount) {
|
||||
getChildren().add(new EBasicSDChild(this, childName, amount));
|
||||
}
|
||||
|
||||
public List<EBasicNoSDChild> getNosdChildren() {
|
||||
return nosdChildren;
|
||||
}
|
||||
|
||||
public void setNosdChildren(List<EBasicNoSDChild> nosdChildren) {
|
||||
this.nosdChildren = nosdChildren;
|
||||
}
|
||||
|
||||
public void addNoSoftDeleteChild(String childName, long amount) {
|
||||
getNosdChildren().add(new EBasicNoSDChild(this, childName, amount));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.avaje.tests.model.softdelete;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ManyToMany;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class ESoftDelRole extends BaseSoftDelete {
|
||||
|
||||
String roleName;
|
||||
|
||||
@ManyToMany(cascade = CascadeType.ALL)
|
||||
List<ESoftDelUser> users;
|
||||
|
||||
public ESoftDelRole(String roleName) {
|
||||
this.roleName = roleName;
|
||||
}
|
||||
|
||||
public String getRoleName() {
|
||||
return roleName;
|
||||
}
|
||||
|
||||
public void setRoleName(String roleName) {
|
||||
this.roleName = roleName;
|
||||
}
|
||||
|
||||
public List<ESoftDelUser> getUsers() {
|
||||
return users;
|
||||
}
|
||||
|
||||
public void setUsers(List<ESoftDelUser> users) {
|
||||
this.users = users;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.avaje.tests.model.softdelete;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ManyToMany;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
public class ESoftDelUser extends BaseSoftDelete {
|
||||
|
||||
String userName;
|
||||
|
||||
@ManyToMany(cascade = CascadeType.ALL)
|
||||
List<ESoftDelRole> roles;
|
||||
|
||||
public ESoftDelUser(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public ESoftDelUser() {
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public List<ESoftDelRole> getRoles() {
|
||||
return roles;
|
||||
}
|
||||
|
||||
public void setRoles(List<ESoftDelRole> roles) {
|
||||
this.roles = roles;
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,15 @@ package com.avaje.tests.softdelete;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.ebean.Query;
|
||||
import com.avaje.ebean.SqlQuery;
|
||||
import com.avaje.ebean.SqlRow;
|
||||
import com.avaje.tests.model.softdelete.EBasicSoftDelete;
|
||||
import org.avaje.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestSoftDeleteBasic extends BaseTestCase {
|
||||
@@ -40,4 +44,84 @@ public class TestSoftDeleteBasic extends BaseTestCase {
|
||||
assertThat(findInclude).isNotNull();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCascadeSaveDelete() {
|
||||
|
||||
EBasicSoftDelete bean = new EBasicSoftDelete();
|
||||
bean.setName("cascadeOne");
|
||||
bean.addChild("child1", 10);
|
||||
bean.addChild("child2", 20);
|
||||
bean.addChild("child3", 30);
|
||||
bean.addNoSoftDeleteChild("nsd1", 101);
|
||||
bean.addNoSoftDeleteChild("nsd2", 102);
|
||||
|
||||
Ebean.save(bean);
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Ebean.delete(bean);
|
||||
|
||||
List<String> loggedSql = LoggedSqlCollector.stop();
|
||||
|
||||
// The children without SoftDelete are left as is (so no third statement)
|
||||
assertThat(loggedSql).hasSize(2);
|
||||
|
||||
// first statement is a single bulk update of the children with SoftDelete
|
||||
assertThat(loggedSql.get(0)).contains("update ebasic_sdchild set deleted=");
|
||||
assertThat(loggedSql.get(0)).contains("where owner_id = ?");
|
||||
|
||||
// second statement is the top level bean
|
||||
assertThat(loggedSql.get(1)).contains("update ebasic_soft_delete set version=?, deleted=? where id=? and version=?");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testFetch() {
|
||||
|
||||
EBasicSoftDelete bean = new EBasicSoftDelete();
|
||||
bean.setName("cascadeOne");
|
||||
bean.addChild("child1", 10);
|
||||
bean.addChild("child2", 20);
|
||||
bean.addChild("child3", 30);
|
||||
bean.addNoSoftDeleteChild("nsd1", 101);
|
||||
bean.addNoSoftDeleteChild("nsd2", 102);
|
||||
|
||||
Ebean.save(bean);
|
||||
|
||||
Ebean.delete(bean.getChildren().get(1));
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
|
||||
Query<EBasicSoftDelete> query1 =
|
||||
Ebean.find(EBasicSoftDelete.class)
|
||||
.fetch("children")
|
||||
.where().eq("id", bean.getId())
|
||||
.query();
|
||||
|
||||
List<EBasicSoftDelete> fetch1 = query1.findList();
|
||||
String generatedSql = query1.getGeneratedSql();
|
||||
|
||||
// first statement is a single bulk update of the children with SoftDelete
|
||||
assertThat(generatedSql).contains("t0.deleted=");
|
||||
assertThat(generatedSql).contains("t1.deleted=");
|
||||
assertThat(fetch1.get(0).getChildren()).hasSize(2);
|
||||
|
||||
assertThat(fetch1.get(0).getNosdChildren()).hasSize(2);
|
||||
|
||||
|
||||
// fetch again using lazy loading
|
||||
EBasicSoftDelete fetchWithLazy = Ebean.find(EBasicSoftDelete.class, bean.getId());
|
||||
assertThat(fetchWithLazy.getChildren()).hasSize(2);
|
||||
|
||||
// fetch includeSoftDeletes using lazy loading
|
||||
EBasicSoftDelete fetchAllWithLazy =
|
||||
Ebean.find(EBasicSoftDelete.class)
|
||||
.setId(bean.getId())
|
||||
.includeSoftDeletes()
|
||||
.findUnique();
|
||||
|
||||
assertThat(fetchAllWithLazy.getChildren()).hasSize(3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.avaje.tests.softdelete;
|
||||
|
||||
import com.avaje.ebean.BaseTestCase;
|
||||
import com.avaje.ebean.Ebean;
|
||||
import com.avaje.tests.model.softdelete.ESoftDelRole;
|
||||
import com.avaje.tests.model.softdelete.ESoftDelUser;
|
||||
import org.avaje.ebeantest.LoggedSqlCollector;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class TestSoftDeleteManyToMany extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
ESoftDelRole role1 = new ESoftDelRole("role1");
|
||||
ESoftDelRole role2 = new ESoftDelRole("role2");
|
||||
|
||||
Ebean.save(role1);
|
||||
Ebean.save(role2);
|
||||
|
||||
ESoftDelUser user1 = new ESoftDelUser("user1");
|
||||
user1.getRoles().add(role1);
|
||||
user1.getRoles().add(role2);
|
||||
|
||||
Ebean.save(user1);
|
||||
|
||||
|
||||
LoggedSqlCollector.start();
|
||||
Ebean.delete(user1);
|
||||
|
||||
List<String> loggedSql = LoggedSqlCollector.stop();
|
||||
|
||||
// No Delete from the relationship table
|
||||
assertThat(loggedSql).hasSize(1);
|
||||
assertThat(loggedSql.get(0)).contains("update esoft_del_user set version=?, deleted=? where id=? and version=?;");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user