mirror of
https://github.com/ebean-orm/ebean.git
synced 2026-10-24 15:55:55 +00:00
#118 - ENH: Add support for for Soft Deletes (Logical Deletion) ...
This commit is contained in:
@@ -704,6 +704,10 @@ public final class Ebean {
|
||||
* you automatically.
|
||||
* </p>
|
||||
* <p>
|
||||
* If the bean is configured with <code>@SoftDelete</code> then this will perform a soft
|
||||
* delete rather than a hard/permanent delete.
|
||||
* </p>
|
||||
* <p>
|
||||
* If the Bean does not have a version property (or loaded version property) and
|
||||
* the bean does not exist then this returns false indicating that nothing was
|
||||
* deleted. Note that, if JDBC batch mode is used then this always returns true.
|
||||
@@ -713,6 +717,13 @@ public final class Ebean {
|
||||
return serverMgr.getDefaultServer().delete(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the bean in permanent fashion (will not use soft delete).
|
||||
*/
|
||||
public static boolean deletePermanent(Object bean) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().deletePermanent(bean);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the bean given its type and id.
|
||||
*/
|
||||
@@ -734,6 +745,13 @@ public final class Ebean {
|
||||
return serverMgr.getDefaultServer().deleteAll(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete permanent all the beans in the Collection (will not use soft delete).
|
||||
*/
|
||||
public static int deleteAllPermanent(Collection<?> beans) throws OptimisticLockException {
|
||||
return serverMgr.getDefaultServer().deleteAllPermanent(beans);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh the values of a bean.
|
||||
* <p>
|
||||
|
||||
@@ -1273,6 +1273,26 @@ public interface EbeanServer {
|
||||
*/
|
||||
boolean delete(Object bean, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete a bean permanently without soft delete.
|
||||
*/
|
||||
boolean deletePermanent(Object bean) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete a bean permanently without soft delete using an explicit transaction.
|
||||
*/
|
||||
boolean deletePermanent(Object bean, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete all the beans in the collection permanently without soft delete.
|
||||
*/
|
||||
int deleteAllPermanent(Collection<?> beans) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete all the beans in the collection permanently without soft delete using an explicit transaction.
|
||||
*/
|
||||
int deleteAllPermanent(Collection<?> beans, Transaction transaction) throws OptimisticLockException;
|
||||
|
||||
/**
|
||||
* Delete the bean given its type and id.
|
||||
*/
|
||||
|
||||
@@ -1883,9 +1883,28 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
/**
|
||||
* Delete the bean with the explicit transaction.
|
||||
*/
|
||||
public boolean delete(Object bean, Transaction t) {
|
||||
|
||||
return persister.delete(checkEntityBean(bean), t);
|
||||
public boolean delete(Object bean, Transaction t) throws OptimisticLockException {
|
||||
return persister.delete(checkEntityBean(bean), t, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deletePermanent(Object bean) throws OptimisticLockException {
|
||||
return deletePermanent(bean, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deletePermanent(Object bean, Transaction t) throws OptimisticLockException {
|
||||
return persister.delete(checkEntityBean(bean), t, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAllPermanent(Collection<?> beans) {
|
||||
return deleteAllInternal(beans.iterator(), null, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int deleteAllPermanent(Collection<?> beans, Transaction t) {
|
||||
return deleteAllInternal(beans.iterator(), t, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1893,7 +1912,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
*/
|
||||
@Override
|
||||
public int deleteAll(Collection<?> beans) {
|
||||
return deleteAllInternal(beans.iterator(), null);
|
||||
return deleteAllInternal(beans.iterator(), null, false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1901,13 +1920,13 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
*/
|
||||
@Override
|
||||
public int deleteAll(Collection<?> beans, Transaction t) {
|
||||
return deleteAllInternal(beans.iterator(), t);
|
||||
return deleteAllInternal(beans.iterator(), t, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all the beans in the iterator with an explicit transaction.
|
||||
*/
|
||||
private int deleteAllInternal(Iterator<?> it, Transaction t) {
|
||||
private int deleteAllInternal(Iterator<?> it, Transaction t, boolean permanent) {
|
||||
|
||||
TransWrapper wrap = initTransIfRequired(t);
|
||||
|
||||
@@ -1917,7 +1936,7 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer {
|
||||
int deleteCount = 0;
|
||||
while (it.hasNext()) {
|
||||
EntityBean bean = checkEntityBean(it.next());
|
||||
persister.delete(bean, trans);
|
||||
persister.delete(bean, trans, permanent);
|
||||
deleteCount++;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import com.avaje.ebeaninternal.server.persist.PersistExecute;
|
||||
public abstract class PersistRequest extends BeanRequest implements BatchPostExecute {
|
||||
|
||||
public enum Type {
|
||||
INSERT, UPDATE, DELETE, SOFT_DELETE, UPDATESQL, CALLABLESQL
|
||||
INSERT, UPDATE, DELETE, SOFT_DELETE, DELETE_PERMANENT, UPDATESQL, CALLABLESQL
|
||||
}
|
||||
|
||||
protected boolean persistCascade;
|
||||
|
||||
@@ -256,6 +256,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
beanDescriptor.cacheHandleUpdate(idValue, this);
|
||||
break;
|
||||
case DELETE:
|
||||
case SOFT_DELETE:
|
||||
// Bean deleted from cache early via postDelete()
|
||||
break;
|
||||
default:
|
||||
@@ -546,6 +547,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
}
|
||||
switch (type) {
|
||||
case DELETE:
|
||||
case SOFT_DELETE:
|
||||
postDelete();
|
||||
break;
|
||||
case UPDATE:
|
||||
@@ -614,6 +616,7 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
controller.postUpdate(this);
|
||||
break;
|
||||
case DELETE:
|
||||
case SOFT_DELETE:
|
||||
controller.postDelete(this);
|
||||
break;
|
||||
default:
|
||||
@@ -635,6 +638,9 @@ public final class PersistRequestBean<T> extends PersistRequest implements BeanP
|
||||
case DELETE:
|
||||
transaction.logSummary("Deleted [" + name + "] [" + idValue + "]" + draft);
|
||||
break;
|
||||
case SOFT_DELETE:
|
||||
transaction.logSummary("SoftDelete [" + name + "] [" + idValue + "]" + draft);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public interface Persister {
|
||||
/**
|
||||
* Delete the bean.
|
||||
*/
|
||||
boolean delete(EntityBean entityBean, Transaction t);
|
||||
boolean delete(EntityBean entityBean, Transaction t, boolean permanent);
|
||||
|
||||
/**
|
||||
* Delete multiple beans given a collection of Id values.
|
||||
|
||||
@@ -683,6 +683,7 @@ public class BeanDescriptor<T> implements MetaBeanInfo, SpiBeanType<T> {
|
||||
case INSERT:
|
||||
return changeLogFilter.includeInsert(request) ? insertBeanChange(request): null;
|
||||
case UPDATE:
|
||||
case SOFT_DELETE:
|
||||
return changeLogFilter.includeUpdate(request) ? updateBeanChange(request): null;
|
||||
case DELETE:
|
||||
return changeLogFilter.includeDelete(request) ? deleteBeanChange(request) :null;
|
||||
|
||||
@@ -138,6 +138,7 @@ public class BatchedBeanHolder {
|
||||
return inserts.size();
|
||||
|
||||
case UPDATE:
|
||||
case SOFT_DELETE:
|
||||
if (updates == null) {
|
||||
updates = new ArrayList<PersistRequest>();
|
||||
}
|
||||
|
||||
@@ -336,7 +336,7 @@ public final class DefaultPersister implements Persister {
|
||||
*/
|
||||
private void deleteRecurse(EntityBean detailBean, Transaction t, boolean softDelete) {
|
||||
|
||||
Type deleteType = softDelete ? Type.SOFT_DELETE : Type.DELETE;
|
||||
Type deleteType = softDelete ? Type.SOFT_DELETE : Type.DELETE_PERMANENT;
|
||||
deleteRequest(createRequest(detailBean, t, deleteType));
|
||||
}
|
||||
|
||||
@@ -498,15 +498,16 @@ public final class DefaultPersister implements Persister {
|
||||
* Delete the bean with the explicit transaction.
|
||||
* Return false if the delete is executed without OCC and 0 rows were deleted.
|
||||
*/
|
||||
public boolean delete(EntityBean bean, Transaction t) {
|
||||
public boolean delete(EntityBean bean, Transaction t, boolean permanent) {
|
||||
|
||||
PersistRequestBean<EntityBean> request = createRequest(bean, t, Type.DELETE);
|
||||
Type deleteType = permanent ? Type.DELETE_PERMANENT : Type.DELETE;
|
||||
PersistRequestBean<EntityBean> request = createRequest(bean, t, deleteType);
|
||||
boolean deleted = deleteRequest(request);
|
||||
|
||||
if (request.isDraftable()) {
|
||||
if (request.isDraftable() && request.getType() == Type.DELETE) {
|
||||
// we have just deleting a draft bean so now we need to delete the
|
||||
// associated 'live' bean. This is effectively an 'automatic publish'.
|
||||
deleteRequest(createPublishRequest(request.createReference(), t, Type.DELETE, true));
|
||||
deleteRequest(createPublishRequest(request.createReference(), t, Type.DELETE_PERMANENT, true));
|
||||
}
|
||||
return deleted;
|
||||
}
|
||||
@@ -541,8 +542,8 @@ public final class DefaultPersister implements Persister {
|
||||
|
||||
private void deleteList(List<?> beanList, Transaction t, boolean softDelete) {
|
||||
for (int i = 0; i < beanList.size(); i++) {
|
||||
// deleteRecurse((EntityBean) beanList.get(i), t, softDelete);
|
||||
delete((EntityBean) beanList.get(i), t);
|
||||
deleteRecurse((EntityBean) beanList.get(i), t, softDelete);
|
||||
//delete((EntityBean) beanList.get(i), t);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -590,7 +591,7 @@ public final class DefaultPersister implements Persister {
|
||||
// We actually need to execute a query to get the foreign key values
|
||||
// as they are required for the delete cascade. Query back just the
|
||||
// Id and the appropriate foreign key values
|
||||
Query<?> q = deleteRequiresQuery(descriptor, propImportDelete);
|
||||
Query<?> q = deleteRequiresQuery(descriptor, propImportDelete, softDelete);
|
||||
if (idList != null) {
|
||||
q.where().idIn(idList);
|
||||
if (t.isLogSummary()) {
|
||||
@@ -701,7 +702,7 @@ public final class DefaultPersister implements Persister {
|
||||
* We need to create and execute a query to get the foreign key values as
|
||||
* the delete cascades to them (foreign keys).
|
||||
*/
|
||||
private Query<?> deleteRequiresQuery(BeanDescriptor<?> desc, BeanPropertyAssocOne<?>[] propImportDelete) {
|
||||
private Query<?> deleteRequiresQuery(BeanDescriptor<?> desc, BeanPropertyAssocOne<?>[] propImportDelete, boolean softDelete) {
|
||||
|
||||
Query<?> q = server.createQuery(desc.getBeanType());
|
||||
StringBuilder sb = new StringBuilder(30);
|
||||
@@ -710,6 +711,10 @@ public final class DefaultPersister implements Persister {
|
||||
}
|
||||
q.setAutoTune(false);
|
||||
q.select(sb.toString());
|
||||
if (!softDelete) {
|
||||
// hard delete so we want this query to include logically deleted rows (if any)
|
||||
q.includeSoftDeletes();
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
@@ -1492,7 +1497,10 @@ public final class DefaultPersister implements Persister {
|
||||
private <T> PersistRequestBean<T> createRequest(T bean, Transaction t, Object parentBean, BeanManager<?> mgr,
|
||||
PersistRequest.Type type, boolean saveRecurse, boolean publish) {
|
||||
|
||||
if (type == Type.DELETE && mgr.getBeanDescriptor().isSoftDelete()) {
|
||||
if (type == Type.DELETE_PERMANENT) {
|
||||
type = Type.DELETE;
|
||||
} else if (type == Type.DELETE && mgr.getBeanDescriptor().isSoftDelete()) {
|
||||
// automatically convert to soft delete for types that support it
|
||||
type = Type.SOFT_DELETE;
|
||||
}
|
||||
|
||||
|
||||
@@ -183,6 +183,7 @@ public class BeanPersistIds implements Serializable {
|
||||
addUpdateId(id);
|
||||
break;
|
||||
case DELETE:
|
||||
case SOFT_DELETE:
|
||||
addDeleteId(id);
|
||||
break;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user