Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ public void loadBean(EntityBeanIntercept ebi) {
// re-add to the batch and lazy load from DB skipping l2 cache
if (loadingStarted.get()) {
if (CoreLog.markedAsDeleted.isLoggable(DEBUG)) {
CoreLog.markedAsDeleted.log(DEBUG, "Adding " + ebi + "to batch " + this + "after loadingStarted(2) ", new RuntimeException("Adding to batch after load(2"));
CoreLog.markedAsDeleted.log(DEBUG, "Adding " + ebi + "to batch " + this + "after loadingStarted(2) ", new RuntimeException("Adding to batch after load(2)"));
}
}
batch.add(ebi);
Expand All @@ -239,9 +239,28 @@ public void loadBean(EntityBeanIntercept ebi) {
return;
}
}

// ensure, that every bean in the batch is in the persistence context.
// this may happen, when bean was previously deleted, but the result is not yet committed.
List<Object> reincarnatedIds = null;
for (EntityBeanIntercept batchEbi : batch) {
Object id = context.desc.getId(batchEbi.owner());
if (id != null && context.desc.contextPutIfAbsent(persistenceContext, id, batchEbi.owner()) == null) {
if (reincarnatedIds == null) {
reincarnatedIds = new ArrayList<>();
}
reincarnatedIds.add(id);
if (CoreLog.markedAsDeleted.isLoggable(DEBUG)) {
CoreLog.markedAsDeleted.log(DEBUG, "Temporary adding " + ebi + "to persistence context", new RuntimeException("Temporary adding bean to persistence context"));
}
}
}
context.desc.ebeanServer().loadBean(new LoadBeanRequest(this, ebi, context.hitCache));
batch.clear();
if (reincarnatedIds != null) {
for (Object id : reincarnatedIds) {
context.desc.contextClear(persistenceContext, id);
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@


import io.ebean.Database;
import io.ebean.DatabaseBuilder;
import io.ebean.DatabaseFactory;
import io.ebean.Transaction;
import io.ebean.DatabaseBuilder;
import io.ebean.config.DatabaseConfig;
import io.ebean.event.BeanDeleteIdRequest;
import io.ebean.event.BeanPersistAdapter;
import io.ebean.event.BeanPersistController;
import io.ebean.event.BeanPersistRequest;
import io.ebean.test.LoggedSql;
import org.junit.jupiter.api.Test;
import org.tests.model.basic.EBasicVer;
import org.tests.model.basic.UTDetail;
Expand Down Expand Up @@ -132,15 +134,124 @@ public void testInsertUpdateDelete_given_stopPersistingAdapter() {
assertThat(stopPersistingAdapter.methodsCalled).containsExactly("preDeleteById");
stopPersistingAdapter.methodsCalled.clear();

db.deleteAll(EBasicVer.class, Arrays.asList(22,23,24));
db.deleteAll(EBasicVer.class, Arrays.asList(22, 23, 24));
assertThat(stopPersistingAdapter.methodsCalled).hasSize(3);
assertThat(stopPersistingAdapter.methodsCalled).containsExactly("preDeleteById", "preDeleteById", "preDeleteById");
stopPersistingAdapter.methodsCalled.clear();

db.shutdown();
}

private Database getDatabase(PersistAdapter persistAdapter) {
@Test
public void testCascade() {
Database db = getDatabase(new BeanPersistAdapter() {
@Override
public boolean isRegisterFor(Class<?> cls) {
return UTMaster.class == cls;
}

@Override
public boolean preDelete(BeanPersistRequest<?> request) {
return false;
}
});
Integer id;
UTMaster master = new UTMaster();
master.addDetail(new UTDetail());
db.save(master);
id = master.getId();

master = db.find(UTMaster.class, id);
assertThat(master.getDetails()).hasSize(1);

try (Transaction txn = db.beginTransaction()) {
txn.setBatchMode(true);
db.delete(master);
txn.commit();
}

master = db.find(UTMaster.class, id);
assertThat(master).isNotNull();
// CHECKME: Deleting of master was denied by the PersistListener
// What about detail? Is this intended, that it will be deleted?
assertThat(master.getDetails()).hasSize(0);

}

@Test
public void testInsertUpdateDelete_with_LazyLoad() {

Database db = getDatabase(new BeanPersistAdapter() {

@Override
public boolean isRegisterFor(Class<?> cls) {
return EBasicVer.class == cls;
}

@Override
public boolean preInsert(BeanPersistRequest<?> request) {
assertThat(((EBasicVer) request.bean()).getDescription()).isEqualTo("MyDescription");
return true;
}

@Override
public boolean preUpdate(BeanPersistRequest<?> request) {
assertThat(((EBasicVer) request.bean()).getDescription()).isEqualTo("MyDescription");
return true;
}

@Override
public boolean preDelete(BeanPersistRequest<?> request) {
assertThat(((EBasicVer) request.bean()).getDescription()).isEqualTo("MyDescription");
return true;
}
});
Integer id;
try (Transaction txn = db.beginTransaction()) {
txn.setBatchMode(true);
EBasicVer bean = new EBasicVer("testController");
bean.setDescription("MyDescription");

db.save(bean);
txn.commit();
id = bean.getId();
}


try (Transaction txn = db.beginTransaction()) {
txn.setBatchMode(true);
EBasicVer bean = db.find(EBasicVer.class).setUseCache(false).select("name").setId(id).findOne();
bean.setName("otherName");

db.save(bean);

txn.commitAndContinue();

EBasicVer bean2 = db.find(EBasicVer.class).setUseCache(false).select("name").setId(id).findOne();
assertThat(bean2).isSameAs(bean);
}

try (Transaction txn = db.beginTransaction()) {
txn.setBatchMode(true);
EBasicVer bean = db.find(EBasicVer.class).setUseCache(false).select("name").setId(id).findOne();

db.delete(bean);
txn.commitAndContinue();
System.out.println(txn);
}
/*
db.update(bean);

db.delete(bean);

db.delete(EBasicVer.class, 22);

db.deleteAll(EBasicVer.class, Arrays.asList(22,23,24));
*/
db.shutdown();
}

private Database getDatabase(BeanPersistController persistAdapter) {
DatabaseBuilder config = new DatabaseConfig();
config.setName("h2ebasicver");
config.loadFromProperties();
Expand Down Expand Up @@ -194,12 +305,12 @@ public boolean preUpdate(BeanPersistRequest<?> request) {

Object bean = request.bean();
if (bean instanceof UTDetail) {
UTDetail detail = (UTDetail)bean;
UTDetail detail = (UTDetail) bean;
// invoke lazy loading ... which invoke the flush of the jdbc batch
detail.setQty(42);
}
if (bean instanceof UTMaster) {
UTMaster master = (UTMaster)bean;
UTMaster master = (UTMaster) bean;
UTMaster.Journal journal = master.getJournal();
if (journal == null) {
journal = new UTMaster.Journal();
Expand Down