From 03189ac92a8e515e6438eea3fb65d5803c4685f0 Mon Sep 17 00:00:00 2001 From: Robin Bygrave Date: Tue, 26 Apr 2016 21:30:52 +1200 Subject: [PATCH] #661 - ENH: Add deletePermanent(beanType, id) and deleteAllPermanent(beanType, ids) ... (basically missing API) --- src/main/java/com/avaje/ebean/Ebean.java | 14 + .../java/com/avaje/ebean/EbeanServer.java | 24 +- .../server/core/DefaultServer.java | 30 +- .../ebeaninternal/server/core/Persister.java | 4 +- .../server/persist/DefaultPersister.java | 14 +- .../ebean/EbeanServer_deleteAllByIdTest.java | 48 +++- .../ebean/EbeanServer_deleteByIdTest.java | 42 ++- .../ebeaninternal/api/TDSpiEbeanServer.java | 20 ++ .../avaje/tests/draftable/DocLinkTest.java | 1 - .../tests/model/onetoone/album/Album.java | 7 + .../tests/model/onetoone/album/Cover.java | 7 + .../album/DeleteById_SoftDelete_Tests.java | 263 ++++++++++++++++++ 12 files changed, 454 insertions(+), 20 deletions(-) create mode 100644 src/test/java/com/avaje/tests/model/onetoone/album/DeleteById_SoftDelete_Tests.java diff --git a/src/main/java/com/avaje/ebean/Ebean.java b/src/main/java/com/avaje/ebean/Ebean.java index c1514887a..d56f48c78 100644 --- a/src/main/java/com/avaje/ebean/Ebean.java +++ b/src/main/java/com/avaje/ebean/Ebean.java @@ -728,6 +728,13 @@ public final class Ebean { return serverMgr.getDefaultServer().delete(beanType, id); } + /** + * Delete permanent the bean given its type and id. + */ + public static int deletePermanent(Class beanType, Object id) { + return serverMgr.getDefaultServer().deletePermanent(beanType, id); + } + /** * Delete several beans given their type and id values. */ @@ -735,6 +742,13 @@ public final class Ebean { serverMgr.getDefaultServer().deleteAll(beanType, ids); } + /** + * Delete permanent several beans given their type and id values. + */ + public static void deleteAllPermanent(Class beanType, Collection ids) { + serverMgr.getDefaultServer().deleteAllPermanent(beanType, ids); + } + /** * Delete all the beans in the Collection. */ diff --git a/src/main/java/com/avaje/ebean/EbeanServer.java b/src/main/java/com/avaje/ebean/EbeanServer.java index ed40ffb05..6f54bd2f2 100644 --- a/src/main/java/com/avaje/ebean/EbeanServer.java +++ b/src/main/java/com/avaje/ebean/EbeanServer.java @@ -1,6 +1,5 @@ package com.avaje.ebean; -import com.avaje.ebean.annotation.CacheStrategy; import com.avaje.ebean.cache.ServerCacheManager; import com.avaje.ebean.config.ServerConfig; import com.avaje.ebean.meta.MetaInfoManager; @@ -1351,6 +1350,16 @@ public interface EbeanServer { */ int delete(Class beanType, Object id, Transaction transaction); + /** + * Delete permanent given the bean type and id. + */ + int deletePermanent(Class beanType, Object id); + + /** + * Delete permanent given the bean type and id with an explicit transaction. + */ + int deletePermanent(Class beanType, Object id, Transaction transaction); + /** * Delete all the beans in the collection. */ @@ -1367,11 +1376,20 @@ public interface EbeanServer { void deleteAll(Class beanType, Collection ids); /** - * Delete several beans given their type and id values with an explicit - * transaction. + * Delete several beans given their type and id values with an explicit transaction. */ void deleteAll(Class beanType, Collection ids, Transaction transaction); + /** + * Delete permanent for several beans given their type and id values. + */ + void deleteAllPermanent(Class beanType, Collection ids); + + /** + * Delete permanent for several beans given their type and id values with an explicit transaction. + */ + void deleteAllPermanent(Class beanType, Collection ids, Transaction transaction); + /** * Execute a Sql Update Delete or Insert statement. This returns the number of * rows that where updated, deleted or inserted. If is executed in batch then diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java index a227e2c16..1f144be70 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/DefaultServer.java @@ -1765,11 +1765,23 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { } public int delete(Class beanType, Object id, Transaction t) { + return delete(beanType, id, t, false); + } + + public int deletePermanent(Class beanType, Object id) { + return delete(beanType, id, null, true); + } + + public int deletePermanent(Class beanType, Object id, Transaction t) { + return delete(beanType, id, t, true); + } + + private int delete(Class beanType, Object id, Transaction t, boolean permanent) { TransWrapper wrap = initTransIfRequired(t); try { SpiTransaction trans = wrap.transaction; - int rowCount = persister.delete(beanType, id, trans); + int rowCount = persister.delete(beanType, id, trans, permanent); wrap.commitIfCreated(); return rowCount; @@ -1787,11 +1799,25 @@ public final class DefaultServer implements SpiServer, SpiEbeanServer { @Override public void deleteAll(Class beanType, Collection ids, Transaction t) { + deleteAll(beanType, ids, t, false); + } + + @Override + public void deleteAllPermanent(Class beanType, Collection ids) { + deleteAll(beanType, ids, null, true); + } + + @Override + public void deleteAllPermanent(Class beanType, Collection ids, Transaction t) { + deleteAll(beanType, ids, t, true); + } + + private void deleteAll(Class beanType, Collection ids, Transaction t, boolean permanent) { TransWrapper wrap = initTransIfRequired(t); try { SpiTransaction trans = wrap.transaction; - persister.deleteMany(beanType, ids, trans); + persister.deleteMany(beanType, ids, trans, permanent); wrap.commitIfCreated(); } catch (RuntimeException e) { diff --git a/src/main/java/com/avaje/ebeaninternal/server/core/Persister.java b/src/main/java/com/avaje/ebeaninternal/server/core/Persister.java index fac5f767b..3413ccd3d 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/core/Persister.java +++ b/src/main/java/com/avaje/ebeaninternal/server/core/Persister.java @@ -61,7 +61,7 @@ public interface Persister { * This will also cascade delete one level of children. *

*/ - int delete(Class beanType, Object id, Transaction transaction); + int delete(Class beanType, Object id, Transaction transaction, boolean permanent); /** * Delete the bean. @@ -71,7 +71,7 @@ public interface Persister { /** * Delete multiple beans given a collection of Id values. */ - void deleteMany(Class beanType, Collection ids, Transaction transaction); + void deleteMany(Class beanType, Collection ids, Transaction transaction, boolean permanent); /** * Execute the Update. diff --git a/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java b/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java index bad7189a2..a74bca758 100644 --- a/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java +++ b/src/main/java/com/avaje/ebeaninternal/server/persist/DefaultPersister.java @@ -559,14 +559,13 @@ 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); } } /** * Delete by a List of Id's. */ - public void deleteMany(Class beanType, Collection ids, Transaction transaction) { + public void deleteMany(Class beanType, Collection ids, Transaction transaction, boolean permanent) { if (ids == null || ids.size() == 0) { return; @@ -580,19 +579,18 @@ public final class DefaultPersister implements Persister { idList.add(descriptor.convertId(id)); } - delete(descriptor, null, idList, transaction, descriptor.isSoftDelete()); + boolean softDelete = !permanent && descriptor.isSoftDelete(); + delete(descriptor, null, idList, transaction, softDelete); } /** * Delete by Id. */ - public int delete(Class beanType, Object id, Transaction transaction) { - + public int delete(Class beanType, Object id, Transaction transaction, boolean permanent) { BeanDescriptor descriptor = beanDescriptorManager.getBeanDescriptor(beanType); - - // convert to appropriate type if required id = descriptor.convertId(id); - return delete(descriptor, id, null, transaction, descriptor.isSoftDelete()); + boolean softDelete = !permanent && descriptor.isSoftDelete(); + return delete(descriptor, id, null, transaction, softDelete); } /** diff --git a/src/test/java/com/avaje/ebean/EbeanServer_deleteAllByIdTest.java b/src/test/java/com/avaje/ebean/EbeanServer_deleteAllByIdTest.java index 694b02fc0..9e5ce361c 100644 --- a/src/test/java/com/avaje/ebean/EbeanServer_deleteAllByIdTest.java +++ b/src/test/java/com/avaje/ebean/EbeanServer_deleteAllByIdTest.java @@ -30,7 +30,6 @@ public class EbeanServer_deleteAllByIdTest { List loggedSql = LoggedSqlCollector.stop(); assertThat(loggedSql).hasSize(1); assertThat(loggedSql.get(0)).contains("delete from e_basicver where id in (?,?,?)"); - } @Test @@ -59,6 +58,53 @@ public class EbeanServer_deleteAllByIdTest { assertThat(loggedSql.get(0)).contains("delete from e_basicver where id in (?,?,?)"); } + @Test + public void deleteAllPermanentById() { + + List someBeans = beans(3); + + Ebean.saveAll(someBeans); + List ids = new ArrayList(); + for (EBasicVer someBean : someBeans) { + ids.add(someBean.getId()); + } + + LoggedSqlCollector.start(); + + Ebean.deleteAllPermanent(EBasicVer.class, ids); + + List loggedSql = LoggedSqlCollector.stop(); + assertThat(loggedSql).hasSize(1); + assertThat(loggedSql.get(0)).contains("delete from e_basicver where id in (?,?,?)"); + } + + + @Test + public void deleteAllPermanentById_withTransaction() { + + List someBeans = beans(3); + + Ebean.saveAll(someBeans); + List ids = new ArrayList(); + for (EBasicVer someBean : someBeans) { + ids.add(someBean.getId()); + } + + EbeanServer server = Ebean.getDefaultServer(); + // act + LoggedSqlCollector.start(); + Transaction txn = server.beginTransaction(); + try { + server.deleteAllPermanent(EBasicVer.class, ids, txn); + txn.commit(); + } finally { + txn.end(); + } + List loggedSql = LoggedSqlCollector.stop(); + assertThat(loggedSql).hasSize(1); + assertThat(loggedSql.get(0)).contains("delete from e_basicver where id in (?,?,?)"); + } + private List beans(int count) { List beans = new ArrayList(); for (int i = 0; i < count; i++) { diff --git a/src/test/java/com/avaje/ebean/EbeanServer_deleteByIdTest.java b/src/test/java/com/avaje/ebean/EbeanServer_deleteByIdTest.java index 0cf019b2e..a0b3bebf6 100644 --- a/src/test/java/com/avaje/ebean/EbeanServer_deleteByIdTest.java +++ b/src/test/java/com/avaje/ebean/EbeanServer_deleteByIdTest.java @@ -12,10 +12,9 @@ import static org.assertj.core.api.Assertions.assertThat; public class EbeanServer_deleteByIdTest { @Test - public void deleteAllById() { + public void deleteById() { EBasicVer someBean = bean("foo1"); - Ebean.save(someBean); // act @@ -28,7 +27,23 @@ public class EbeanServer_deleteByIdTest { } @Test - public void deleteAllById_withTransaction() { + public void deletePermanentById() { + + EBasicVer someBean = bean("foo1"); + Ebean.save(someBean); + + // act + LoggedSqlCollector.start(); + Ebean.deletePermanent(EBasicVer.class, someBean.getId()); + + List loggedSql = LoggedSqlCollector.stop(); + assertThat(loggedSql).hasSize(1); + assertThat(loggedSql.get(0)).contains("delete from e_basicver where id = ?"); + } + + + @Test + public void deleteById_withTransaction() { EBasicVer someBean = bean("foo1"); Ebean.save(someBean); @@ -48,6 +63,27 @@ public class EbeanServer_deleteByIdTest { assertThat(loggedSql.get(0)).contains("delete from e_basicver where id = ?"); } + @Test + public void deletePermanentById_withTransaction() { + + EBasicVer someBean = bean("foo2"); + Ebean.save(someBean); + + EbeanServer server = Ebean.getDefaultServer(); + // act + LoggedSqlCollector.start(); + Transaction txn = server.beginTransaction(); + try { + server.deletePermanent(EBasicVer.class, someBean.getId(), txn); + txn.commit(); + } finally { + txn.end(); + } + List loggedSql = LoggedSqlCollector.stop(); + assertThat(loggedSql).hasSize(1); + assertThat(loggedSql.get(0)).contains("delete from e_basicver where id = ?"); + } + private EBasicVer bean(String name) { EBasicVer bean = new EBasicVer(); bean.setName(name); diff --git a/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java b/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java index 663d80847..8ae9467e1 100644 --- a/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java +++ b/src/test/java/com/avaje/ebeaninternal/api/TDSpiEbeanServer.java @@ -575,6 +575,16 @@ public class TDSpiEbeanServer implements SpiEbeanServer { return 0; } + @Override + public int deletePermanent(Class beanType, Object id) { + return 0; + } + + @Override + public int deletePermanent(Class beanType, Object id, Transaction transaction) { + return 0; + } + @Override public int execute(SqlUpdate updSql) { return 0; @@ -765,6 +775,16 @@ public class TDSpiEbeanServer implements SpiEbeanServer { } + @Override + public void deleteAllPermanent(Class beanType, Collection ids) { + + } + + @Override + public void deleteAllPermanent(Class beanType, Collection ids, Transaction transaction) { + + } + @Override public int saveAll(Collection beans, Transaction transaction) throws OptimisticLockException { return 0; diff --git a/src/test/java/com/avaje/tests/draftable/DocLinkTest.java b/src/test/java/com/avaje/tests/draftable/DocLinkTest.java index 27050ca6d..d5fe60989 100644 --- a/src/test/java/com/avaje/tests/draftable/DocLinkTest.java +++ b/src/test/java/com/avaje/tests/draftable/DocLinkTest.java @@ -82,7 +82,6 @@ public class DocLinkTest extends BaseTestCase { Ebean.delete(link1); } - @Test public void testDeletePermanent_whenPublished2() { diff --git a/src/test/java/com/avaje/tests/model/onetoone/album/Album.java b/src/test/java/com/avaje/tests/model/onetoone/album/Album.java index 4b4f195a1..3bc4f4056 100644 --- a/src/test/java/com/avaje/tests/model/onetoone/album/Album.java +++ b/src/test/java/com/avaje/tests/model/onetoone/album/Album.java @@ -17,6 +17,13 @@ public class Album extends BaseModel { @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE) private Cover cover; + public Album(String name) { + this.name = name; + } + + public Album() { + } + public String getName() { return this.name; } diff --git a/src/test/java/com/avaje/tests/model/onetoone/album/Cover.java b/src/test/java/com/avaje/tests/model/onetoone/album/Cover.java index a0138484e..4972d22a6 100644 --- a/src/test/java/com/avaje/tests/model/onetoone/album/Cover.java +++ b/src/test/java/com/avaje/tests/model/onetoone/album/Cover.java @@ -25,6 +25,13 @@ public class Cover extends Model { protected String s3Url; + public Cover() { + } + + public Cover(String s3Url) { + this.s3Url = s3Url; + } + public String getS3Url() { return this.s3Url; } diff --git a/src/test/java/com/avaje/tests/model/onetoone/album/DeleteById_SoftDelete_Tests.java b/src/test/java/com/avaje/tests/model/onetoone/album/DeleteById_SoftDelete_Tests.java new file mode 100644 index 000000000..f6e2dd847 --- /dev/null +++ b/src/test/java/com/avaje/tests/model/onetoone/album/DeleteById_SoftDelete_Tests.java @@ -0,0 +1,263 @@ +package com.avaje.tests.model.onetoone.album; + +import com.avaje.ebean.Ebean; +import com.avaje.ebean.EbeanServer; +import com.avaje.ebean.Transaction; +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 DeleteById_SoftDelete_Tests { + + @Test + public void ebean_deleteById_when_softDelete() { + + Cover cover = new Cover("a1"); + cover.save(); + + LoggedSqlCollector.start(); + + Ebean.delete(Cover.class, cover.getId()); + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(1); + assertThat(sql.get(0)).contains("update cover set deleted=true where id = ?"); + + cover.deletePermanent(); + } + + @Test + public void deleteById_when_softDelete() { + + Cover cover = new Cover("a1"); + cover.save(); + + LoggedSqlCollector.start(); + + Ebean.getDefaultServer().delete(Cover.class, cover.getId(), null); + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(1); + assertThat(sql.get(0)).contains("update cover set deleted=true where id = ?"); + + cover.deletePermanent(); + } + + @Test + public void deletePermanentById_when_softDelete() { + + Cover cover = new Cover("a2"); + cover.save(); + + LoggedSqlCollector.start(); + + Ebean.getDefaultServer().deletePermanent(Cover.class, cover.getId(), null); + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(1); + assertThat(sql.get(0)).contains("delete from cover where id = ?"); + } + + @Test + public void deleteAllById_when_softDelete() { + + EbeanServer server = Ebean.getDefaultServer(); + List beans = beans(2); + server.saveAll(beans); + + LoggedSqlCollector.start(); + + server.deleteAll(Cover.class, ids(beans)); + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(1); + assertThat(sql.get(0)).contains("update cover set deleted=true where id in (?,?)"); + } + + @Test + public void deleteAllById_when_softDelete_withTransaction() { + + EbeanServer server = Ebean.getDefaultServer(); + List beans = beans(2); + server.saveAll(beans); + + LoggedSqlCollector.start(); + + Transaction transaction = server.beginTransaction(); + try { + server.deleteAll(Cover.class, ids(beans), transaction); + server.commitTransaction(); + } finally { + server.endTransaction(); + } + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(1); + assertThat(sql.get(0)).contains("update cover set deleted=true where id in (?,?)"); + } + + @Test + public void ebean_deleteAllPermanentById_when_softDelete() { + + List beans = beans(2); + Ebean.saveAll(beans); + + LoggedSqlCollector.start(); + + Ebean.deleteAllPermanent(Cover.class, ids(beans)); + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(1); + assertThat(sql.get(0)).contains("delete from cover where id in (?,?)"); + } + + @Test + public void deleteAllPermanentById_when_softDelete() { + + EbeanServer server = Ebean.getDefaultServer(); + List beans = beans(2); + server.saveAll(beans); + + LoggedSqlCollector.start(); + + server.deleteAllPermanent(Cover.class, ids(beans)); + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(1); + assertThat(sql.get(0)).contains("delete from cover where id in (?,?)"); + } + + + @Test + public void deleteAllPermanentById_when_softDelete_withTransaction() { + + EbeanServer server = Ebean.getDefaultServer(); + List beans = beans(2); + server.saveAll(beans); + + LoggedSqlCollector.start(); + + Transaction transaction = server.beginTransaction(); + try { + server.deleteAllPermanent(Cover.class, ids(beans), transaction); + server.commitTransaction(); + } finally { + server.endTransaction(); + } + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(1); + assertThat(sql.get(0)).contains("delete from cover where id in (?,?)"); + } + + @Test + public void ebean_deleteAll_when_softDelete() { + + List beans = beans(2); + Ebean.saveAll(beans); + + LoggedSqlCollector.start(); + + Ebean.deleteAll(beans); + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(2); + assertThat(sql.get(0)).contains("update cover set s3url=?, deleted=? where id=?"); + } + + @Test + public void deleteAll_when_softDelete() { + + EbeanServer server = Ebean.getDefaultServer(); + List beans = beans(2); + server.saveAll(beans); + + LoggedSqlCollector.start(); + + server.deleteAll(beans); + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(2); + assertThat(sql.get(0)).contains("update cover set s3url=?, deleted=? where id=?"); + } + + @Test + public void deleteAll_when_softDelete_withTransaction() { + + EbeanServer server = Ebean.getDefaultServer(); + List beans = beans(2); + server.saveAll(beans); + + LoggedSqlCollector.start(); + + Transaction transaction = server.beginTransaction(); + try { + server.deleteAll(beans, transaction); + server.commitTransaction(); + } finally { + server.endTransaction(); + } + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(2); + assertThat(sql.get(0)).contains("update cover set s3url=?, deleted=? where id=?"); + } + + @Test + public void deleteAllPermanent_when_softDelete() { + + EbeanServer server = Ebean.getDefaultServer(); + List beans = beans(2); + server.saveAll(beans); + + LoggedSqlCollector.start(); + + server.deleteAllPermanent(beans); + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(2); + assertThat(sql.get(0)).contains("delete from cover where id=?"); + } + + @Test + public void deleteAllPermanent_when_softDelete_withTransaction() { + + EbeanServer server = Ebean.getDefaultServer(); + List beans = beans(2); + server.saveAll(beans); + + LoggedSqlCollector.start(); + + Transaction transaction = server.beginTransaction(); + try { + server.deleteAllPermanent(beans, transaction); + server.commitTransaction(); + } finally { + server.endTransaction(); + } + + List sql = LoggedSqlCollector.stop(); + assertThat(sql).hasSize(2); + assertThat(sql.get(0)).contains("delete from cover where id=?"); + } + + private List ids(List beans) { + List ids = new ArrayList(); + for (Cover someBean : beans) { + ids.add(someBean.getId()); + } + return ids; + } + + private List beans(int count) { + List beans = new ArrayList(); + for (int i = 0; i < count; i++) { + beans.add(new Cover("delById " + i)); + } + return beans; + } +}