Refactor move tests from ebean-core to ebean-test

This commit is contained in:
rbygrave committed 2021-09-08 22:49:23 +12:00
1 parent 0b00a14fd3
commit eab56d323b
1650 files changed
+185 -147

No files matched your search

@@ -0,0 +1,59 @@
package org.tests.update;
import io.ebean.annotation.Index;
import io.ebean.annotation.WhenModified;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.Size;
import java.time.Instant;
@Entity
@Table(name = "e_person_online")
public class EPersonOnline {
@Id
Long id;
@Index(unique = true)
@Size(max=127)
String email;
boolean onlineStatus;
@WhenModified
Instant whenUpdated;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean isOnlineStatus() {
return onlineStatus;
}
public void setOnlineStatus(boolean onlineStatus) {
this.onlineStatus = onlineStatus;
}
public Instant getWhenUpdated() {
return whenUpdated;
}
public void setWhenUpdated(Instant whenUpdated) {
this.whenUpdated = whenUpdated;
}
}
@@ -0,0 +1,63 @@
package org.tests.update;
import io.ebean.BaseTestCase;
import io.ebean.DB;
import org.tests.model.embedded.EEmbDatePeriod;
import org.tests.model.embedded.EEmbInner;
import org.tests.model.embedded.EEmbOuter;
import org.junit.jupiter.api.Test;
import java.util.Date;
import static org.assertj.core.api.Assertions.assertThat;
public class TestEmbeddedRefreshUpdate extends BaseTestCase {
@Test
public void test() {
EEmbOuter outer = new EEmbOuter();
outer.setNomeOuter("test");
EEmbDatePeriod embeddedBean = new EEmbDatePeriod();
embeddedBean.setDate1(new Date());
outer.setDatePeriod(embeddedBean);
DB.save(outer);
EEmbOuter loaded = DB.find(EEmbOuter.class).where().idEq(outer.getId()).findOne();
// if commented Ebean saves correctly
DB.refresh(loaded);
loaded.getDatePeriod().setDate2(new Date());
// BUG 343
DB.save(loaded);
// See BUG 344
DB.find(EEmbInner.class).fetch("outer").orderBy("outer.datePeriod.date1").findList();
}
@Test
public void test2() {
EEmbOuter outer = new EEmbOuter();
outer.setNomeOuter("test");
EEmbDatePeriod embeddedBean = new EEmbDatePeriod();
embeddedBean.setDate1(new Date());
outer.setDatePeriod(embeddedBean);
DB.save(outer);
assertThat(outer.getUpdateCount()).isEqualTo(1);
Date d = new Date();
d.setTime(1L);
outer.getDatePeriod().setDate1(d);
DB.save(outer);
assertThat(outer.getUpdateCount()).isEqualTo(2);
}
}
@@ -0,0 +1,63 @@
package org.tests.update;
import io.ebean.BaseTestCase;
import io.ebean.DB;
import io.ebean.text.json.JsonContext;
import io.ebean.text.json.JsonWriteOptions;
import org.tests.model.basic.UUOne;
import org.tests.model.basic.UUTwo;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestJsonStatelessUpdate extends BaseTestCase {
@Test
public void test() throws IOException {
UUOne one = new UUOne();
one.setName("oneName");
DB.save(one);
UUTwo two = new UUTwo();
two.setMaster(one);
two.setName("twoName");
DB.save(two);
UUTwo twoX = DB.find(UUTwo.class, two.getId());
JsonContext jsonContext = DB.json();
JsonWriteOptions writeOptions = JsonWriteOptions.parsePath("(id,name,master(*))");
String jsonString = jsonContext.toJson(twoX, writeOptions);
jsonString = jsonString.replace("twoName", "twoNameModified");
jsonString = jsonString.replace("oneName", "oneNameModified");
UUTwo two2 = jsonContext.toBean(UUTwo.class, jsonString);
assertEquals(twoX.getId(), two2.getId());
assertEquals("twoNameModified", two2.getName());
assertEquals("oneNameModified", two2.getMaster().getName());
// The update below cascades to also save "master" and that fails
// as it thinks it should INSERT master rather than UPDATE master
DB.update(two2);
awaitL2Cache();
// confirm the properties where updated as expected
UUTwo twoConfirm = DB.find(UUTwo.class, two.getId());
assertEquals("twoNameModified", twoConfirm.getName());
assertEquals("oneNameModified", twoConfirm.getMaster().getName());
}
}
@@ -0,0 +1,36 @@
package org.tests.update;
import io.ebean.BaseTestCase;
import io.ebean.DB;
import org.tests.model.basic.EBasicVer;
import org.junit.jupiter.api.Test;
import java.sql.Timestamp;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
public class TestMarkAsDirty extends BaseTestCase {
@Test
public void test() throws InterruptedException {
EBasicVer bean = new EBasicVer("markAsDirty");
DB.save(bean);
Timestamp lastUpdate = bean.getLastUpdate();
assertNotNull(lastUpdate);
Thread.sleep(100);
// ensure the update occurs and version property is updated/incremented
DB.markAsDirty(bean);
DB.save(bean);
Timestamp lastUpdate2 = bean.getLastUpdate();
assertNotNull(lastUpdate2);
assertNotEquals(lastUpdate, lastUpdate2);
}
}
@@ -0,0 +1,30 @@
package org.tests.update;
import io.ebean.BaseTestCase;
import org.junit.jupiter.api.Test;
public class TestPostgresTruncate extends BaseTestCase {
@Test
public void test() {
// Database server = DB.getDefault();
//
// EBasic e = new EBasic();
// e.setName("something");
// e.setStatus(Status.NEW);
// e.setDescription("wow");
//
// server.save(e);
//
// server.beginTransaction();
// Integer oriC =
// DB.sqlQuery("select count(*) as c from e_basic").findOne().getInteger("c");
// int rows = DB.sqlUpdate("truncate e_basic cascade").execute();
// Integer currentC =
// DB.sqlQuery("select count(*) as c from e_basic").findOne().getInteger("c");
// server.commitTransaction();
// //DB.cacheManager().clearAll();
// System.out.println("table : ori="+oriC+", delC="+rows+", currentC="+currentC);
}
}
@@ -0,0 +1,68 @@
package org.tests.update;
import io.ebean.BaseTestCase;
import io.ebean.DB;
import io.ebean.SqlUpdate;
import io.ebean.Transaction;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Testclass that ensures the correct behaviour of SqlUpdate in combination with batching.
*
* @author Jonas Pöhler, FOCONIS AG
*/
public class TestSqlUpdateBatch extends BaseTestCase {
/**
* This test ensures the correct behaviour of update batching in the {@code BatchedPstmtHolder} after a flush. Two batch updates
* are executed with each a batchsize of 21, which is the default limit for automatic flushing on {@code addBatch()}. After that
* the statements are each executed with {@code executeBatch()}. The desired behaviour is, that each execution succeeds although
* technically the batch was already flushed.
*/
@Test
public void testTwoParallelBatches() {
try (Transaction txn = DB.beginTransaction()) {
// Dummy updates, that effectively do nothing, but ebean doesn't need to know this.
final SqlUpdate update = DB.sqlUpdate("update uuone set name = ? where 0=1");
final SqlUpdate delete = DB.sqlUpdate("delete from uuone where ?=-1");
for (int i = 0; i < 20; i++) {
update
.setParameter(1, String.valueOf(i))
.addBatch();
delete
.setParameter(1, i)
.addBatch();
}
assertThat(delete.executeBatch().length).isEqualTo(20);
assertThat(update.executeBatch().length).isEqualTo(20);
txn.commit();
}
}
/**
* This test checks that for a batch update a correct array with update counts is returned. If a update with 40 entries is
* executed, it is expected, that {@code executeBatch()} returns a array with 40 elements each containing the update count for
* the given parameters.
*/
@Test
public void testBatchReturnArrayLength() {
try (Transaction txn = DB.beginTransaction()) {
// transaction batch size is ignored with addBatch()
txn.setBatchSize(10);
// Dummy update, that effectively does nothing, but ebean doesn't need to know this.
final SqlUpdate update = DB.sqlUpdate("update uuone set name = ? where 0=1");
for (int i = 0; i < 40; i++) {
update
.setParameter(1, String.valueOf(i))
.addBatch();
}
assertEquals(40, update.executeBatch().length);
}
}
}
@@ -0,0 +1,300 @@
package org.tests.update;
import io.ebean.BaseTestCase;
import io.ebean.DB;
import io.ebean.SqlUpdate;
import io.ebean.Transaction;
import org.ebeantest.LoggedSqlCollector;
import org.junit.jupiter.api.Test;
import java.util.List;
import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestSqlUpdateBindMultipleLists extends BaseTestCase {
@Test
public void test() {
LoggedSqlCollector.start();
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id in (:ids)");
sqlUpdate.setParameter("ids", asList(9991, 9992, 9993));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?,?)", sqlUpdate.getGeneratedSql());
// 3 parameters in the IN clause
sqlUpdate.setParameter("ids", asList(9991, 9992));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?)", sqlUpdate.getGeneratedSql());
List<String> sql = LoggedSqlCollector.stop();
assertThat(sql).hasSize(2);
}
@Test
public void positionParamsExpansion() {
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id in (?1)");
sqlUpdate.setParameter(1, asList(9991, 9992, 9993));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate = DB.sqlUpdate("delete from o_customer where id in (?1)");
sqlUpdate.setParameter(1, asList(9991, 9993));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate = DB.sqlUpdate("delete from o_customer where id in (?1)");
sqlUpdate.setParameter(1, asList(9993));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?)", sqlUpdate.getGeneratedSql());
}
@Test
public void positionParamsExpansion_withPrePost() {
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id > ? and id in (?2) and id < ?")
.setParameter(1, 90)
.setParameter(2, asList(9991, 9992, 9993))
.setParameter(3, 91);
sqlUpdate.execute();
assertEquals("delete from o_customer where id > ? and id in (?,?,?) and id < ?", sqlUpdate.getGeneratedSql());
}
@Test
public void positionParamsExpansion_withPrePost_2() {
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id > ? and id in (?2) and id < ?")
.setParameter(90)
.setParameter(asList(9991, 9992, 9993))
.setParameter(91);
sqlUpdate.execute();
assertEquals("delete from o_customer where id > ? and id in (?,?,?) and id < ?", sqlUpdate.getGeneratedSql());
}
@Test
public void positionParamsExpansion_withPrePost_usingParam() {
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id > ? and id in (?2) and id < ?")
.setParameters(90, asList(9991, 9992, 9993), 91);
sqlUpdate.execute();
assertEquals("delete from o_customer where id > ? and id in (?,?,?) and id < ?", sqlUpdate.getGeneratedSql());
}
@Test
public void positionParamsExpansion_withPre() {
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where name = ? and id in (?2)");
sqlUpdate.setParameter(1, "Foo");
sqlUpdate.setParameter(2, asList(9991, 9992, 9993));
sqlUpdate.execute();
assertEquals("delete from o_customer where name = ? and id in (?,?,?)", sqlUpdate.getGeneratedSql());
}
@Test
public void positionParamsExpansion_multi() {
SqlUpdate upd = DB.sqlUpdate("delete from o_customer where id in (?1) and name in (?2) and id not in (?3)");
try (Transaction transaction = DB.beginTransaction()) {
transaction.setBatchMode(true);
upd.setParameters(asList(9991), asList("Foo"), asList(9994));
upd.execute();
upd.setParameters(asList(9991, 9992), asList("Foo", "Bar"), asList(1,2,3,4));
upd.execute();
upd.setParameters(asList(9991), asList("Foo", "Bar", "Baz"), asList(1,2));
upd.execute();
transaction.commit();
}
}
@Test
public void positionParamsExpansion_withPost() {
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id in (?1) and name = ?");
sqlUpdate.setParameter(1, asList(9991, 9992, 9993));
sqlUpdate.setParameter(2, "Foo");
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?,?) and name = ?", sqlUpdate.getGeneratedSql());
}
@Test
public void positionParamsExpansion_withPost_andBatch_execute() {
SqlUpdate upd = DB.sqlUpdate("delete from o_customer where id in (?1) and name = ?");
try (Transaction transaction = DB.beginTransaction()) {
transaction.setBatchMode(true);
upd.setParameters(asList(9991, 9992, 9993), "Foo");
upd.execute();
upd.setParameters(asList(9991, 9992), "Bar");
upd.execute();
upd.setParameters(asList(9991, 9992, 9999), "Baz");
upd.execute();
transaction.commit();
}
}
@Test
public void positionParamsExpansion_withPost_addBatch_execute() {
SqlUpdate upd = DB.sqlUpdate("delete from o_customer where id in (?1) and name = ?");
try (Transaction transaction = DB.beginTransaction()) {
transaction.setBatchMode(true);
upd.setParameters(asList(9991, 9992, 9993), "Foo");
upd.addBatch();
upd.setParameters(asList(9991, 9992), "Bar");
upd.addBatch();
upd.setParameters(asList(9991, 9992, 9999), "Baz");
upd.addBatch();
transaction.commit();
}
}
@Test
public void test_multipleLists_asPositioned() {
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id in (?1) and name in (?2)");
try (Transaction transaction = DB.beginTransaction()) {
sqlUpdate.setParameter(1, asList(9991, 9992, 9993));
sqlUpdate.setParameter(2, asList("rob", "jim"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?,?) and name in (?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameters(asList(9991, 9992), asList("rob", "jim", "sd"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?) and name in (?,?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameter(1, asList(9991, 9992));
sqlUpdate.setParameter(2, asList("rob", "jim"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?) and name in (?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameters(asList(9991), asList("rob", "jim"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?) and name in (?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameters(asList(9992), asList("ro3b", "j3im"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?) and name in (?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameter(1, asList(9992, 4545));
sqlUpdate.setParameter(2, asList("ro3b"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?) and name in (?)", sqlUpdate.getGeneratedSql());
transaction.commit();
}
}
@Test
public void test_multipleLists_asPositioned_withBatch() {
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id in (?1) and name in (?2)");
try (Transaction transaction = DB.beginTransaction()) {
transaction.setBatchMode(true);
sqlUpdate.setParameter(1, asList(9991, 9992, 9993));
sqlUpdate.setParameter(2, asList("rob", "jim"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?,?) and name in (?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameters(asList(9991, 9992), asList("rob", "jim", "sd"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?) and name in (?,?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameter(1, asList(9991, 9992));
sqlUpdate.setParameter(2, asList("rob", "jim"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?) and name in (?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameters(asList(9991), asList("rob", "jim"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?) and name in (?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameters(asList(9992), asList("ro3b", "j3im"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?) and name in (?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameter(1, asList(9992, 4545));
sqlUpdate.setParameter(2, asList("ro3b"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?) and name in (?)", sqlUpdate.getGeneratedSql());
transaction.commit();
}
}
@Test
public void test_multipleLists() {
SqlUpdate sqlUpdate = DB.sqlUpdate("delete from o_customer where id in (:ids) and name in (:names)");
sqlUpdate.setParameter("ids", asList(9991, 9992, 9993));
sqlUpdate.setParameter("names", asList("rob", "jim"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?,?) and name in (?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameter("ids", asList(9991, 9992));
sqlUpdate.setParameter("names", asList("rob", "jim", "sd"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?) and name in (?,?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameter("ids", asList(9991, 9992));
sqlUpdate.setParameter("names", asList("rob", "jim"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?) and name in (?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameter("ids", asList(9991));
sqlUpdate.setParameter("names", asList("rob", "jim"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?) and name in (?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameter("ids", asList(9992));
sqlUpdate.setParameter("names", asList("ro3b", "j3im"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?) and name in (?,?)", sqlUpdate.getGeneratedSql());
sqlUpdate.setParameter("ids", asList(9992, 4545));
sqlUpdate.setParameter("names", asList("ro3b"));
sqlUpdate.execute();
assertEquals("delete from o_customer where id in (?,?) and name in (?)", sqlUpdate.getGeneratedSql());
}
}
@@ -0,0 +1,111 @@
package org.tests.update;
import io.ebean.BaseTestCase;
import io.ebean.DB;
import io.ebean.DuplicateKeyException;
import io.ebean.SqlUpdate;
import io.ebean.Transaction;
import org.junit.jupiter.api.Test;
import java.util.UUID;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
public class TestSqlUpdateExceptions extends BaseTestCase {
private String sql = "insert into uuone (id, name, version) values (?,?,?)";
@Test
public void simpleInsert() {
UUID id = UUID.randomUUID();
DB.sqlUpdate(sql)
.setParameters(id, "hi", 1)
.executeNow();
UUID foundId = DB.sqlQuery("select id from uuone where id = ?")
.setParameters(id)
.mapToScalar(UUID.class)
.findOne();
assertThat(foundId).isEqualTo(id);
}
@Test
public void duplicateKey() {
UUID id = UUID.randomUUID();
SqlUpdate sqlUpdate = DB.sqlUpdate(sql);
sqlUpdate.setParameter(1, id);
sqlUpdate.setParameter(2, "hi");
sqlUpdate.setParameter(3, 1);
sqlUpdate.execute();
sqlUpdate.setParameter(1, id);
sqlUpdate.setParameter(2, "fail");
sqlUpdate.setParameter(3, 1);
assertThrows(DuplicateKeyException.class, sqlUpdate::execute);
}
@Test
public void duplicateKey_executeNow() {
UUID id = UUID.randomUUID();
SqlUpdate sqlUpdate = DB.sqlUpdate(sql);
sqlUpdate.setParameter(1, id);
sqlUpdate.setParameter(2, "hi");
sqlUpdate.setParameter(3, 1);
sqlUpdate.executeNow();
sqlUpdate.setParameter(1, id);
sqlUpdate.setParameter(2, "fail");
sqlUpdate.setParameter(3, 1);
assertThrows(DuplicateKeyException.class, sqlUpdate::executeNow);
}
@Test
public void duplicateKey_inBatch() {
UUID id = UUID.randomUUID();
assertThrows(DuplicateKeyException.class, () -> {
try (Transaction transaction = DB.beginTransaction()) {
SqlUpdate sqlUpdate = DB.sqlUpdate(sql);
sqlUpdate.setParameter(1, id);
sqlUpdate.setParameter(2, "hi in batch");
sqlUpdate.setParameter(3, 1);
sqlUpdate.addBatch();
sqlUpdate.setParameter(1, id);
sqlUpdate.setParameter(2, "fail in batch");
sqlUpdate.setParameter(3, 1);
sqlUpdate.addBatch();
transaction.commit();
}
});
}
@Test
public void duplicateKey_executeBatch() {
UUID id = UUID.randomUUID();
assertThrows(DuplicateKeyException.class, () -> {
try (Transaction transaction = DB.beginTransaction()) {
SqlUpdate sqlUpdate = DB.sqlUpdate(sql);
sqlUpdate.setParameter(1, id);
sqlUpdate.setParameter(2, "hi in batch");
sqlUpdate.setParameter(3, 1);
sqlUpdate.addBatch();
sqlUpdate.setParameter(1, id);
sqlUpdate.setParameter(2, "fail in batch");
sqlUpdate.setParameter(3, 1);
sqlUpdate.addBatch();
sqlUpdate.executeBatch();
transaction.commit();
}
});
}
}
@@ -0,0 +1,202 @@
package org.tests.update;
import io.ebean.BaseTestCase;
import io.ebean.DB;
import io.ebean.SqlUpdate;
import io.ebean.Transaction;
import io.ebean.meta.MetaTimedMetric;
import org.ebeantest.LoggedSqlCollector;
import org.junit.jupiter.api.Test;
import org.tests.idkeys.db.AuditLog;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestSqlUpdateInTxn extends BaseTestCase {
@Test
public void testSqlTrim() {
String sql = " this\nis\ntrimmed ";
SqlUpdate sqlUpdate = DB.sqlUpdate(sql);
assertThat(sqlUpdate.getSql()).isEqualTo(sql.trim());
}
@Test
public void test_twoWordSql() {
if (isH2()) {
// 2 word syntax ... means no automatic determination of the type of change
// and table effected (so no automatic L2 cache invalidation)
String sql = "CHECKPOINT SYNC";
SqlUpdate sqlUpdate = DB.sqlUpdate(sql);
sqlUpdate.execute();
assertThat(sqlUpdate.getSql()).isEqualTo(sql.trim());
}
}
@Test
public void testExecute_inTransaction_withBatch() {
LoggedSqlCollector.start();
try (Transaction transaction = DB.beginTransaction()) {
transaction.setBatchMode(true);
SqlUpdate sqlUpdate = DB.sqlUpdate("update audit_log set description = description where id = ?")
.setParameter(1, 999999);
int row = sqlUpdate.execute();
// update statement using JDBC batch so not executed yet
assertThat(row).isEqualTo(-1);
sqlUpdate.setParameter(1, 999998);
sqlUpdate.execute();
transaction.commit();
}
List<String> sql = LoggedSqlCollector.stop();
assertThat(sql).hasSize(3);
assertSql(sql.get(0)).contains("update audit_log set description = description where id = ?");
assertSqlBind(sql, 1, 2);
}
@Test
public void testExecute_inTransaction_withoutBatch() {
LoggedSqlCollector.start();
try (Transaction transaction = DB.beginTransaction()) {
transaction.setBatchMode(false);
SqlUpdate sqlUpdate = DB.sqlUpdate("update audit_log set description = description where id = ?")
.setParameter(1, 999999);
int row0 = sqlUpdate.execute();
assertThat(row0).isEqualTo(0);
sqlUpdate.setParameter(1, 999998);
int row1 = sqlUpdate.execute();
assertThat(row1).isEqualTo(0);
transaction.commit();
}
List<String> sql = LoggedSqlCollector.stop();
assertThat(sql).hasSize(2);
assertSql(sql.get(0)).contains("update audit_log set description = description where id = ?; -- bind(999999)");
assertSql(sql.get(1)).contains("update audit_log set description = description where id = ?; -- bind(999998)");
}
@Test
public void testExecuteNow_inTransaction_withBatch() {
try (Transaction transaction = DB.beginTransaction()) {
transaction.setBatchMode(true);
int row = DB.sqlUpdate("update audit_log set description = description where id = ?")
.setParameter(1, 999999)
.executeNow();
// update statement executed even though JDBC batch mode is on
assertThat(row).isEqualTo(0);
transaction.commit();
}
}
@Test
public void testSqlUpdateWithWhitespace() {
String sql = " \nupdate audit_log \nset description = description \nwhere id = id";
resetAllMetrics();
SqlUpdate sqlUpdate = DB.sqlUpdate(sql).setLabel("auditLargeUpdate");
sqlUpdate.execute();
assertThat(sqlUpdate.getSql()).isEqualTo(sql.trim());
assertThat(sqlUpdate.getGeneratedSql()).isEqualTo(sql.trim());
List<MetaTimedMetric> sqlMetrics = sqlMetrics();
assertThat(sqlMetrics).hasSize(1);
assertThat(sqlMetrics.get(0).name()).isEqualTo("sql.update.auditLargeUpdate");
assertThat(sqlMetrics.get(0).count()).isEqualTo(1);
}
@Test
public void testBasic() {
AuditLog otherLog = new AuditLog();
otherLog.setDescription("foo");
DB.save(otherLog);
AuditLog log = new AuditLog();
log.setDescription("foo");
DB.save(log);
AuditLog log2 = DB.find(AuditLog.class, log.getId());
assertEquals("foo", log2.getDescription());
final Long id = log2.getId();
final String updateDml = "update audit_log set description = :desc where id = :id";
final String updateModDml = "update audit_log set modified_description = :desc";
SqlUpdate sqlUpdate = DB.sqlUpdate(updateDml);
sqlUpdate.setParameter("desc", "foo2");
sqlUpdate.setParameter("id", id);
sqlUpdate.execute();
SqlUpdate updateMod = DB.sqlUpdate(updateModDml);
updateMod.setParameter("desc", "mod0");
updateMod.execute();
AuditLog log3 = DB.find(AuditLog.class, log.getId());
assertEquals("foo2", log3.getDescription());
assertEquals("mod0", log3.getModifiedDescription());
DB.execute(() -> {
SqlUpdate update = DB.sqlUpdate(updateDml);
update.setParameter("desc", "foo3");
update.setParameter("id", id);
update.execute();
SqlUpdate updateMod1 = DB.sqlUpdate(updateModDml);
updateMod1.setParameter("desc", "mod1");
updateMod1.execute();
});
AuditLog log4 = DB.find(AuditLog.class, log.getId());
assertEquals("foo3", log4.getDescription());
assertEquals("mod1", log4.getModifiedDescription());
DB.beginTransaction();
try {
SqlUpdate update = DB.sqlUpdate(updateDml);
update.setParameter("desc", "foo4");
update.setParameter("id", id);
update.execute();
updateMod = DB.sqlUpdate(updateModDml);
updateMod.setParameter("desc", "mod2");
updateMod.execute();
DB.commitTransaction();
} finally {
DB.endTransaction();
}
AuditLog log5 = DB.find(AuditLog.class, log.getId());
assertEquals("foo4", log5.getDescription());
assertEquals("mod2", log5.getModifiedDescription());
}
}
@@ -0,0 +1,130 @@
package org.tests.update;
import io.ebean.BaseTestCase;
import io.ebean.DB;
import io.ebean.DB;
import io.ebean.SqlUpdate;
import io.ebean.annotation.ForPlatform;
import io.ebean.annotation.Platform;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
public class TestSqlUpdateUpsert extends BaseTestCase {
@ForPlatform(Platform.H2)
@Test
public void h2Merge() throws InterruptedException {
String sql = "merge into e_person_online (email, online_status, when_updated) key(email) values (?, ?, now())";
String email = "baz@one.com";
Object key = DB.sqlUpdate(sql)
.setGetGeneratedKeys(true)
.setParameter(email)
.setParameter(true)
.executeGetKey();
EPersonOnline found = DB.find(EPersonOnline.class, key);
assertThat(found).isNotNull();
assertThat(found.getEmail()).isEqualTo(email);
assertThat(found.isOnlineStatus()).isTrue();
Thread.sleep(50); // have to wait some millis here
String sqlNamed = "merge into e_person_online (email, online_status, when_updated) key(email) values (:email, :online, now())";
SqlUpdate sqlUpdate2 = DB.sqlUpdate(sqlNamed)
.setGetGeneratedKeys(true)
.setParameter("email", email)
.setParameter("online", false);
Object key2 = sqlUpdate2.executeGetKey();
assertThat(key2).isNull();
EPersonOnline found2 = DB.find(EPersonOnline.class).where().eq("email", email).findOne();
assertThat(found2).isNotNull();
assertThat(found2.getId()).isEqualTo(key);
assertThat(found2.getEmail()).isEqualTo(email);
assertThat(found2.isOnlineStatus()).isFalse();
assertThat(found2.getWhenUpdated()).isAfter(found.getWhenUpdated()); // otherwise this test fails on my machine
}
@ForPlatform(Platform.POSTGRES)
@Test
public void postgresUpsert() {
String sql = "insert into e_person_online (email, online_status, when_updated) values (?, ?, now()) on conflict (email) do update set when_updated=now(), online_status = ?";
String email = "foo@one.com";
Object key = DB.sqlUpdate(sql)
.setGetGeneratedKeys(true)
.setParameter(1, email)
.setParameter(2, true)
.setParameter(3, true)
.executeGetKey();
EPersonOnline found = DB.find(EPersonOnline.class, key);
assertThat(found).isNotNull();
assertThat(found.getEmail()).isEqualTo("foo@one.com");
assertThat(found.isOnlineStatus()).isTrue();
String sqlNamed = "insert into e_person_online (email, online_status, when_updated) values (:email, :online, now()) on conflict (email) do update set when_updated=now(), online_status = :online";
SqlUpdate sqlUpdate2 = DB.sqlUpdate(sqlNamed)
.setGetGeneratedKeys(true)
.setParameter("email", email)
.setParameter("online", false);
Object key2 = sqlUpdate2.executeGetKey();
EPersonOnline found2 = DB.find(EPersonOnline.class, key2);
assertThat(found2).isNotNull();
assertThat(found2.getId()).isEqualTo(key);
assertThat(found2.getEmail()).isEqualTo("foo@one.com");
assertThat(found2.isOnlineStatus()).isFalse();
assertThat(found2.getWhenUpdated()).isAfter(found.getWhenUpdated());
}
@ForPlatform(Platform.MYSQL)
@Test
public void mySqlUpsert() {
String email = "bar@one.com";
String sql = "insert into e_person_online (email, online_status, when_updated) values (?, ?, current_time) on duplicate key update when_updated=current_time, online_status = ?";
SqlUpdate sqlUpdate = DB.sqlUpdate(sql)
.setGetGeneratedKeys(true)
.setParameter(1, email)
.setParameter(2, true)
.setParameter(3, true);
Object key = sqlUpdate.executeGetKey();
assertThat(key).isNotNull();
EPersonOnline found = DB.find(EPersonOnline.class, key);
assertThat(found).isNotNull();
assertThat(found.getEmail()).isEqualTo("bar@one.com");
assertThat(found.isOnlineStatus()).isTrue();
String sqlNamed = "insert into e_person_online (email, online_status, when_updated) values (:email, :online, current_time) on duplicate key update when_updated=current_time, online_status = :online";
SqlUpdate sqlUpdate2 = DB.sqlUpdate(sqlNamed)
.setGetGeneratedKeys(true)
.setParameter("email", email)
.setParameter("online", false);
sqlUpdate2.execute();
Object key2 = sqlUpdate2.getGeneratedKey();
EPersonOnline found2 = DB.find(EPersonOnline.class, key2);
assertThat(found2).isNotNull();
assertThat(found2.getId().toString()).isEqualTo(key.toString());
assertThat(found2.getEmail()).isEqualTo("bar@one.com");
assertThat(found2.isOnlineStatus()).isFalse();
}
}
@@ -0,0 +1,425 @@
package org.tests.update;
import io.ebean.DB;
import io.ebean.TransactionalTestCase;
import io.ebeantest.LoggedSql;
import org.junit.jupiter.api.Test;
import org.tests.model.basic.Contact;
import org.tests.model.basic.Customer;
import org.tests.model.basic.EBasic;
import org.tests.model.basic.EBasic.Status;
import javax.persistence.EntityNotFoundException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
public class TestStatelessUpdate extends TransactionalTestCase {
@Test
public void test() {
EBasic e = new EBasic();
e.setName("something");
e.setStatus(Status.NEW);
e.setDescription("wow");
DB.save(e);
// confirm saved as expected
EBasic original = DB.find(EBasic.class, e.getId());
assertEquals(e.getId(), original.getId());
assertEquals(e.getName(), original.getName());
assertEquals(e.getStatus(), original.getStatus());
assertEquals(e.getDescription(), original.getDescription());
// test updating just the name
EBasic updateNameOnly = new EBasic();
updateNameOnly.setId(e.getId());
updateNameOnly.setName("updateNameOnly");
LoggedSql.start();
DB.update(updateNameOnly);
List<String> sql = LoggedSql.collect();
original = DB.find(EBasic.class, e.getId());
assertEquals(e.getStatus(), original.getStatus());
assertEquals(e.getDescription(), original.getDescription());
assertEquals(updateNameOnly.getName(), original.getName());
assertThat(sql).hasSize(1);
assertThat(sql.get(0)).contains("update e_basic set name=? where id=?; -- bind(updateNameOnly");
LoggedSql.collect();
// test setting null
EBasic updateWithNull = new EBasic();
updateWithNull.setId(e.getId());
updateWithNull.setName("updateWithNull");
updateWithNull.setDescription(null);
DB.update(updateWithNull);
sql = LoggedSql.stop();
// name and description changed (using null)
original = DB.find(EBasic.class, e.getId());
assertEquals(e.getStatus(), original.getStatus());
assertEquals(updateWithNull.getName(), original.getName());
assertNull(original.getDescription());
assertThat(sql).hasSize(1);
assertThat(sql.get(0)).contains("update e_basic set name=?, description=? where id=?; -- bind(updateWithNull,null,");
}
@Test
public void update_NoRowsUpdated_expect_EntityNotFoundException() {
EBasic basic = new EBasic();
basic.setId(999999999);
basic.setName("something");
basic.setStatus(Status.ACTIVE);
assertThrows(EntityNotFoundException.class, () -> DB.update(basic));
}
@Test
public void delete_NoRowsDeleted_expect_false() {
EBasic basic = new EBasic();
basic.setId(999999999);
basic.setName("something");
basic.setStatus(Status.ACTIVE);
assertThat(DB.delete(basic)).isFalse();
}
/**
* I am expecting that Ebean detects there aren't any changes and don't execute any query.
* Currently a {@link javax.persistence.PersistenceException} with message 'Invalid value "null" for parameter "SQL"' is thrown.
*/
@Test
public void testWithoutChangesAndIgnoreNullValues() {
// arrange
EBasic basic = new EBasic();
basic.setName("something");
basic.setStatus(Status.NEW);
basic.setDescription("wow");
DB.save(basic);
LoggedSql.start();
// act
EBasic basicWithoutChanges = new EBasic();
basicWithoutChanges.setId(basic.getId());
DB.update(basicWithoutChanges);
// assert no update executed
final List<String> sql = LoggedSql.stop();
assertThat(sql).isEmpty();
}
/**
* Nice to have:
* <br />
* Assuming we have a Version column, it will always be generated an Update despite we have nothing to update.
* It would be nice that this would be recognized and no update would happen.
* <br />
* <br />
* This feature already works for normal Updates!
* <br />
* see: {@link org.tests.update.TestUpdatePartial#testWithoutChangesAndVersionColumn()}
*/
@Test
public void testWithoutChangesAndVersionColumnAndIgnoreNullValues() {
// arrange
Customer customer = new Customer();
customer.setName("something");
DB.save(customer);
LoggedSql.start();
// act
Customer customerWithoutChanges = new Customer();
customerWithoutChanges.setId(customer.getId());
DB.update(customerWithoutChanges);
final List<String> sql = LoggedSql.stop();
Customer result = DB.find(Customer.class, customer.getId());
assertThat(result.getUpdtime()).isEqualToIgnoringMillis(customer.getUpdtime());
assertThat(sql).isEmpty();
}
/**
* Many relations mustn't be deleted when they are not loaded.
*/
@Test
public void testStatelessUpdateIgnoreNullCollection() {
// arrange
Contact contact = new Contact();
contact.setFirstName("wobu :P");
Customer customer = new Customer();
customer.setName("something");
customer.setContacts(new ArrayList<>());
customer.getContacts().add(contact);
DB.save(customer);
// act
Customer customerWithChange = new Customer();
customerWithChange.setId(customer.getId());
customerWithChange.setName("new name");
// contacts is not loaded
assertFalse(containsContacts(customerWithChange));
LoggedSql.start();
DB.update(customerWithChange);
final List<String> sql = LoggedSql.stop();
Customer result = DB.find(Customer.class, customer.getId());
// assert null list was ignored (missing children not deleted)
assertNotNull(result.getContacts());
assertFalse(result.getContacts().isEmpty());
assertThat(sql).hasSize(1);
assertThat(sql.get(0)).contains("update o_customer set name=?, updtime=? where id=?;");
}
/**
* When BeanCollection is inadvertantly initialised and empty then ignore it
* Specifically a non-BeanCollection (like ArrayList) is not ignored in terms
* of deleting missing children.
*/
@Test
public void testStatelessUpdateIgnoreEmptyBeanCollection() {
// arrange
Contact contact = new Contact();
contact.setFirstName("wobu :P");
Customer customer = new Customer();
customer.setName("something");
customer.setContacts(new ArrayList<>());
customer.getContacts().add(contact);
DB.save(customer);
// act
Customer customerWithChange = new Customer();
customerWithChange.setId(customer.getId());
customerWithChange.setName("new name");
// with Ebean enhancement this loads the an empty contacts BeanList
customerWithChange.getContacts();
// contacts has been initialised to empty BeanList
assertTrue(containsContacts(customerWithChange));
LoggedSql.start();
DB.update(customerWithChange);
final List<String> sql = LoggedSql.stop();
Customer result = DB.find(Customer.class, customer.getId());
// assert empty bean list was ignore (missing children not deleted)
assertNotNull(result.getContacts());
assertFalse(result.getContacts().isEmpty());
assertThat(sql).hasSize(1);
assertThat(sql.get(0)).contains("update o_customer set name=?, updtime=? where id=?;");
}
@Test
public void testStatelessUpdateDeleteChildrenForNonBeanCollection() {
// arrange
Contact contact = new Contact();
contact.setFirstName("wobu :P");
Customer customer = new Customer();
customer.setName("something");
customer.setContacts(new ArrayList<>());
customer.getContacts().add(contact);
DB.save(customer);
// act
Customer customerWithChange = new Customer();
customerWithChange.setId(customer.getId());
customerWithChange.setName("new name");
// with Ebean enhancement this loads the an empty contacts BeanList
customerWithChange.setContacts(Collections.<Contact>emptyList());
assertTrue(containsContacts(customerWithChange));
LoggedSql.start();
DB.update(customerWithChange);
final List<String> sql = LoggedSql.stop();
Customer result = DB.find(Customer.class, customer.getId());
// assert empty bean list was ignore (missing children not deleted)
assertThat(result.getContacts()).hasSize(1);
assertThat(sql).hasSize(1);
assertThat(sql.get(0)).contains("update o_customer set name=?, updtime=? where id=?;");
}
private boolean containsContacts(Customer cust) {
return DB.beanState(cust).loadedProps().contains("contacts");
}
/**
* when using stateless updates with recursive calls,
* the version column shouldn't decide to use insert instead of update,
* although an ID has been set.
*/
@Test
public void testStatelessRecursiveUpdateWithVersionField() {
// arrange
Contact contact1 = new Contact();
contact1.setLastName("contact1");
Contact contact2 = new Contact();
contact2.setLastName("contact2");
Customer customer = new Customer();
customer.setName("something");
customer.getContacts().add(contact1);
customer.getContacts().add(contact2);
DB.save(customer);
// act
Contact updateContact1 = new Contact();
updateContact1.setId(contact1.getId());
Contact updateContact2 = new Contact();
updateContact2.setId(contact2.getId());
Customer updateCustomer = new Customer();
updateCustomer.setId(customer.getId());
updateCustomer.getContacts().add(updateContact1);
updateCustomer.getContacts().add(updateContact2);
LoggedSql.start();
DB.update(updateCustomer);
final List<String> sql = LoggedSql.stop();
// assert
assertThat(sql).hasSize(1);
assertThat(sql.get(0)).contains("update o_customer set updtime=? where id=?;");
}
@Test
public void testStatelessRecursiveUpdateWithChangesInDetailOnly() {
// arrange
Contact contact1 = new Contact();
contact1.setLastName("contact1");
Contact contact2 = new Contact();
contact2.setLastName("contact2");
Customer customer = new Customer();
customer.setName("something");
customer.getContacts().add(contact1);
customer.getContacts().add(contact2);
DB.save(customer);
// act
Contact updateContact1 = new Contact();
updateContact1.setId(contact1.getId());
updateContact1.setLastName("contact1-changed");
Contact updateContact3 = new Contact();
updateContact3.setLastName("contact3-added");
Customer updateCustomer = new Customer();
updateCustomer.setId(customer.getId());
updateCustomer.getContacts().add(updateContact1);
updateCustomer.getContacts().add(updateContact3);
LoggedSql.start();
DB.update(updateCustomer);
final List<String> sql = LoggedSql.stop();
assertThat(sql).hasSize(5);
assertThat(sql.get(0)).contains("update o_customer set updtime=? where id=?");
assertThat(sql.get(1)).contains("insert into contact");
assertThat(sql.get(2)).contains(" -- bind(");
assertThat(sql.get(3)).contains("update contact set last_name=?, customer_id=? where id=?");
assertThat(sql.get(4)).contains(" -- bind(");
// assert
Customer assCustomer = DB.find(Customer.class, customer.getId());
List<Contact> assContacts = assCustomer.getContacts();
assertThat(assContacts).hasSize(3);
Set<Integer> ids = new LinkedHashSet<>();
Set<String> names = new LinkedHashSet<>();
for (Contact contact : assContacts) {
ids.add(contact.getId());
names.add(contact.getLastName());
}
assertThat(ids).contains(contact1.getId(), updateContact3.getId(), contact2.getId());
assertThat(names).contains(updateContact1.getLastName(), updateContact3.getLastName());
}
@Test
public void testStatelessRecursiveUpdateWithChangesInDetailOnlyAnd() {
// arrange
Contact contact1 = new Contact();
contact1.setLastName("contact1");
Contact contact2 = new Contact();
contact2.setLastName("contact2");
Customer customer = new Customer();
customer.setName("something");
customer.getContacts().add(contact1);
customer.getContacts().add(contact2);
DB.save(customer);
// act
Contact updateContact1 = new Contact();
updateContact1.setId(contact1.getId());
updateContact1.setLastName("contact1-changed");
Contact updateContact3 = new Contact();
updateContact3.setLastName("contact3-added");
Customer updateCustomer = new Customer();
updateCustomer.setId(customer.getId());
updateCustomer.getContacts().add(updateContact1);
updateCustomer.getContacts().add(updateContact3);
// not adding contact2 but it won't be deleted in this case
LoggedSql.start();
DB.update(updateCustomer);
final List<String> sql = LoggedSql.stop();
assertThat(sql).hasSize(5);
assertThat(sql.get(0)).contains("update o_customer set updtime=? where id=?");
assertThat(sql.get(1)).contains("insert into contact");
assertThat(sql.get(2)).contains(" -- bind(");
assertThat(sql.get(3)).contains("update contact set last_name=?, customer_id=? where id=?");
assertThat(sql.get(4)).contains(" -- bind(");
// assert
Customer assCustomer = DB.find(Customer.class, customer.getId());
List<Contact> assContacts = assCustomer.getContacts();
// contact 2 was not deleted this time
assertEquals(3, assContacts.size());
Set<Integer> ids = new LinkedHashSet<>();
Set<String> names = new LinkedHashSet<>();
for (Contact contact : assContacts) {
ids.add(contact.getId());
names.add(contact.getLastName());
}
assertThat(ids).contains(contact1.getId(), updateContact3.getId(), contact2.getId());
assertThat(names).contains(updateContact1.getLastName(), contact2.getLastName(), updateContact3.getLastName());
}
}
@@ -0,0 +1,102 @@
package org.tests.update;
import io.ebean.BaseTestCase;
import io.ebean.DB;
import io.ebean.Database;
import io.ebean.Transaction;
import org.ebeantest.LoggedSqlCollector;
import org.junit.jupiter.api.Test;
import org.tests.model.basic.EBasicVer;
import java.util.ArrayList;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestUpdateAllLoadedProperties extends BaseTestCase {
@Test
public void test() {
EBasicVer basic1 = new EBasicVer("basic1");
basic1.setDescription("aaa");
DB.save(basic1);
EBasicVer basic2 = new EBasicVer("basic2");
basic1.setDescription("bbb");
DB.save(basic2);
Database server = DB.getDefault();
try (Transaction txn = server.beginTransaction()) {
txn.setUpdateAllLoadedProperties(true);
LoggedSqlCollector.start();
basic2.setDescription("bbb-mod");
server.save(basic2, txn);
basic1.setName("basic1-mod");
basic1.setDescription("aaa-mod");
server.save(basic1, txn);
txn.commit();
List<String> loggedSql = LoggedSqlCollector.stop();
assertEquals(2, loggedSql.size());
// all properties in the bean
assertThat(loggedSql.get(0)).contains("update e_basicver set name=?, description=?, other=?, last_update=? where id=? and last_update=?; -- bind(");
assertThat(loggedSql.get(1)).contains("update e_basicver set name=?, description=?, other=?, last_update=? where id=? and last_update=?; -- bind(");
}
testPartiallyLoaded(basic1.getId(), basic2.getId());
}
private void testPartiallyLoaded(Integer id1, Integer id2) {
List<Integer> ids = new ArrayList<>();
ids.add(id1);
ids.add(id2);
List<EBasicVer> beans = DB.find(EBasicVer.class)
.select("name, other")
.where().idIn(ids)
.order().asc("id")
.findList();
assertEquals(2, beans.size());
LoggedSqlCollector.start();
Transaction txn = DB.beginTransaction();
try {
txn.setUpdateAllLoadedProperties(true);
EBasicVer basic1 = beans.get(0);
basic1.setName("jim");
DB.save(basic1);
EBasicVer basic2 = beans.get(1);
basic2.setName("john");
basic2.setOther("otherDesc");
DB.save(basic2);
txn.commit();
} finally {
txn.end();
}
List<String> loggedSql = LoggedSqlCollector.stop();
assertThat(loggedSql).hasSize(2);
assertThat(loggedSql.get(0)).contains("update e_basicver set name=?, other=? where id=?; -- bind(");
assertThat(loggedSql.get(1)).contains("update e_basicver set name=?, other=? where id=?; -- bind(");
}
}
@@ -0,0 +1,93 @@
package org.tests.update;
import io.ebean.BaseTestCase;
import io.ebean.DB;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.tests.update.objects.Child;
import org.tests.update.objects.Parent;
import org.tests.update.objects.SiblingA;
import org.tests.update.objects.SiblingB;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestUpdateCircularSave extends BaseTestCase {
@Test
public void testCircularCascade() {
long aId = createA();
modifyPropertyToTrue(aId);
SiblingA siblingA = DB.find(SiblingA.class, aId);
assert siblingA != null;
assertTrue(siblingA.getSiblingB().isTestProperty());
}
private void modifyPropertyToTrue(long aId) {
SiblingA siblingA = DB.find(SiblingA.class, aId);
assert siblingA != null;
final SiblingB siblingB = siblingA.getSiblingB();
siblingB.setTestProperty(true);
// Will get optimistic lock as version is increased twice on B
DB.save(siblingB);
}
private long createA() {
SiblingA siblingA = new SiblingA();
SiblingB siblingB = new SiblingB();
siblingA.setSiblingB(siblingB);
DB.save(siblingA);
return siblingA.getId();
}
@Disabled
@Test
public void testFetchChildModifyChildSaveParent() {
long childId = createParentAndChild().getChild().getId();
Child child = DB.find(Child.class, childId);
assert child != null;
child.setTestProperty(true);
final Parent parent = child.getParent();
DB.save(parent);
assertChildModified(childId);
}
private void assertChildModified(long childId) {
Parent parent = DB.find(Parent.class, childId);
assert parent != null;
// Fails here because D was not saved even though C has cascade = ALL
assertTrue(parent.getChild().isTestProperty());
assertEquals(parent.getChild().getVersion(), 2L);
}
private Parent createParentAndChild() {
Parent parent = new Parent();
Child child = new Child();
parent.setChild(child);
DB.save(parent);
return parent;
}
@Test
public void testFetchParentModifyChildSaveParent() {
long parentId = createParentAndChild().getId();
Parent parent = DB.find(Parent.class, parentId);
assert parent != null;
parent.getChild().setTestProperty(true);
DB.save(parent);
assertChildModified(parent.getChild().getId());
}
}
@@ -0,0 +1,82 @@
package org.tests.update;
import io.ebean.BaseTestCase;
import io.ebean.DB;
import io.ebean.DB;
import io.ebean.SqlRow;
import org.junit.jupiter.api.Test;
import org.tests.model.basic.Customer;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class TestUpdatePartial extends BaseTestCase {
@Test
public void test() {
Customer c = new Customer();
c.setName("TestUpdateMe");
c.setStatus(Customer.Status.ACTIVE);
c.setSmallnote("a note");
DB.save(c);
checkDbStatusValue(c.getId(), "A");
Customer c2 = DB.find(Customer.class)
.setUseCache(false)
.select("status, smallnote")
.setId(c.getId())
.findOne();
c2.setStatus(Customer.Status.INACTIVE);
c2.setSmallnote("2nd note");
DB.save(c2);
checkDbStatusValue(c.getId(), "I");
Customer c3 = DB.find(Customer.class)
.setUseCache(false)
.select("status")
.setId(c.getId())
.findOne();
c3.setStatus(Customer.Status.NEW);
c3.setSmallnote("3rd note");
DB.save(c3);
checkDbStatusValue(c.getId(), "N");
// cleanup
DB.delete(Customer.class, c.getId());
}
private void checkDbStatusValue(Integer custId, String dbStatus) {
SqlRow sqlRow = DB.sqlQuery("select id, status from o_customer where id = ?")
.setParameter(custId)
.findOne();
String status = sqlRow.getString("status");
assertEquals(dbStatus, status);
}
/**
* If we have no changes detected, don't execute an Update and don't update the Version column.
*/
@Test
public void testWithoutChangesAndVersionColumn() {
Customer customer = new Customer();
customer.setName("something");
DB.save(customer);
Customer customerWithoutChanges = DB.find(Customer.class, customer.getId());
DB.save(customerWithoutChanges);
assertThat(customerWithoutChanges.getUpdtime()).isEqualToIgnoringMillis(customer.getUpdtime());
// cleanup
DB.delete(customerWithoutChanges);
}
}
@@ -0,0 +1,29 @@
package org.tests.update;
import io.ebean.BaseTestCase;
import io.ebean.DB;
import org.tests.model.basic.EBasic;
import org.tests.model.basic.EBasic.Status;
import org.junit.jupiter.api.Test;
public class TestUpdatePartialNoVer extends BaseTestCase {
@Test
public void test() {
EBasic b = new EBasic();
b.setName("testpart");
b.setStatus(Status.ACTIVE);
b.setDescription("description");
DB.save(b);
EBasic basic = DB.find(EBasic.class).select("status, name").setId(b.getId()).findOne();
basic.setName("modiName");
DB.save(basic);
}
}
@@ -0,0 +1,52 @@
package org.tests.update.objects;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Version;
@Entity
@Table(name = "e_save_test_d")
public class Child {
@Id
private Long id;
@Version
private long version = 0L;
@OneToOne
private Parent parent;
private boolean testProperty = false;
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 Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
public boolean isTestProperty() {
return testProperty;
}
public void setTestProperty(boolean testProperty) {
this.testProperty = testProperty;
}
}
@@ -0,0 +1,43 @@
package org.tests.update.objects;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Version;
@Entity
@Table(name = "e_save_test_c")
public class Parent {
@Id
private Long id;
@Version
private long version = 0L;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "parent")
private Child child;
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 Child getChild() {
return child;
}
public void setChild(Child child) {
this.child = child;
}
}
@@ -0,0 +1,43 @@
package org.tests.update.objects;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Version;
@Entity
@Table(name = "e_save_test_a")
public class SiblingA {
@Id
private Long id;
@Version
private long version = 0L;
@OneToOne(cascade = CascadeType.ALL, mappedBy = "siblingA")
private SiblingB siblingB;
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 SiblingB getSiblingB() {
return siblingB;
}
public void setSiblingB(SiblingB siblingB) {
this.siblingB = siblingB;
}
}
@@ -0,0 +1,53 @@
package org.tests.update.objects;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Version;
@Entity
@Table(name = "e_save_test_b")
public class SiblingB {
@Id
private Long id;
@Version
private long version = 0L;
@OneToOne(cascade = CascadeType.ALL)
private SiblingA siblingA;
private boolean testProperty = false;
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 SiblingA getSiblingA() {
return siblingA;
}
public void setSiblingA(SiblingA siblingA) {
this.siblingA = siblingA;
}
public boolean isTestProperty() {
return testProperty;
}
public void setTestProperty(boolean testProperty) {
this.testProperty = testProperty;
}
}