#118 - ENH: Add support for for Soft Deletes (Logical Deletion) ...

This commit is contained in:
Robin Bygrave
2015-12-02 23:46:26 +13:00
parent f39a684c8e
commit aea7a7fd65
17 changed files with 392 additions and 20 deletions
@@ -667,6 +667,26 @@ public class TDSpiEbeanServer implements SpiEbeanServer {
return false;
}
@Override
public boolean deletePermanent(Object bean) throws OptimisticLockException {
return false;
}
@Override
public boolean deletePermanent(Object bean, Transaction transaction) throws OptimisticLockException {
return false;
}
@Override
public int deleteAllPermanent(Collection<?> beans) throws OptimisticLockException {
return 0;
}
@Override
public int deleteAllPermanent(Collection<?> beans, Transaction transaction) throws OptimisticLockException {
return 0;
}
@Override
public int execute(SqlUpdate updSql, Transaction t) {
return 0;
@@ -0,0 +1,21 @@
package com.avaje.tests.model.softdelete;
import javax.persistence.Entity;
@Entity
public class ESoftDelDown extends BaseSoftDelete {
String down;
public ESoftDelDown(String up) {
this.down = down;
}
public String getDown() {
return down;
}
public void setDown(String down) {
this.down = down;
}
}
@@ -0,0 +1,64 @@
package com.avaje.tests.model.softdelete;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import java.util.List;
@Entity
public class ESoftDelMid extends BaseSoftDelete {
@ManyToOne(optional = false)
ESoftDelTop top;
String mid;
@ManyToOne(cascade = CascadeType.ALL)
ESoftDelUp up;
@OneToMany(cascade = CascadeType.ALL)
List<ESoftDelDown> downs;
public ESoftDelMid(ESoftDelTop top, String mid) {
this.top = top;
this.mid = mid;
}
public ESoftDelTop getTop() {
return top;
}
public void setTop(ESoftDelTop top) {
this.top = top;
}
public ESoftDelUp getUp() {
return up;
}
public void setUp(ESoftDelUp up) {
this.up = up;
}
public String getMid() {
return mid;
}
public void setMid(String mid) {
this.mid = mid;
}
public List<ESoftDelDown> getDowns() {
return downs;
}
public void setDowns(List<ESoftDelDown> downs) {
this.downs = downs;
}
public void addDown(String down) {
getDowns().add(new ESoftDelDown(down));
}
}
@@ -0,0 +1,44 @@
package com.avaje.tests.model.softdelete;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import java.util.List;
@Entity
public class ESoftDelTop extends BaseSoftDelete {
String top;
@OneToMany(mappedBy = "top", cascade = CascadeType.ALL)
List<ESoftDelMid> mids;
public ESoftDelTop(String top) {
this.top = top;
}
public String getTop() {
return top;
}
public void setTop(String top) {
this.top = top;
}
public List<ESoftDelMid> getMids() {
return mids;
}
public void setMids(List<ESoftDelMid> mids) {
this.mids = mids;
}
public ESoftDelMid addMids(String mid) {
ESoftDelMid bean = new ESoftDelMid(this, mid);
getMids().add(bean);
return bean;
}
}
@@ -0,0 +1,21 @@
package com.avaje.tests.model.softdelete;
import javax.persistence.Entity;
@Entity
public class ESoftDelUp extends BaseSoftDelete {
String up;
public ESoftDelUp(String up) {
this.up = up;
}
public String getUp() {
return up;
}
public void setUp(String up) {
this.up = up;
}
}
@@ -20,7 +20,6 @@ public class TestSoftDeleteBasic extends BaseTestCase {
EBasicSoftDelete bean = new EBasicSoftDelete();
bean.setName("one");
Ebean.save(bean);
Ebean.delete(bean);
@@ -42,7 +41,39 @@ public class TestSoftDeleteBasic extends BaseTestCase {
.findUnique();
assertThat(findInclude).isNotNull();
}
@Test
public void testDeleteById() {
EBasicSoftDelete bean = new EBasicSoftDelete();
bean.setName("two");
Ebean.save(bean);
Ebean.delete(EBasicSoftDelete.class, bean.getId());
}
@Test
public void testDeletePartial() {
EBasicSoftDelete bean = new EBasicSoftDelete();
bean.setName("partial");
Ebean.save(bean);
// partially loaded bean without deleted state loaded
EBasicSoftDelete partial = Ebean.find(EBasicSoftDelete.class)
.select("id")
.setId(bean.getId())
.findUnique();
LoggedSqlCollector.start();
Ebean.delete(partial);
// check lazy loading isn't invoked (deleted set to true without invoking lazy loading)
List<String> loggedSql = LoggedSqlCollector.stop();
assertThat(loggedSql).hasSize(2);
assertThat(loggedSql.get(0)).contains("update ebasic_sdchild set deleted=");
assertThat(loggedSql.get(1)).contains("update ebasic_soft_delete set deleted=? where id=?");
}
@Test
@@ -0,0 +1,97 @@
package com.avaje.tests.softdelete;
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.Transaction;
import com.avaje.ebean.config.PersistBatch;
import com.avaje.tests.model.softdelete.ESoftDelMid;
import com.avaje.tests.model.softdelete.ESoftDelRole;
import com.avaje.tests.model.softdelete.ESoftDelTop;
import com.avaje.tests.model.softdelete.ESoftDelUp;
import com.avaje.tests.model.softdelete.ESoftDelUser;
import org.avaje.ebeantest.LoggedSqlCollector;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
public class TestSoftDeleteTop extends BaseTestCase {
@Test
public void testDeletePermanent() {
ESoftDelUp up1 = new ESoftDelUp("up1");
Ebean.save(up1);
Ebean.delete(up1);
Ebean.deletePermanent(up1);
}
@Test
public void testSoftDeleteJdbcBatch() {
ESoftDelUp up1 = new ESoftDelUp("upBatch1");
Ebean.save(up1);
ESoftDelUp up2 = new ESoftDelUp("upBatch2");
Ebean.save(up2);
Transaction transaction = Ebean.beginTransaction();
try {
transaction.setBatch(PersistBatch.ALL);
Ebean.delete(up1);
Ebean.delete(up2);
transaction.commit();
} finally {
transaction.end();
}
List<ESoftDelUp> list = new ArrayList<ESoftDelUp>();
list.add(up1);
list.add(up2);
Ebean.deleteAllPermanent(list);
}
@Test
public void testSoftDeleteAll() {
ESoftDelUp up1 = new ESoftDelUp("upBatchX");
ESoftDelUp up2 = new ESoftDelUp("upBatchY");
List<ESoftDelUp> list = new ArrayList<ESoftDelUp>();
list.add(up1);
list.add(up2);
// by default uses JDBC for the 'all' methods
Ebean.saveAll(list);
Ebean.deleteAll(list);
Ebean.deleteAllPermanent(list);
}
@Test
public void test() {
ESoftDelUp up1 = new ESoftDelUp("up1");
ESoftDelTop top1 = new ESoftDelTop("top1");
ESoftDelMid mid1 = top1.addMids("mid1");
mid1.addDown("down1");
mid1.addDown("down2");
mid1.setUp(up1);
ESoftDelMid mid2 = top1.addMids("mid2");
mid2.addDown("down3");
mid2.addDown("down4");
Ebean.save(top1);
Ebean.delete(top1);
Ebean.deletePermanent(top1);
}
}